1
1
;;; ess-inf.el --- Support for running S as an inferior Emacs process
3
3
;; Copyright (C) 1989-1994 Bates, Kademan, Ritter and Smith
4
;; Copyright (C) 1997-2001 A.J. Rossini <rossini@u.washington.edu>,
5
;; Martin Maechler <maechler@stat.math.ethz.ch>.
4
;; Copyright (C) 1997-1999 A.J. Rossini <rossini@u.washington.edu>,
5
;; Martin Maechler <maechler@stat.math.ethz.ch>.
6
;; Copyright (C) 2000--2004 A.J. Rossini, Rich M. Heiberger, Martin
7
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
7
;; Author: David Smith <dsmith@stats.adelaide.edu.au>
8
;; (now: dsmith@insightful.com)
9
;; Maintainer: A.J. Rossini <rossini@u.washington.edu>
9
;; Original Author: David Smith <dsmith@stats.adelaide.edu.au>
10
10
;; Created: 7 Jan 1994
11
;; Modified: $Date: 2002/06/20 21:52:06 $
12
;; Version: $Revision: 5.78 $
13
;; RCS: $Id: ess-inf.el,v 5.78 2002/06/20 21:52:06 rsparapa Exp $
11
;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
15
13
;; This file is part of ESS
125
125
;;- Is this needed? (no, but it's useful to see them there [MM])
126
126
(set-buffer ess-dribble-buffer)
127
(ess-setq-vars-default ess-customize-alist (current-buffer))
127
;; Hack to work around the following "default" (global) setting of vars:
128
;; make sure our comint-... hack doesn't affect anything else
129
(make-variable-buffer-local 'comint-use-prompt-regexp-instead-of-fields)
130
;; now the abomination:
131
(ess-setq-vars-default ess-customize-alist)
133
(setq-default comint-use-prompt-regexp-instead-of-fields nil); re set HACK!
128
134
;;>> Doesn't set ess-language,
129
135
;;>> => comint-input-sender is not set to 'ess-input- ==> no input echo!
130
136
;;>> => that's why things fail:
131
137
;;>> (ess-setq-vars-local ess-customize-alist (current-buffer))
133
(setq temp-ess-dialect
134
(eval(cdr(assoc 'ess-dialect ess-customize-alist))))
136
(eval(cdr(assoc 'ess-language ess-customize-alist)))))
139
;;MM --- why set them here again when already "(let ..)" above ?
140
;; --> trying without (comment the following 4 lines):
141
;; (setq temp-ess-dialect
142
;; (eval(cdr(assoc 'ess-dialect ess-customize-alist))))
143
;; (setq temp-ess-lang
144
;; (eval(cdr(assoc 'ess-language ess-customize-alist))))
138
147
;; run hooks now, to overwrite the above!
139
148
(run-hooks 'ess-pre-run-hook)
170
179
(memq major-mode '(inferior-ess-mode)))
172
181
(if ess-ask-for-ess-directory
173
(ess-get-directory (directory-file-name defdir))
182
(ess-get-directory (directory-file-name defdir))
175
184
(setq buf (current-buffer))
176
185
(ess-write-to-dribble-buffer
177
(format "(inferior-ess) Method #1 start=%s buf=%s\n" startdir buf)))
186
(format "(inferior-ess) Method #1 start=%s buf=%s\n" startdir buf)))
179
188
;; Not an ESS buffer yet
181
190
(get-buffer buf-name-str))
182
191
(setq buf (get-buffer buf-name-str))
183
192
(ess-write-to-dribble-buffer
184
(format "(inferior-ess) Method #2 buf=%s\n" buf)))
193
(format "(inferior-ess) Method #2 buf=%s\n" buf)))
186
195
;; Ask for transcript file and startdir
187
196
;; FIXME -- this should be in ess-get-transfile
263
272
there is no process NAME)."
265
274
(let* ((proc-name name)
275
(special-display-regexps nil)
276
(special-display-frame-alist inferior-ess-frame-alist)
266
277
(proc (get-process proc-name)))
278
(if inferior-ess-own-frame
279
(setq special-display-regexps '(".")))
267
280
;; If ESS process NAME is running, switch to it
268
281
(if (and proc (comint-check-proc (process-buffer proc)))
269
(switch-to-buffer (process-buffer proc))
282
(pop-to-buffer (process-buffer proc))
270
283
;; Otherwise, crank up a new process
271
284
(let* ((symbol-string
272
285
(concat "inferior-" inferior-ess-program "-args"))
509
531
(set-buffer (process-buffer (get-process proc)))
510
532
(ess-make-buffer-current))
511
(if noswitch nil (switch-to-buffer (process-buffer (get-process proc))))
535
(ess-show-buffer (buffer-name (process-buffer (get-process proc))) t))
514
538
(defun ess-force-buffer-current (prompt &optional force)
515
539
"Make sure the current buffer is attached to an ESS process.
516
If not, or FORCE (prefix argument) is non-nil,
540
If not, or FORCE (prefix argument) is non-nil,
517
541
prompt for a process name with PROMPT.
518
542
`ess-local-process-name' is set to the name of the process selected.
519
543
`ess-dialect' is set to the dialect associated with the process selected."
544
568
(defun ess-switch-to-ESS (eob-p)
545
569
"Switch to the current inferior ESS process buffer.
546
With (prefix) EOB-P non-nil, positions cursor at end of buffer."
570
With (prefix) EOB-P non-nil, positions cursor at end of buffer.
571
This function should follow the description in `ess-show-buffer'
572
for showing the iESS buffer, except that the iESS buffer is also
547
574
(interactive "P")
548
575
(ess-make-buffer-current)
549
576
(if (and ess-current-process-name (get-process ess-current-process-name))
552
(process-buffer (get-process ess-current-process-name)))
578
;; Display the buffer, but don't select it yet.
580
(buffer-name (process-buffer (get-process ess-current-process-name)))
553
582
(if eob-p (goto-char (point-max))))
554
583
(message "No inferior ESS process")
579
608
(if (eq (length ess-process-name-list) 0)
580
609
(setq ess-current-process-name nil)))
611
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
613
;; Something like this almost works, but problems with XEmacs and Emacs
614
;; differing implementations of the args to display-buffer make this
615
;; too tough to pursue. The longer version below works.
616
;; (defun ess-show-buffer (buf)
617
;; "Display the buffer BUF, a string, but do not select it.
618
;; Returns the window corresponding to the buffer."
619
;; ;; On XEmacs, I get an error if third arg to display-buffer is t and
620
;; ;; the BUF is in another frame. Emacs does not have this problem.
621
;; (if (featurep 'xemacs)
622
;; (display-buffer buf nil (get-frame-for-buffer buf))
623
;; (display-buffer buf nil t)))
624
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
625
(defun ess-show-buffer (buf &optional visit)
626
"Ensure the ESS buffer BUF is visible.
627
The buffer, specified as a string, is typically an iESS (e.g. *R*) buffer.
629
This handles several cases:
631
1. If BUF is visible in the current frame, nothing is done.
632
2. If BUF is visible in another frame, then we ensure that frame is
633
visible (it may have been iconified).
634
3. If buffer is not visible in any frame, simply show it in another window
635
in the current frame.
637
Iff VISIT is non-nil, as well as making BUF visible, we also select it
638
as the current buffer."
640
(if (ess-buffer-visible-this-frame buf)
641
;;1. Nothing to do, BUF visible in this frame; just return window
642
;; where this buffer is.
645
;; 2. Maybe BUF visible in another frame.
646
(setq frame (ess-buffer-visible-other-frame buf))
648
;; BUF is visible in frame, so just check frame is raised.
649
(if (not (eq (frame-visible-p frame) t))
650
;; frame is not yet visible, so raise it.
652
;; 3. else BUF not visible in any frame, so show it (but do
653
;; not select it) in another window in current frame.
654
(display-buffer buf)))
655
;; At this stage, the buffer should now be visible on screen,
656
;; although it won't have been made current.
659
;; Need to select the buffer.
661
;; First of all, check case 2 if buffer is in another frame
662
;; but that frame may not be selected.
663
(if (and frame (not (featurep 'xemacs)))
665
;; need to select the frame
667
;; reposition mouse to make frame active.
668
(set-mouse-position (selected-frame) (1- (frame-width)) 0)))
669
(select-window (get-buffer-window buf 0))))))
672
;; The next few functions are copied from my (SJE) iswitchb library.
673
(defun ess-get-bufname (win)
674
"Used by `ess-get-buffers-in-frames' to walk through all windows."
675
(let ((buf (buffer-name (window-buffer win))))
676
(if (not (member buf ess-bufs-in-frame))
677
;; Only add buf if it is not already in list.
678
;; This prevents same buf in two different windows being
679
;; put into the list twice.
680
(setq ess-bufs-in-frame
681
(cons buf ess-bufs-in-frame)))))
683
(defun ess-get-buffers-in-frames (&optional current)
684
"Return the list of buffers that are visible in the current frame.
685
If optional argument CURRENT is given, restrict searching to the
686
current frame, rather than all frames."
687
(let ((ess-bufs-in-frame nil))
688
(walk-windows 'ess-get-bufname nil (if current nil 0))
691
(defun ess-buffer-visible-this-frame (buf)
692
"Return t if BUF is visible in current frame."
693
(member buf (ess-get-buffers-in-frames t)))
695
(defun ess-buffer-visible-other-frame (buf)
696
"Return t if BUF is visible in another frame.
697
Assumes that buffer has not already been in found in current frame."
698
(if (member buf (ess-get-buffers-in-frames))
699
(window-frame (get-buffer-window buf 0))
582
703
; Functions for evaluating code
584
705
(defun ess-ddeclient-p ()
1071
1193
;; Code for GNU Emacs
1072
1194
(setq inferior-ess-mode-map (cons 'keymap comint-mode-map))))
1074
;; Use syntax valid *both* for GNU emacs and Xemacs :
1196
;; Use syntax valid *both* for GNU emacs and XEmacs :
1075
1197
(define-key inferior-ess-mode-map "\r" 'inferior-ess-send-input)
1198
(define-key inferior-ess-mode-map "\C-a" 'comint-bol)
1076
1199
(define-key inferior-ess-mode-map "\M-\r" 'ess-transcript-send-command-and-move)
1077
1200
(define-key inferior-ess-mode-map "\C-c\C-l" 'ess-load-file)
1201
;; the above OVERRIDES comint-dynamic-list-input-ring --> re-assign:
1202
(define-key inferior-ess-mode-map "\C-c\M-l" 'comint-dynamic-list-input-ring)
1078
1203
(define-key inferior-ess-mode-map "\C-c`" 'ess-parse-errors)
1079
1204
(define-key inferior-ess-mode-map "\C-c\C-d" 'ess-dump-object-into-edit-buffer)
1080
1205
(define-key inferior-ess-mode-map "\C-c\C-v" 'ess-display-help-on-object)
1336
1463
;;> As promised, here is a quick hack:
1337
1464
;; ___hack much improved by MM___ , both help(.) and ?... now work
1339
;; rmh: catch page() just like we catch help()
1465
;; FIXME: Note that '??' nicely works in *R*, but
1466
;; 'type ? topic' doesn't use ess-help {but display in *R*}
1340
1467
(defconst inferior-R-1-input-help (format "help *(%s)" ess-help-arg-regexp))
1341
1468
(defconst inferior-R-2-input-help (format "^ *\\? *%s" ess-help-arg-regexp))
1342
(defconst inferior-R-page (format "page *(%s)" ess-help-arg-regexp))
1469
(defconst inferior-R-page (format "^ *page *(%s)" ess-help-arg-regexp))
1344
1471
(defun inferior-R-input-sender (proc string)
1345
1472
;; REALLY only for debugging: this S_L_O_W_S D_O_W_N [here AND below]
1570
1696
"Delete all buffers associated with process %s? "
1573
(mapcar '(lambda (buf)
1575
;; Consider buffers for which
1576
;; ess-local-process-name is the same as
1578
(if (and (not (get-buffer-process buf))
1579
ess-local-process-name
1580
(equal ess-local-process-name
1584
(ess-switch-to-ESS nil)))))
1700
(mapcar '(lambda (buf)
1702
;; Consider buffers for which
1703
;; ess-local-process-name is the same as
1705
(if (and (not (get-buffer-process buf))
1706
ess-local-process-name
1707
(equal ess-local-process-name
1711
(ess-switch-to-ESS nil)))
1586
1713
(defun ess-kill-buffer-function nil
1587
1714
"Function run just before an ESS process buffer is killed."