Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
;;; ess-inf.el --- Support for running S as an inferior Emacs process
2
3
;; Copyright (C) 1989-1994 Bates, Kademan, Ritter and Smith
4
;; Copyright (C) 1997-1999 A.J. Rossini <[email protected]>,
5
;; Martin Maechler <[email protected]>.
6
;; Copyright (C) 2000--2010 A.J. Rossini, Richard M. Heiberger, Martin
7
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
8
;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler,
9
;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu.
10
11
;; Author: David Smith <[email protected]>
12
;; Created: 7 Jan 1994
13
;; Maintainer: ESS-core <[email protected]>
14
15
;; This file is part of ESS
16
17
;; This file is free software; you can redistribute it and/or modify
18
;; it under the terms of the GNU General Public License as published by
19
;; the Free Software Foundation; either version 2, or (at your option)
20
;; any later version.
21
22
;; This file is distributed in the hope that it will be useful,
23
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
;; GNU General Public License for more details.
26
27
;; A copy of the GNU General Public License is available at
28
;; http://www.r-project.org/Licenses/
29
30
;;; Commentary:
31
32
;; Code for handling running ESS processes.
33
34
;;; Code:
35
36
; Requires and autoloads
37
38
;;*;; Requires
39
;; (require 'ess-site)
40
41
;; Byte-compiler, SHUT-UP!
42
(eval-and-compile
43
(require 'ess-utils))
44
(unless (featurep 'xemacs)
45
(require 'newcomment nil t))
46
(require 'comint)
47
(require 'overlay)
48
49
;;; VS: These autoloads are not needed. See coments in ess-mode.el.
50
;;*;; Autoloads
51
;; (autoload 'ess-parse-errors "ess-mode" "(autoload).")
52
;; (autoload 'ess-dump-object-into-edit-buffer "ess-mode" "(autoload).")
53
;; (autoload 'ess-beginning-of-function "ess-mode" "(autoload).")
54
;; (autoload 'ess-end-of-function "ess-mode" "(autoload).")
55
;; (autoload 'ess-display-help-on-object "ess-help" "(autoload).")
56
57
;; (autoload 'ess-extract-word-name "ess-utils" "(autoload).")
58
;; (autoload 'ess-uniq-list "ess-utils" "(autoload).")
59
60
;; (autoload 'ess-transcript-send-command-and-move "ess-trns" "(autoload).")
61
62
;; (autoload 'ess-R-complete-object-name "ess-r-d" "(autoload).")
63
64
(autoload 'ess-eval-region-ddeclient "ess-dde" "(autoload).")
65
(autoload 'ess-eval-linewise-ddeclient "ess-dde" "(autoload).")
66
(autoload 'ess-load-file-ddeclient "ess-dde" "(autoload).")
67
(autoload 'ess-command-ddeclient "ess-dde" "(autoload).")
68
69
(autoload 'tramp-tramp-file-p "tramp" "(autoload).")
70
(autoload 'tramp-file-name-localname "tramp" "(autoload).")
71
(autoload 'tramp-dissect-file-name "tramp" "(autoload).")
72
(autoload 'with-parsed-tramp-file-name "tramp" "(autolaod).")
73
74
;; not really needed as tracebug and developer are loaded in r-d.el
75
(autoload 'ess-tracebug-send-region "ess-tracebug" "(autoload).")
76
(autoload 'ess-developer-send-function "ess-developer" "(autoload).")
77
78
;;*;; Process handling
79
80
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81
;;; In this section:
82
;;;
83
;;; * User commands for starting an ESS process
84
;;; * Functions called at startup
85
;;; * Process handling code
86
;;; * Multiple process implementation
87
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88
89
;;*;; Starting a process
90
91
(defun ess-proc-name (n name)
92
"Return name of process N, as a string, with NAME prepended.
93
If ess-plain-first-buffername, then initial process is number-free."
94
(concat name
95
(if (not (and ess-plain-first-buffername
96
(= n 1))) ; if not both first and plain-first add number
97
(concat ":" (number-to-string n)))))
98
99
(defun inferior-ess (&optional ess-start-args customize-alist no-wait)
100
"Start inferior ESS process.
101
102
Without a prefix argument, starts a new ESS process, or switches
103
to the ESS process associated with the current buffer.
104
With a prefix, starts the process with those args.
105
The current buffer is used if it is an `inferior-ess-mode'
106
or `ess-transcript-mode' buffer.
107
108
If `ess-ask-about-transfile' is non-nil, you will be asked for a
109
transcript file to use. If there is no transcript file, the buffer
110
name will be like *S* or *S2*.
111
112
Takes the program name from the variable `inferior-ess-program'.
113
An initialization file (dumped into the process) is specified by
114
`inferior-ess-start-file', and `inferior-ess-start-args' is used to
115
accompany the call for `inferior-ess-program'.
116
117
When creating a new process, the process buffer replaces the
118
current window if `inferior-ess-same-window' is non-nil.
119
Alternatively, it can appear in its own frame if
120
`inferior-ess-own-frame' is non-nil.
121
122
\(Type \\[describe-mode] in the process buffer for a list of commands.)"
123
124
;; Use the current buffer if it is in inferior-ess-mode or ess-trans-mode
125
;; If not, maybe ask about starting directory and/or transcript file.
126
;; If no transfile, use buffer *S*
127
;;
128
;; This function is primarily used to figure out the Process and
129
;; buffer names to use for inferior-ess.
130
131
;; Once, long ago, it was used for switching buffers, but we don't
132
;; do that any more (at least not from here).
133
134
(interactive)
135
136
(let* ((ess-customize-alist (or customize-alist
137
ess-customize-alist))
138
(temp-ess-dialect (eval (cdr (assoc 'ess-dialect
139
ess-customize-alist))))
140
(temp-ess-lang (eval (cdr (assoc 'ess-language
141
ess-customize-alist)))))
142
143
(run-hooks 'ess-pre-run-hook)
144
(ess-write-to-dribble-buffer
145
(format "(inf-ess 1): lang=%s, dialect=%s, tmp-dialect=%s, buf=%s\n"
146
ess-language ess-dialect temp-ess-dialect (current-buffer)))
147
(let* ((process-environment process-environment)
148
(defdir (or (and ess-directory-function (funcall ess-directory-function))
149
ess-directory default-directory))
150
151
(temp-dialect (if ess-use-inferior-program-name-in-buffer-name ;VS[23-02-2013]: fixme: this should not be here
152
(if (string-equal temp-ess-dialect "R")
153
inferior-R-program-name
154
temp-ess-dialect) ; use temp-ess-dialect
155
; if not R, R program name
156
; otherwise.
157
temp-ess-dialect))
158
(temp-lang temp-ess-lang)
159
(procname (let ((ntry 0) ;; find the next non-existent process N (*R:N*)
160
(done nil))
161
(while (not done)
162
(setq ntry (1+ ntry)
163
done (not
164
(get-process (ess-proc-name
165
ntry
166
temp-dialect)))))
167
(ess-proc-name ntry temp-dialect)))
168
(buf-name-str (funcall ess-gen-proc-buffer-name-function procname))
169
startdir buf method)
170
171
(ess-write-to-dribble-buffer
172
(format "(inf-ess 1.1): procname=%s temp-dialect=%s, buf-name=%s \n"
173
procname temp-dialect buf-name-str))
174
175
(cond
176
;; 1) try to use current buffer, if inferior-ess-mode but no process
177
((and (not (comint-check-proc (current-buffer)))
178
(eq major-mode 'inferior-ess-mode))
179
(setq startdir (if ess-ask-for-ess-directory
180
(ess-get-directory defdir temp-dialect procname)
181
defdir)
182
buf (current-buffer)
183
;; don't change existing buffer name in this case; It is very
184
;; commong to restart the process in the same buffer.
185
buf-name-str (buffer-name)
186
method 1))
187
188
;; 2) Take the *R:N* buffer if already exists (and contains dead proc!)
189
;; fixme: buffer name might have been changed, iterate over all
190
;; inferior-ess buffers
191
((get-buffer buf-name-str)
192
(setq buf (get-buffer buf-name-str)
193
method 2))
194
195
;; 3) Pick up a transcript file or create a new buffer
196
(t
197
(setq startdir (if ess-ask-for-ess-directory
198
(ess-get-directory defdir temp-dialect procname)
199
defdir)
200
buf (if ess-ask-about-transfile
201
(let ((transfilename (read-file-name "Use transcript file (default none):"
202
startdir "")))
203
(if (string= transfilename "")
204
(get-buffer-create buf-name-str)
205
(find-file-noselect (expand-file-name transfilename))))
206
(get-buffer-create buf-name-str))
207
method 3)))
208
209
(ess-write-to-dribble-buffer
210
(format "(inferior-ess) Method #%d start=%s buf=%s\n" method startdir buf))
211
212
(set-buffer buf)
213
;; Now that we have the buffer, set buffer-local variables.
214
(ess-setq-vars-local ess-customize-alist) ; buf)
215
216
;; Write out debug info
217
(ess-write-to-dribble-buffer
218
(format "(inf-ess 2.1): ess-language=%s, ess-dialect=%s buf=%s \n"
219
ess-language ess-dialect (current-buffer)))
220
221
;; initialize.
222
(if startdir (setq default-directory startdir))
223
224
;; the following was part of ess-multi;
225
226
(let* ((ess-directory (or startdir
227
ess-directory))
228
(infargs (or ess-start-args
229
inferior-ess-start-args))
230
(special-display-regexps nil)
231
(special-display-frame-alist inferior-ess-frame-alist)
232
(proc (get-process procname)))
233
(if inferior-ess-own-frame
234
(setq special-display-regexps '(".")))
235
;; If ESS process NAME is running, switch to it
236
(if (and proc (comint-check-proc (process-buffer proc)))
237
;; fixme: when does this happen?
238
(pop-to-buffer (process-buffer proc))
239
240
;; Otherwise, crank up a new process
241
(let* ((symbol-string
242
(concat "inferior-" inferior-ess-program "-args"))
243
(switches-symbol (intern-soft symbol-string))
244
(switches
245
(if (and switches-symbol (boundp switches-symbol))
246
(symbol-value switches-symbol))))
247
(set-buffer buf)
248
(inferior-ess-mode)
249
(ess-write-to-dribble-buffer
250
(format "(inferior-ess (post inf-ess): start-args=%s, comint-echoes=%s\n"
251
infargs comint-process-echoes))
252
(setq ess-local-process-name procname)
253
(goto-char (point-max))
254
;; load past history
255
256
;; Set up history file
257
(if ess-history-file
258
(if (eq t ess-history-file)
259
(set (make-variable-buffer-local 'ess-history-file)
260
(concat "." ess-dialect "history"))
261
;; otherwise must be a string "..."
262
(unless (stringp ess-history-file)
263
(error "`ess-history-file' must be nil, t, or a string"))))
264
265
(when ess-history-file
266
(setq comint-input-ring-file-name
267
(expand-file-name ess-history-file
268
(or ess-history-directory ess-directory)))
269
(comint-read-input-ring))
270
271
;; create and run process.
272
(set-buffer
273
(if switches
274
(inferior-ess-make-comint buf-name-str
275
procname
276
infargs
277
switches)
278
(inferior-ess-make-comint buf-name-str
279
procname
280
infargs)))
281
282
;; Set the process sentinel to save the history
283
(set-process-sentinel (get-process procname) 'ess-process-sentinel)
284
;; Add this process to ess-process-name-list, if needed
285
(let ((conselt (assoc procname ess-process-name-list)))
286
(if conselt nil
287
(setq ess-process-name-list
288
(cons (cons procname nil) ess-process-name-list))))
289
(ess-make-buffer-current)
290
(goto-char (point-max))
291
(setq ess-sl-modtime-alist nil)
292
293
;; Add the process filter to catch certain output.
294
(set-process-filter (get-process procname)
295
'inferior-ess-output-filter)
296
;; (inferior-ess-wait-for-prompt)
297
(inferior-ess-mark-as-busy (get-process procname))
298
(process-send-string (get-process procname) "\n") ;; to be sure we catch the prompt if user comp is super-duper fast.
299
(unless no-wait
300
(ess-write-to-dribble-buffer "(inferior-ess: waiting for process to start (before hook)\n")
301
(ess-wait-for-process (get-process procname) nil 0.01))
302
303
;; arguments cache
304
(ess-process-put 'funargs-cache (make-hash-table :test 'equal))
305
(ess-process-put 'funargs-pre-cache nil)
306
307
;; set accumulation buffer name (buffer to cache output for faster display)
308
(process-put (get-process procname) 'accum-buffer-name
309
(format " *%s:accum*" procname))
310
311
312
;; don't font-lock strings over process prompt
313
(set (make-local-variable 'syntax-begin-function)
314
#'inferior-ess-goto-last-prompt-if-close)
315
(set (make-local-variable 'font-lock-fontify-region-function)
316
#'inferior-ess-fontify-region)
317
318
(run-hooks 'ess-post-run-hook)
319
320
;; EXTRAS
321
(ess-load-extras t)
322
;; user initialization can take some time ...
323
(unless no-wait
324
(ess-write-to-dribble-buffer "(inferior-ess 3): waiting for process after hook")
325
(ess-wait-for-process (get-process procname))))
326
327
(with-current-buffer buf
328
(rename-buffer buf-name-str t))
329
330
(if (and inferior-ess-same-window (not inferior-ess-own-frame))
331
(switch-to-buffer buf)
332
(pop-to-buffer buf)))))))
333
334
335
(defvar inferior-ess-objects-command nil
336
"The language/dialect specific command for listing objects.
337
It is initialized from the corresponding inferior-<lang>-objects-command
338
and then made buffer local."); and the *-<lang>-* ones are customized!
339
(make-variable-buffer-local 'inferior-ess-objects-command)
340
341
(defvar ess-save-lastvalue-command nil
342
"The command to save the last value. See S section for more details.
343
Default depends on the ESS language/dialect and hence made buffer local")
344
(make-variable-buffer-local 'ess-save-lastvalue-command)
345
346
(defvar ess-retr-lastvalue-command nil
347
"The command to retrieve the last value. See S section for more details.
348
Default depends on the ESS language/dialect and hence made buffer local")
349
(make-variable-buffer-local 'ess-retr-lastvalue-command)
350
351
;;; A note on multiple processes: the following variables
352
;;; ess-local-process-name
353
;;; ess-sl-modtime-alist
354
;;; ess-prev-load-dir/file
355
;;; ess-directory
356
;;; ess-object-list
357
;;; are specific to each ess-process and are buffer-local variables
358
;;; local to the ESS process buffer. If required, these variables should
359
;;; be accessed with the function ess-get-process-variable
360
361
362
(defun inferior-ess-goto-last-prompt-if-close ()
363
"If any prompt has been found on current line, go to previous primary prompt and return the position.
364
Otherwise stay at current position and return nil "
365
366
(let ((new-point (save-excursion
367
(beginning-of-line)
368
(if (looking-at inferior-ess-primary-prompt)
369
(point)
370
(when (and inferior-ess-secondary-prompt
371
(looking-at inferior-ess-secondary-prompt))
372
(re-search-backward (concat "^" inferior-ess-primary-prompt))
373
(point))))))
374
(when new-point
375
(goto-char new-point))))
376
377
(defvar compilation--parsed)
378
(defun inferior-ess-fontify-region (beg end &optional verbose)
379
"Fontify output by output within the beg-end region to avoid
380
fontification spilling over prompts."
381
(let* ((buffer-undo-list t)
382
(inhibit-point-motion-hooks t)
383
(font-lock-dont-widen t)
384
(buff (current-buffer))
385
(pos (or (inferior-ess-goto-last-prompt-if-close)
386
beg))
387
(pos2))
388
;; Font lock seems to skip regions for unlear reason when
389
;; font-lock-dont-widen is t. This in turn screws compilation marker and
390
;; makes compilation--parse-region think that it parsed stuff that it
391
;; didn't. So reset it each time.
392
(setq compilation--parsed -1)
393
(with-silent-modifications
394
;; (dbg pos end)
395
;; (font-lock-unfontify-region pos end)
396
(while (< pos end)
397
(goto-char pos)
398
(comint-next-prompt 1)
399
(setq pos2 (min (point) end))
400
(if nil
401
(font-lock-default-fontify-region pos pos2 verbose)
402
;; Some error locations are not fontified with with narrowing. Especiall those from gcc.
403
;; What on earth is goin on?
404
(save-restriction
405
(narrow-to-region pos pos2)
406
(font-lock-default-fontify-region pos pos2 verbose)))
407
(setq pos pos2)))))
408
409
(defun ess-gen-proc-buffer-name:simple (proc-name)
410
"Function to generate buffer name by wrapping PROC-NAME in *proc-name*"
411
(format "*%s*" proc-name))
412
413
(defun ess-gen-proc-buffer-name:directory (proc-name)
414
"Function to generate buffer name by wrapping PROC-NAME in
415
*proc-name:dir-name* where dir-name is a short directory name."
416
(format "*%s:%s*" proc-name (file-name-nondirectory
417
(directory-file-name default-directory))))
418
419
(defun ess-gen-proc-buffer-name:abbr-long-directory (proc-name)
420
"Function to generate buffer name by wrapping PROC-NAME in
421
*proc-name:abbreviated-long-dir-name*, where
422
abbreviated-long-dir-name is an abbreviated full directory name.
423
Abbreviation performed by `abbreviate-file-name'.
424
"
425
(format "*%s:%s*" proc-name (abbreviate-file-name default-directory)))
426
427
(defun inferior-ess-set-status (proc string &optional no-timestamp)
428
"Internal function to set the satus of the PROC
429
If no-timestamp, don't set the last-eval timestamp.
430
Return the 'busy state."
431
;; todo: do it in one search, use starting position, use prog1
432
(let ((busy (not (string-match (concat "\\(" inferior-ess-primary-prompt "\\)\\'") string))))
433
(process-put proc 'busy-end? (and (not busy)
434
(process-get proc 'busy)))
435
(when (not busy)
436
(process-put proc 'running-async? nil))
437
(process-put proc 'busy busy)
438
(process-put proc 'sec-prompt
439
(when inferior-ess-secondary-prompt
440
(string-match (concat "\\(" inferior-ess-secondary-prompt "\\)\\'") string)))
441
(unless no-timestamp
442
(process-put proc 'last-eval (current-time)))
443
busy))
444
445
(defun inferior-ess-mark-as-busy (proc)
446
(process-put proc 'busy t)
447
(process-put proc 'sec-prompt nil))
448
449
(defun inferior-ess-run-callback (proc string)
450
;; callback is stored in 'callbacks proc property. Callbacks is a list that
451
;; can contain either functions to be called with two artuments PROC and
452
;; STRING, or cons cells of the form (func . suppress). If SUPPRESS is non-nil
453
;; next process output will be suppressed.
454
(unless (process-get proc 'busy)
455
;; only one callback is implemented for now
456
(let* ((cb (car (process-get proc 'callbacks)))
457
(listp (not (functionp cb)))
458
(suppress (and listp (consp cb) (cdr cb)))
459
(cb (if (and listp (consp cb))
460
(car cb)
461
cb)))
462
(when cb
463
(when ess-verbose
464
(ess-write-to-dribble-buffer "executing callback ...\n"))
465
(when suppress
466
(process-put proc 'suppress-next-output? t))
467
(process-put proc 'callbacks nil)
468
(condition-case err
469
(funcall cb proc string)
470
(error (message "%s" (error-message-string err))))))))
471
472
(defun ess--if-verbose-write-process-state (proc string &optional filter)
473
(ess-if-verbose-write
474
(format "\n%s:
475
--> busy:%s busy-end:%s sec-prompt:%s interruptable:%s <--
476
--> running-async:%s callback:%s suppress-next-output:%s <--
477
--> dbg-active:%s is-recover:%s <--
478
--> string:%s\n"
479
(or filter "NORMAL-FILTER")
480
(process-get proc 'busy)
481
(process-get proc 'busy-end?)
482
(process-get proc 'sec-prompt)
483
(process-get proc 'interruptable?)
484
(process-get proc 'running-async?)
485
(if (process-get proc 'callbacks) "yes")
486
(process-get proc 'suppress-next-output?)
487
(process-get proc 'dbg-active)
488
(process-get proc 'is-recover)
489
(if (> (length string) 150)
490
(format "%s .... %s" (substring string 0 50) (substring string -50))
491
string))))
492
493
(defun inferior-ess-output-filter (proc string)
494
"Standard output filter for the inferior ESS process.
495
Ring Emacs bell if process output starts with an ASCII bell, and pass
496
the rest to `comint-output-filter'.
497
Taken from octave-mod.el."
498
(inferior-ess-set-status proc string)
499
(ess--if-verbose-write-process-state proc string)
500
(inferior-ess-run-callback proc string)
501
(if (process-get proc 'suppress-next-output?)
502
;; works only for surpressing short output, for time being is enough (for callbacks)
503
(process-put proc 'suppress-next-output? nil)
504
(comint-output-filter proc (inferior-ess-strip-ctrl-g string))
505
(ess--show-process-buffer-on-error string proc)))
506
507
508
(defun ess--show-process-buffer-on-error (string proc)
509
(let ((case-fold-search nil))
510
(when (string-match "Error\\(:\\| +in\\)" string)
511
(ess-show-buffer (process-buffer proc)))))
512
513
(defun inferior-ess-strip-ctrl-g (string)
514
"Strip leading `^G' character.
515
If STRING starts with a `^G', ring the Emacs bell and strip it.
516
Depending on the value of `visible-bell', either the frame will
517
flash or you'll hear a beep. Taken from octave-mod.el."
518
(if (string-match "^\a" string)
519
(progn
520
(ding)
521
(setq string (substring string 1))))
522
string)
523
524
525
(defun ess-process-sentinel (proc message)
526
"Sentinel for use with ESS processes.
527
This marks the process with a message, at a particular time point."
528
(save-excursion
529
(setq message (substring message 0 -1)) ; strip newline
530
(set-buffer (process-buffer proc))
531
(comint-write-input-ring)
532
(goto-char (point-max))
533
(insert-before-markers
534
(format "\nProcess %s %s at %s\n"
535
(process-name proc) message (current-time-string)))))
536
537
(defun inferior-ess-make-comint (bufname
538
procname
539
infargs
540
&rest switches)
541
"Make an S comint process in buffer BUFNAME with process PROCNAME."
542
;;; This function is a modification of make-comint from the comint.el
543
;;; code of Olin Shivers.
544
(let* ((buffer (get-buffer-create bufname))
545
(proc (get-process procname)))
546
;; If no process, or nuked process, crank up a new one and put buffer in
547
;; comint mode. Otherwise, leave buffer and existing process alone.
548
(cond ((or (not proc) (not (memq (process-status proc) '(run stop))))
549
(with-current-buffer buffer
550
(if ess-directory (setq default-directory ess-directory))
551
(if (eq (buffer-size) 0) nil
552
(goto-char (point-max))
553
(insert "\^L\n"))) ; page boundaries = Interactive sessions
554
(let ((process-environment
555
(nconc
556
(list "STATATERM=emacs"
557
(format "PAGER=%s" inferior-ess-pager))
558
process-environment))
559
(tramp-remote-process-environment
560
(nconc ;; it contains a pager already, so append
561
(when (boundp 'tramp-remote-process-environment)
562
(copy-sequence tramp-remote-process-environment))
563
(list "STATATERM=emacs"
564
(format "PAGER=%s" inferior-ess-pager)))))
565
(ess-write-to-dribble-buffer "Making Process...")
566
(ess-write-to-dribble-buffer
567
(format "Buf %s, :Proc %s, :Prog %s\n :Args= %s\nStart File=%s\n"
568
buffer
569
procname
570
inferior-ess-program
571
infargs
572
inferior-ess-start-file))
573
(comint-exec buffer
574
procname
575
inferior-ess-program
576
inferior-ess-start-file
577
(ess-line-to-list-of-words
578
infargs)))))
579
buffer))
580
581
582
;;*;; Requester functions called at startup
583
584
(defun ess-get-directory (default dialect procname)
585
(let ((prog-version (cond ((string= dialect "R")
586
(concat ", " inferior-R-version)) ; notably for the R-X.Y versions
587
(inferior-ess-program
588
(concat ", " inferior-ess-program ))
589
(t ""))))
590
(ess-prompt-for-directory
591
(directory-file-name default)
592
(format "ESS (*%s*%s) starting data directory? "
593
procname prog-version)
594
;; (format "ESS [%s {%s(%s)}: '%s'] starting data directory? "
595
;; ;;FIXME: maybe rather tmp-dialect (+ evt drop ess-language?)?
596
;; procname ess-language ess-dialect prog-version)
597
)))
598
599
600
(defun ess-prompt-for-directory (default prompt)
601
"`prompt' for a directory, using `default' as the usual."
602
(let* ((def-dir (file-name-as-directory default))
603
(the-dir (expand-file-name
604
(file-name-as-directory
605
(read-directory-name prompt def-dir def-dir t nil)))))
606
(if (file-directory-p the-dir) nil
607
(error "%s is not a valid directory" the-dir))
608
the-dir))
609
610
611
;;*;; General process handling code
612
(defmacro with-ess-process-buffer (no-error &rest body)
613
"Execute BODY with current-buffer set to the process buffer of ess-current-process-name.
614
If NO-ERROR is t don't trigger error when there is not current
615
process.
616
617
Symbol *proc* is bound to the current process during the evaluation of BODY."
618
(declare (indent 1))
619
`(let ((*proc* (and ess-local-process-name (get-process ess-local-process-name))))
620
(if *proc*
621
(with-current-buffer (process-buffer *proc*)
622
,@body)
623
(unless ,no-error
624
(error "No current ESS process")))))
625
626
(defmacro ess-with-current-buffer (buffer &rest body)
627
"Like `with-current-buffer' but with transfer of some essential
628
local ESS vars like `ess-local-process-name'"
629
(declare (indent 1))
630
(let ((lpn (make-symbol "lpn"))
631
(alist (make-symbol "alist")))
632
`(let ((,lpn ess-local-process-name)
633
(,alist ess-local-customize-alist))
634
(with-current-buffer ,buffer
635
(ess-setq-vars-local (eval ,alist))
636
(setq ess-local-process-name ,lpn)
637
,@body))))
638
639
(dolist (mode '(emacs-lisp-mode lisp-interaction-mode))
640
(font-lock-add-keywords
641
mode
642
'(("(\\(ess-with-current-buffer\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)"
643
(1 font-lock-keyword-face)
644
(2 font-lock-variable-name-face)))))
645
646
(defun ess-get-process (&optional name use-another)
647
"Return the ESS process named by NAME. If USE-ANOTHER is non-nil,
648
and the process NAME is not running (anymore), try to connect to another if
649
there is one. By default (USE-ANOTHER is nil), the connection to another
650
process happens interactively (when possible)."
651
(setq name (or name ess-local-process-name))
652
(if (null name) ; should almost never happen at this point
653
(error "No ESS process is associated with this buffer now"))
654
(update-ess-process-name-list)
655
(if (assoc name ess-process-name-list)
656
(get-process name)
657
;; else :
658
;; was (error "Process %s is not running" name)
659
(ess-write-to-dribble-buffer
660
(format "ess-get-process: process '%s' not running" name))
661
(if (= 0 (length ess-process-name-list))
662
(save-current-buffer
663
(ess-write-to-dribble-buffer
664
(format " .. restart proc %s for language %s (buf %s)\n"
665
name ess-language (current-buffer)))
666
(message "trying to (re)start process %s for language %s ..."
667
name ess-language)
668
(ess-start-process-specific ess-language ess-dialect)
669
;; and return the process: "call me again"
670
(ess-get-process name))
671
672
;; else: there are other running processes
673
(if use-another ; connect to another running process : the first one
674
(let ((other-name (car (elt ess-process-name-list 0))))
675
;; "FIXME": try to find the process name that matches *closest*
676
(message "associating with *other* process '%s'" other-name)
677
(ess-get-process other-name))
678
;; else
679
(ding)
680
(if (yes-or-no-p
681
(format "Process %s is not running, but others are. Switch? " name))
682
(progn
683
(ess-force-buffer-current
684
(concat ess-dialect " process to use: ") 'force)
685
(ess-get-process ess-current-process-name))
686
(error "Process %s is not running" name))))))
687
688
689
;; (defun inferior-ess-wait-for-prompt ()
690
;; "Wait until the ESS process is ready for input."
691
;; (let* ((cbuffer (current-buffer))
692
;; (sprocess (ess-get-process ess-current-process-name))
693
;; (sbuffer (process-buffer sprocess))
694
;; (r nil)
695
;; (timeout 0))
696
;; (set-buffer sbuffer)
697
;; (while (progn
698
;; (if (not (eq (process-status sprocess) 'run))
699
;; (ess-error "ESS process has died unexpectedly.")
700
;; (if (> (setq timeout (1+ timeout)) ess-loop-timeout)
701
;; (ess-error "Timeout waiting for prompt. Check inferior-ess-prompt or ess-loop-timeout."))
702
;; (accept-process-output)
703
;; (goto-char (point-max))
704
;; (beginning-of-line); bol ==> no need for "^" in *-prompt! (MM?)
705
;; ;; above, except for Stata, which has "broken" i/o,
706
;; ;; sigh... (AJR)
707
;; (setq r (looking-at inferior-ess-prompt))
708
;; (not (or r (looking-at ".*\\?\\s *"))))))
709
;; (goto-char (point-max))
710
;; (set-buffer cbuffer)
711
;; (symbol-value r)))
712
713
;;--- Unfinished idea (ESS-help / R-help ) -- probably not worth it...
714
;;- (defun ess-set-inferior-program-name (filename)
715
;;- "Allows to set or change `inferior-ess-program', the program (file)name."
716
;;- (interactive "fR executable (script) file: ")
717
;;- ;; "f" : existing file {file name completion} !
718
;;- (setq inferior-ess-program filename))
719
;; the inferior-ess-program is initialized in the customize..alist,
720
;; e.g. from inferior-R-program-name ... --> should change rather these.
721
;; However these really depend on the current ess-language!
722
;; Plan: 1) must know and use ess-language
723
;; 2) change the appropriate inferior-<ESSlang>-program-name
724
;; (how?) in R/S : assign(paste("inferior-",ESSlang,"-p...."), filename))
725
726
;;*;; Multiple process handling code
727
728
(defun ess-make-buffer-current nil
729
"Make the process associated with the current buffer the current ESS process.
730
Returns the name of the process, or nil if the current buffer has none."
731
(update-ess-process-name-list)
732
;; (if ess-local-process-name
733
;; (setq ess-current-process-name ess-local-process-name))
734
ess-local-process-name)
735
736
(defun ess-get-process-variable (var)
737
"Return the variable VAR (symbol) local to ESS process called NAME (string)."
738
(buffer-local-value var (process-buffer (ess-get-process ess-local-process-name))))
739
740
(defun ess-set-process-variable (var val)
741
"Set variable VAR (symbol) local to ESS process called NAME (string) to VAL."
742
(with-current-buffer (process-buffer (ess-get-process ess-local-process-name))
743
(set var val)))
744
745
;; emacs 23 compatibility
746
(unless (fboundp 'process-live-p)
747
(defun process-live-p (process)
748
"Returns non-nil if PROCESS is alive.
749
A process is considered alive if its status is `run', `open',
750
`listen', `connect' or `stop'."
751
(memq (process-status process)
752
'(run open listen connect stop))))
753
754
(defun ess-process-live-p ()
755
"Check if the local ess process is alive.
756
Return nil if current buffer has no associated process, or
757
process was killed."
758
(and ess-local-process-name
759
(let ((proc (get-process ess-local-process-name)))
760
(and (processp proc)
761
(process-live-p proc)))))
762
763
(defun ess-process-get (propname)
764
"Return the variable PROPNAME (symbol) from the plist of the
765
current ESS process."
766
(process-get (get-process ess-local-process-name) propname))
767
768
(defun ess-process-put (propname value)
769
"Set the variable PROPNAME (symbol) to VALUE in the plist of
770
the current ESS process."
771
(process-put (get-process ess-local-process-name) propname value))
772
773
(defun ess-start-process-specific (language dialect)
774
"Start an ESS process typically from a language-specific buffer, using
775
LANGUAGE (and DIALECT)."
776
777
(unless dialect
778
(error "The value of `dialect' is nil"))
779
780
(save-current-buffer
781
(let ((dsymb (intern dialect)))
782
(ess-write-to-dribble-buffer
783
(format " ..start-process-specific: lang:dialect= %s:%s, current-buf=%s\n"
784
language dialect (current-buffer)))
785
(cond ;; ((string= dialect "R") (R))
786
;; ((string= language "S") ;
787
;; (message "ESS process not running, trying to start R, since language = 'S")
788
;; (R))
789
;; ((string= dialect STA-dialect-name) (stata))
790
;;general case
791
((fboundp dsymb)
792
(funcall dsymb))
793
(t ;; else: ess-dialect is not a function
794
795
;; Typically triggered from
796
;; ess-force-buffer-current("Process to load into: ")
797
;; \--> ess-request-a-process("Process to load into: " no-switch)
798
(error "No ESS processes running; not yet implemented to start (%s,%s)"
799
language dialect)))
800
;; save excursion is not working here !!! bad bad bad !!
801
)))
802
803
(defun ess-request-a-process (message &optional noswitch ask-if-1)
804
"Ask for a process, and make it the current ESS process.
805
If there is exactly one process, only ask if ASK-IF-1 is non-nil.
806
Also switches to the process buffer unless NOSWITCH is non-nil. Interactively,
807
NOSWITCH can be set by giving a prefix argument.
808
Returns the name of the selected process."
809
(interactive
810
(list "Switch to which ESS process? " current-prefix-arg))
811
; prefix sets 'noswitch
812
(ess-write-to-dribble-buffer "ess-request-a-process: {beginning}\n")
813
(update-ess-process-name-list)
814
815
(setq ess-dialect
816
(or ess-dialect (ess-completing-read
817
"Set `ess-dialect'"
818
(delete-dups (list "R" "S+" S+-dialect-name
819
"stata" STA-dialect-name
820
"julia" "SAS" "XLS" "ViSta")))))
821
822
(let* ((pname-list (delq nil ;; keep only those mathing dialect
823
(append
824
(mapcar (lambda (lproc)
825
(and (equal ess-dialect
826
(buffer-local-value
827
'ess-dialect
828
(process-buffer (get-process (car lproc)))))
829
(not (equal ess-local-process-name (car lproc)))
830
(car lproc)))
831
ess-process-name-list)
832
;; append local only if running
833
(when (assoc ess-local-process-name ess-process-name-list)
834
(list ess-local-process-name)))))
835
(num-processes (length pname-list))
836
(inferior-ess-same-window nil) ;; this should produce the inferior process in other window
837
(auto-started?))
838
(if (or (= 0 num-processes)
839
(and (= 1 num-processes)
840
(not (equal ess-dialect ;; don't auto connect if from different dialect
841
(buffer-local-value
842
'ess-dialect
843
(process-buffer (get-process
844
(car pname-list))))))))
845
;; try to start "the appropriate" process
846
(progn
847
(ess-write-to-dribble-buffer
848
(concat " ... request-a-process:\n "
849
(format
850
"major mode %s; current buff: %s; ess-language: %s, ess-dialect: %s\n"
851
major-mode (current-buffer) ess-language ess-dialect)))
852
(ess-start-process-specific ess-language ess-dialect)
853
(ess-write-to-dribble-buffer
854
(format " ... request-a-process: buf=%s\n" (current-buffer)))
855
(setq num-processes 1
856
pname-list (car ess-process-name-list)
857
auto-started? t)))
858
;; now num-processes >= 1 :
859
(let* ((proc-buffers (mapcar (lambda (lproc)
860
(buffer-name (process-buffer (get-process lproc))))
861
pname-list))
862
(proc
863
(if (or auto-started?
864
(and (not ask-if-1) (= 1 num-processes)))
865
(progn
866
(message "using process '%s'" (car proc-buffers))
867
(car pname-list))
868
;; else
869
(unless (and ess-current-process-name
870
(get-process ess-current-process-name))
871
(setq ess-current-process-name nil))
872
(when message
873
(setq message (replace-regexp-in-string ": +\\'" "" message))) ;; <- why is this here??
874
;; ask for buffer name not the *real* process name:
875
(let ((buf (ess-completing-read message (append proc-buffers (list "*new*")) nil t nil nil)))
876
(if (equal buf "*new*")
877
(progn
878
(ess-start-process-specific ess-language ess-dialect) ;; switches to proc-buff
879
(caar ess-process-name-list))
880
(process-name (get-buffer-process buf))
881
))
882
)))
883
(if noswitch
884
(pop-to-buffer (current-buffer)) ;; VS: this is weired, but is necessary
885
(pop-to-buffer (buffer-name (process-buffer (get-process proc))) t))
886
proc)))
887
888
889
(defun ess-force-buffer-current (&optional prompt force no-autostart ask-if-1)
890
"Make sure the current buffer is attached to an ESS process.
891
If not, or FORCE (prefix argument) is non-nil, prompt for a
892
process name with PROMPT. If NO-AUTOSTART is nil starts the new
893
process if process associated with current buffer has
894
died. `ess-local-process-name' is set to the name of the process
895
selected. `ess-dialect' is set to the dialect associated with
896
the process selected. ASK-IF-1 asks user for the process, even if
897
there is only one process running."
898
(interactive
899
(list (concat ess-dialect " process to use: ") current-prefix-arg nil))
900
;; fixme: why the above interactive is not working in emacs 24?
901
(setq prompt (or prompt "Process to use: "))
902
(let ((proc-name (ess-make-buffer-current)))
903
(if (and (not force) proc-name (get-process proc-name))
904
nil ; do nothing
905
;; Make sure the source buffer is attached to a process
906
(if (and ess-local-process-name (not force) no-autostart)
907
(error "Process %s has died" ess-local-process-name)
908
;; ess-local-process-name is nil -- which process to attach to
909
(let ((proc (ess-request-a-process prompt 'no-switch ask-if-1))
910
temp-ess-help-filetype dialect)
911
(with-current-buffer (process-buffer (get-process proc))
912
(setq temp-ess-help-filetype inferior-ess-help-filetype))
913
(setq ess-local-process-name proc)
914
(setq inferior-ess-help-filetype temp-ess-help-filetype)
915
)))))
916
917
(defun ess-switch-process ()
918
"Force a switch to a new underlying process."
919
(interactive)
920
(ess-force-buffer-current "Process to use: " 'force nil 'ask-if-1))
921
922
(defun ess-get-next-available-process (&optional dialect ignore-busy)
923
"Return first availabe (aka not busy) process of dialect DIALECT.
924
DIALECT defaults to the local value of ess-dialect. Return nil if
925
no such process has been found."
926
(setq dialect (or dialect ess-dialect))
927
(when dialect
928
(let (proc)
929
(catch 'found
930
(dolist (p (cons ess-local-process-name
931
(mapcar 'car ess-process-name-list)))
932
(when p
933
(setq proc (get-process p))
934
(when (and proc
935
(process-live-p proc)
936
(equal dialect
937
(buffer-local-value 'ess-dialect (process-buffer proc)))
938
(or ignore-busy
939
(not (process-get proc 'busy))))
940
(throw 'found proc))))))))
941
942
943
;;*;;; Commands for switching to the process buffer
944
945
(defun ess-switch-to-ESS (eob-p)
946
"Switch to the current inferior ESS process buffer.
947
With (prefix) EOB-P non-nil, positions cursor at end of buffer.
948
This function should follow the description in `ess-show-buffer'
949
for showing the iESS buffer, except that the iESS buffer is also
950
made current."
951
(interactive "P")
952
(ess-force-buffer-current)
953
(if (and ess-current-process-name (get-process ess-current-process-name))
954
(progn
955
;; Display the buffer, but don't select it yet.
956
(ess-show-buffer
957
(buffer-name (process-buffer (get-process ess-current-process-name)))
958
t)
959
(if eob-p (goto-char (point-max))))
960
(message "No inferior ESS process")
961
(ding)))
962
963
(defun ess-switch-to-ESS-deprecated (eob-p)
964
(interactive "P")
965
(ess-switch-to-ESS eob-p)
966
(message "C-c C-y is deprecated, use C-c C-z instead (ess-switch-to-inferior-or-script-buffer)"))
967
968
969
(defun ess-switch-to-end-of-ESS ()
970
"Switch to the end of the inferior ESS process buffer."
971
(interactive)
972
(ess-switch-to-ESS t))
973
974
(defun ess-switch-to-inferior-or-script-buffer (toggle-eob)
975
"If in script, switch to the iESS. If in iESS switch to most recent script buffer.
976
977
This is a single-key command. Assuming that it is bound to C-c C-z,
978
you can navigate back and forth between iESS and script buffer
979
with C-c C-z C-z C-z ...
980
981
If variable `ess-switch-to-end-of-proc-buffer' is t (the default)
982
this function switches to the end of process buffer.
983
984
If TOGGLE-EOB is given, the value of
985
`ess-switch-to-end-of-proc-buffer' is toggled.
986
"
987
(interactive "P")
988
(let ((map (make-sparse-keymap))
989
(EOB (if toggle-eob
990
(not ess-switch-to-end-of-proc-buffer)
991
ess-switch-to-end-of-proc-buffer)))
992
(define-key map (vector last-command-event)
993
(lambda (ev eob) (interactive)
994
(if (not (eq major-mode 'inferior-ess-mode))
995
(ess-switch-to-ESS eob)
996
(let ((dialect ess-dialect)
997
(loc-proc-name ess-local-process-name)
998
(blist (cdr (buffer-list))))
999
(while (and blist
1000
(with-current-buffer (car blist)
1001
(not (or (and (eq major-mode 'ess-mode)
1002
(equal dialect ess-dialect)
1003
(null ess-local-process-name))
1004
(and (eq major-mode 'ess-mode)
1005
(equal loc-proc-name ess-local-process-name))
1006
))))
1007
(pop blist))
1008
(if blist
1009
(ess-show-buffer (car blist) t)
1010
(message "Found no buffers for ess-dialect %s associated with process %s"
1011
dialect loc-proc-name)))
1012
)))
1013
(ess--execute-electric-command map nil nil nil EOB)))
1014
1015
1016
(defun ess-get-process-buffer (&optional name)
1017
"Return the buffer associated with the ESS process named by NAME."
1018
(process-buffer (ess-get-process (or name ess-local-process-name))))
1019
1020
(defun update-ess-process-name-list ()
1021
"Remove names with no process."
1022
(let (defunct)
1023
(dolist (conselt ess-process-name-list)
1024
(let ((proc (get-process (car conselt))))
1025
(unless (and proc (eq (process-status proc) 'run))
1026
(push conselt defunct))))
1027
(dolist (pointer defunct)
1028
(setq ess-process-name-list (delq pointer ess-process-name-list))))
1029
(if (eq (length ess-process-name-list) 0)
1030
(setq ess-current-process-name nil)))
1031
1032
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1033
;; ess-show-buffer
1034
;; Something like this almost works, but problems with XEmacs and Emacs
1035
;; differing implementations of the args to display-buffer make this
1036
;; too tough to pursue. The longer version below works.
1037
;; (defun ess-show-buffer (buf)
1038
;; "Display the buffer BUF, a string, but do not select it.
1039
;; Returns the window corresponding to the buffer."
1040
;; ;; On XEmacs, I get an error if third arg to display-buffer is t and
1041
;; ;; the BUF is in another frame. Emacs does not have this problem.
1042
;; (if (featurep 'xemacs)
1043
;; (display-buffer buf nil (get-frame-for-buffer buf))
1044
;; (display-buffer buf nil t)))
1045
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1046
(defun ess-show-buffer (buf &optional visit)
1047
"Ensure the ESS buffer BUF is visible.
1048
The buffer, specified as a string, is typically an iESS (e.g. *R*) buffer.
1049
1050
This handles several cases:
1051
1052
1. If BUF is visible in the current frame, nothing is done.
1053
2. If BUF is visible in another frame, then we ensure that frame is
1054
visible (it may have been iconified).
1055
3. If buffer is not visible in any frame, simply show it in another window
1056
in the current frame.
1057
1058
If VISIT is non-nil, as well as making BUF visible, we also select it
1059
as the current buffer."
1060
(let ( (frame))
1061
(if (ess-buffer-visible-this-frame buf)
1062
;;1. Nothing to do, BUF visible in this frame; just return window
1063
;; where this buffer is.
1064
t
1065
1066
;; 2. Maybe BUF visible in another frame.
1067
(setq frame (ess-buffer-visible-other-frame buf))
1068
(if frame
1069
;; BUF is visible in frame, so just check frame is raised.
1070
(if (not (eq (frame-visible-p frame) t))
1071
;; frame is not yet visible, so raise it.
1072
(raise-frame frame))
1073
;; 3. else BUF not visible in any frame, so show it (but do
1074
;; not select it) in another window in current frame.
1075
(display-buffer buf)))
1076
;; At this stage, the buffer should now be visible on screen,
1077
;; although it won't have been made current.
1078
(when visit
1079
;; Need to select the buffer.
1080
;;
1081
;; First of all, check case 2 if buffer is in another frame
1082
;; but that frame may not be selected.
1083
(if frame
1084
(ess-select-frame-set-input-focus frame))
1085
(select-window (get-buffer-window buf 0)))))
1086
1087
1088
(defvar ess-bufs-in-frame nil) ;silence the compiler.
1089
;; The next few functions are copied from my (SJE) iswitchb library.
1090
(defun ess-get-bufname (win)
1091
"Used by `ess-get-buffers-in-frames' to walk through all windows."
1092
(let ((buf (buffer-name (window-buffer win))))
1093
(if (not (member buf ess-bufs-in-frame))
1094
;; Only add buf if it is not already in list.
1095
;; This prevents same buf in two different windows being
1096
;; put into the list twice.
1097
(setq ess-bufs-in-frame
1098
(cons buf ess-bufs-in-frame)))))
1099
1100
(defun ess-get-buffers-in-frames (&optional current)
1101
"Return the list of buffers that are visible in the current frame.
1102
If optional argument CURRENT is given, restrict searching to the
1103
current frame, rather than all frames."
1104
(let ((ess-bufs-in-frame nil))
1105
(walk-windows 'ess-get-bufname nil (if current nil 0))
1106
ess-bufs-in-frame))
1107
1108
(defun ess-buffer-visible-this-frame (buf)
1109
"Return t if BUF is visible in current frame."
1110
(member buf (ess-get-buffers-in-frames t)))
1111
1112
(defun ess-buffer-visible-other-frame (buf)
1113
"Return t if BUF is visible in another frame.
1114
Assumes that buffer has not already been in found in current frame."
1115
(if (member (buffer-name (get-buffer buf)) (ess-get-buffers-in-frames))
1116
(window-frame (get-buffer-window buf 0))
1117
nil))
1118
1119
1120
; Functions for evaluating code
1121
1122
(defun ess-ddeclient-p ()
1123
"Returns t iff `ess-local-process-name' is associated with an
1124
inferior-ess-ddeclient, and nil if the ess-process is running as an
1125
ordinary inferior process. Alway nil on Unix machines."
1126
(interactive)
1127
(if ess-microsoft-p
1128
(progn
1129
;; Debug: C-c C-l fails (to start R or give good message) in Windows
1130
(ess-write-to-dribble-buffer
1131
(format "*ddeclient-p: ess-loc-proc-name is '%s'" ess-local-process-name))
1132
(ess-force-buffer-current "Process to load into: ")
1133
(not (equal (ess-get-process-variable 'inferior-ess-ddeclient)
1134
(default-value 'inferior-ess-ddeclient))))))
1135
1136
;; (defun ess-prompt-wait (proc prompt-reg &optional sleep )
1137
;; "Wait for a prompt to appear at the end of current buffer.
1138
;; PROC is the ESS process. PROMPT-REG is a regexp of the process
1139
;; prompt to look for. Does not change point. Not to be used in
1140
;; inferior-process buffer. Use `inferior-ess-wait-for-prompt'
1141
;; instead. "
1142
;; (if sleep (sleep-for sleep)); we sleep here, *and* wait below
1143
;; (save-excursion
1144
;; (while (or (accept-process-output proc 0 100)
1145
;; (progn ;; if no more output, check for prompt
1146
;; (goto-char (marker-position (process-mark proc)))
1147
;; (beginning-of-line)
1148
;; (not (re-search-forward prompt-reg nil t))
1149
;; )))))
1150
1151
(defun ess-wait-for-process (&optional proc sec-prompt wait force-redisplay)
1152
"Wait for 'busy property of the process to become nil.
1153
If SEC-PROMPT is non-nil return if secondary prompt is detected
1154
regardless of whether primary prompt was detected or not. If
1155
WAIT is non-nil wait for WAIT seconds for process output before
1156
the prompt check, default 0.001s. When FORCE-REDISPLAY is non-nil
1157
force redisplay. You better use WAIT >= 0.1 if you need
1158
FORCE-REDISPLAY to avoid excesive redisplay."
1159
(setq proc (or proc (get-process ess-local-process-name)))
1160
(unless (eq (process-status proc) 'run)
1161
(ess-error "ESS process has died unexpectedly."))
1162
(setq wait (or wait 0.002)) ;;xemacs is stuck if it's 0 here
1163
(let ((start-time (float-time)))
1164
(save-excursion
1165
(while (or (accept-process-output proc wait)
1166
(if (and sec-prompt (process-get proc 'sec-prompt))
1167
nil
1168
(if force-redisplay (redisplay 'force))
1169
(process-get proc 'busy)))
1170
(if (> (- (float-time) start-time) .5)
1171
(setq wait .5))))))
1172
1173
;; (defun inferior-ess-ordinary-filter (proc string)
1174
;; (let ((old-buffer (current-buffer)))
1175
;; (unwind-protect
1176
;; (let (moving)
1177
;; (set-buffer (process-buffer proc))
1178
;; (setq moving (= (point) (process-mark proc)))
1179
;; (save-excursion
1180
;; ;; Insert the text, moving the process-marker.
1181
;; (goto-char (process-mark proc))
1182
;; (insert string)
1183
;; (set-marker (process-mark proc) (point)))
1184
;; (if moving (goto-char (process-mark proc))))
1185
;; (set-buffer old-buffer))))
1186
1187
(defun inferior-ess-ordinary-filter (proc string)
1188
(inferior-ess-set-status proc string t)
1189
(ess--if-verbose-write-process-state proc string "ordinary-filter")
1190
(inferior-ess-run-callback proc string)
1191
(with-current-buffer (process-buffer proc)
1192
;; (princ (format "%s:" string))
1193
(insert string)))
1194
1195
1196
(defvar ess-presend-filter-functions nil
1197
"List of functions to call before sending the input string to the process.
1198
Each function gets one argument, a string containing the text to
1199
be send to the subprocess. It should return the string sent,
1200
perhaps the same string that was received, or perhaps a modified
1201
or transformed string.
1202
1203
The functions on the list are called sequentially, and each one is
1204
given the string returned by the previous one. The string returned by
1205
the last function is the text that is actually sent to the process.
1206
1207
You can use `add-hook' to add functions to this list either
1208
globally or locally.
1209
1210
The hook is executed in current buffer. Before execution, the
1211
local value of this hook in the process buffer is appended to the
1212
hook from the current buffer.
1213
")
1214
1215
(defun ess-send-region (process start end &optional visibly message)
1216
"Low level ESS version of `process-send-region'.
1217
If VISIBLY call `ess-eval-linewise', else call `ess-send-string'.
1218
If MESSAGE is supplied, display it at the end.
1219
1220
Run `comint-input-filter-functions' and curent buffer's and
1221
associated with PROCESS `ess-presend-filter-functions' hooks.
1222
"
1223
(if (ess-ddeclient-p)
1224
(ess-eval-region-ddeclient start end 'even-empty)
1225
;; else: "normal", non-DDE behavior:
1226
(ess-send-string process (buffer-substring start end) visibly message)
1227
))
1228
1229
(defvar ess-send-string-function nil)
1230
(make-variable-buffer-local 'ess-send-string-function)
1231
1232
(defun ess-send-string (process string &optional visibly message)
1233
"ESS wrapper for `process-send-string'.
1234
STRING need not end with \\n.
1235
1236
Run `comint-input-filter-functions' and current buffer's and
1237
PROCESS' `ess-presend-filter-functions' hooks on the input
1238
STRING.
1239
1240
VISIBLY can be nil, t, 'nowait or a string. If string the
1241
behavior is as with 'nowait with the differences that inserted
1242
string is VISIBLY instead of STRING (evaluated command is still
1243
STRING). In all other cases the behavior is as described in
1244
`ess-eval-visibly'.
1245
"
1246
(setq string (ess--run-presend-hooks process string))
1247
(inferior-ess--interrupt-subjob-maybe process)
1248
(inferior-ess-mark-as-busy process)
1249
(if (fboundp (buffer-local-value 'ess-send-string-function
1250
(current-buffer)))
1251
;; overloading
1252
(funcall ess-send-string-function process string visibly)
1253
(when (and (eq visibly t)
1254
(null inferior-ess-secondary-prompt)) ; cannot evaluate visibly
1255
(setq visibly 'nowait))
1256
(cond ((eq visibly t) ;; wait after each line
1257
(let ((ess--inhibit-presend-hooks t))
1258
(ess-eval-linewise string)))
1259
((or (stringp visibly)
1260
(eq visibly 'nowait)) ;; insert command and eval invisibly .
1261
(with-current-buffer (process-buffer process)
1262
(save-excursion
1263
(goto-char (process-mark process))
1264
(insert-before-markers
1265
(propertize (format "%s\n"
1266
(replace-regexp-in-string
1267
"\n[ \t]" "\n+ "
1268
(if (stringp visibly) visibly string)))
1269
'font-lock-face 'comint-highlight-input)))
1270
(process-send-string process (ess--concat-new-line-maybe string))))
1271
(t
1272
(process-send-string process (ess--concat-new-line-maybe string)))))
1273
(if message (message message)))
1274
1275
(defvar ess--inhibit-presend-hooks nil
1276
"If non-nil don't run presend hooks.")
1277
1278
(defun ess--run-presend-hooks (process string)
1279
;; run ess-presend-filter-functions and comint-input-filter-functions
1280
(if ess--inhibit-presend-hooks
1281
string
1282
;;return modified string
1283
(let* ((pbuf (process-buffer process))
1284
;; also run proc buffer local hooks
1285
(functions (unless (eq pbuf (current-buffer))
1286
(buffer-local-value 'ess-presend-filter-functions pbuf))))
1287
(setq functions (append (delq t (copy-sequence functions)) ;; even in let, delq distructs
1288
ess-presend-filter-functions))
1289
(while (and functions string)
1290
;; cannot use run-hook-with-args here because string must be passed from one
1291
;; function to another
1292
(if (eq (car functions) t)
1293
(let ((functions
1294
(default-value 'ess-presend-filter-functions)))
1295
(while (and functions string)
1296
(setq string (funcall (car functions) string))
1297
(setq functions (cdr functions))))
1298
(setq string (funcall (car functions) string)))
1299
(setq functions (cdr functions)))
1300
1301
(with-current-buffer pbuf
1302
(run-hook-with-args 'comint-input-filter-functions string))
1303
1304
string)))
1305
1306
(defun ess--concat-new-line-maybe (string)
1307
"Append \\n at the end of STRING if missing."
1308
(if (string-match "\n\\'" string (max (- (length string) 2) 0))
1309
string
1310
(concat string "\n")))
1311
1312
1313
(defvar ess--dbg-del-empty-p t
1314
"Internal variable to control removal of empty lines during the
1315
debugging. Let-bind it to nil before calling
1316
`ess-send-string' or `ess-send-region' if no
1317
removal is necessary.")
1318
1319
(defun inferior-ess--interrupt-subjob-maybe (proc)
1320
"Internal. Interrupt the process if interruptable? process variable is non-nil.
1321
Hide all the junk output in temporary buffer."
1322
(when (process-get proc 'interruptable?)
1323
(let ((cb (cadr (process-get proc 'callbacks)))
1324
(buf (get-buffer-create " *ess-temp-buff*"))
1325
(old-filter (process-filter proc))
1326
(old-buff (process-buffer proc)))
1327
(unwind-protect
1328
(progn
1329
(ess-if-verbose-write "interrupting subjob ... start")
1330
(process-put proc 'interruptable? nil)
1331
(process-put proc 'callbacks nil)
1332
(process-put proc 'running-async? nil)
1333
;; this is to avoid putting junk in user's buffer on process
1334
;; interruption
1335
(set-process-buffer proc buf)
1336
(set-process-filter proc 'inferior-ess-ordinary-filter)
1337
(interrupt-process proc)
1338
(when cb
1339
(ess-if-verbose-write "executing interruption callback ... ")
1340
(funcall cb proc))
1341
;; should be very fast as it inputs only the prompt
1342
(ess-wait-for-process proc)
1343
(ess-if-verbose-write "interrupting subjob ... finished")
1344
)
1345
(set-process-buffer proc old-buff)
1346
(set-process-filter proc old-filter)
1347
))))
1348
1349
(defun ess-async-command-delayed (com &optional buf proc callback delay)
1350
"Delayed asynchronous ess-command.
1351
COM and BUF are as in `ess-command'. DELAY is a number of idle
1352
seconds to wait before starting the execution of the COM. On
1353
interruption (by user's evaluation) ESS tries to rerun the job
1354
after next DELAY seconds, and the whole process repeats itself
1355
until the command manages to run completely.
1356
1357
DELAY defaults to `ess-idle-timer-interval' + 3 seconds
1358
1359
You should always provide PROC for delayed evaluation, as the
1360
current process might change, leading to unpredictable
1361
consequences.
1362
1363
This function is a wrapper of `ess-async-command' with an
1364
explicit interrupt-callback.
1365
"
1366
(unless proc
1367
(error "You must provide PROC argument to ess-async-command-delayed"))
1368
(let* ((timer (make-symbol "timer"))
1369
(delay (or delay
1370
(+ ess-idle-timer-interval 3)))
1371
(int-cb `(lambda (proc)
1372
(ess-async-command-delayed ,com ,buf proc ,callback ,delay)))
1373
(com-fun `(lambda ()
1374
(when (eq (process-status ,proc) 'run) ; do nothing if not running
1375
(if (or (process-get ,proc 'busy) ; if busy, try later
1376
(process-get ,proc 'running-async?))
1377
;; idle timer doesn't work here
1378
(run-with-timer ,delay nil 'ess-async-command-delayed
1379
,com ,buf ,proc ,callback ,delay))
1380
(ess-async-command ,com ,buf ,proc ,callback ',int-cb)))))
1381
(run-with-idle-timer delay nil com-fun)))
1382
1383
;; ;;; VS[03-09-2012]: Test Cases:
1384
;; (ess-command "a<-0\n" nil nil nil nil (get-process "R"))
1385
;; (ess-async-command-delayed "Sys.sleep(5);a<-a+1;cat(1:10)\n" nil
1386
;; (get-process "R") (lambda (proc) (message "done")))
1387
1388
;; (ess-async-command-delayed "Sys.sleep(5)\n" nil (get-process "R")
1389
;; (lambda (proc) (message "done")))
1390
1391
;; (process-get (get-process "R") 'running-async?)
1392
1393
;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
1394
;; (lambda (proc) (message "done")))
1395
;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
1396
;; (lambda (proc) (message "done"))
1397
;; t)
1398
;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
1399
;; (lambda (proc) (message "done"))
1400
;; (lambda (proc2) (message "name: %s" (process-name proc2))))
1401
1402
1403
(defun ess-async-command (com &optional buf proc callback interrupt-callback )
1404
"Asynchronous version of ess-command.
1405
COM, BUF, WAIT and PROC are as in `ess-command'.
1406
1407
CALLBACK is a function of two arguments (PROC STRING) to run
1408
after the successful execution. When INTERRUPT-CALLBACK is
1409
non-nil, user evaluation can interrupt the
1410
job. INTERRUPT-CALLBACK should be either t or a function of one
1411
argument (PROC) to be called on interruption.
1412
1413
NOTE: Currently this function should be used only for background
1414
jobs like caching. ESS tries to suppress any output from the
1415
asynchronous command, but long output of COM will most likely end
1416
up in user's main buffer.
1417
"
1418
(let ((proc (or proc (get-process ess-local-process-name))))
1419
(if (not (and proc
1420
(eq (process-status proc) 'run)))
1421
(error "Process %s is dead" ess-local-process-name)
1422
(if (or (process-get proc 'busy)
1423
(process-get proc 'running-async?))
1424
(error "Process %s is busy or already running an async command." ess-local-process-name)
1425
(when (eq interrupt-callback t)
1426
(setq interrupt-callback (lambda (proc))))
1427
(process-put proc 'callbacks (list (cons callback 'suppress-output)
1428
interrupt-callback))
1429
(process-put proc 'interruptable? (and interrupt-callback t))
1430
(process-put proc 'running-async? t)
1431
(ess-command com buf nil 'no-prompt-check .01 proc)))))
1432
1433
1434
(defun ess-command (com &optional buf sleep no-prompt-check wait proc force-redisplay)
1435
"Send the ESS process command COM and delete the output from
1436
the ESS process buffer. If an optional second argument BUF
1437
exists save the output in that buffer. BUF is erased before
1438
use. COM should have a terminating newline. Guarantees that the
1439
value of .Last.value will be preserved. When optional third arg
1440
SLEEP is non-nil, `(sleep-for (* a SLEEP))' will be used in a few
1441
places where `a' is proportional to `ess-cmd-delay'. WAIT and
1442
FORCE-REDISPLAY are as in `ess-wait-for-process' and are passed
1443
to `ess-wait-for-process'.
1444
1445
PROC should be a process, if nil the process name is taken from
1446
`ess-local-process-name'. This command doesn't set 'last-eval
1447
process variable.
1448
1449
Note: for critical, or error prone code you should consider
1450
wrapping the code into:
1451
1452
local({
1453
olderr <- options(error=NULL)
1454
on.exit(options(olderr))
1455
...
1456
})
1457
"
1458
;; Use this function when you need to evaluate some S code, and the
1459
;; result is needed immediately. Waits until the output is ready
1460
1461
;; the ddeclient-p checks needs to use the local-process-name
1462
(unless buf
1463
(setq buf (get-buffer-create " *ess-command-output*")))
1464
1465
(if (ess-ddeclient-p)
1466
(ess-command-ddeclient com buf sleep)
1467
1468
;; else: "normal", non-DDE behavior:
1469
1470
(let* ((sprocess (or proc (ess-get-process ess-local-process-name)))
1471
sbuffer primary-prompt end-of-output oldpb oldpf oldpm
1472
)
1473
1474
(unless sprocess
1475
;; should hardly happen, since (ess-get-process *) already checked:
1476
(error "Process %s is not running!" ess-current-process-name))
1477
(setq sbuffer (process-buffer sprocess))
1478
(with-current-buffer sbuffer
1479
(unless ess-local-process-name
1480
(setq ess-local-process-name (process-name sprocess))) ; let it be here (calling functions need not set it explicitly)
1481
(setq primary-prompt inferior-ess-primary-prompt)
1482
(ess-if-verbose-write (format "n(ess-command %s ..)" com))
1483
(unless no-prompt-check
1484
(when (process-get sprocess 'busy) ;;(looking-at inferior-ess-primary-prompt)
1485
(ess-error
1486
"ESS process not ready. Finish your command before trying again.")))
1487
(setq oldpf (process-filter sprocess))
1488
(setq oldpb (process-buffer sprocess))
1489
(setq oldpm (marker-position (process-mark sprocess)))
1490
;; need the buffer-local values in result buffer "buf":
1491
(unwind-protect
1492
(progn
1493
(set-process-buffer sprocess buf)
1494
(set-process-filter sprocess 'inferior-ess-ordinary-filter)
1495
;; Output is now going to BUF:
1496
(with-current-buffer buf
1497
(setq inferior-ess-primary-prompt primary-prompt) ;; set local value
1498
(setq buffer-read-only nil)
1499
(erase-buffer)
1500
(set-marker (process-mark sprocess) (point-min))
1501
(inferior-ess-mark-as-busy sprocess)
1502
(process-send-string sprocess com)
1503
;; need time for ess-create-object-name-db on PC
1504
(if no-prompt-check
1505
(sleep-for 0.020); 0.1 is noticeable!
1506
;; else: default
1507
(ess-wait-for-process sprocess nil wait force-redisplay)
1508
(goto-char (point-max))
1509
;; remove prompt
1510
;; if output is cat(..)ed this deletes the output ...
1511
(delete-region (point-at-bol) (point-max)))
1512
(ess-if-verbose-write " .. ok{ess-command}")
1513
))
1514
1515
(ess-if-verbose-write " .. exiting{ess-command}\n")
1516
;; Restore old values for process filter
1517
(set-process-buffer sprocess oldpb)
1518
(set-process-filter sprocess oldpf)
1519
(set-marker (process-mark sprocess) oldpm))))
1520
buf))
1521
1522
(defun ess-boolean-command (com &optional buf wait)
1523
"Like `ess-command' but expects COM to print TRUE or FALSE.
1524
If TRUE (or true) is found return non-nil otherwise nil.
1525
1526
Example: (ess-boolean-command \"2>1\n\")"
1527
(with-current-buffer (ess-command com buf nil nil wait)
1528
(goto-char (point-min))
1529
(let ((case-fold-search t))
1530
(re-search-forward "true" nil t))))
1531
1532
(defun ess-replace-in-string (str regexp newtext &optional literal)
1533
"Replace all matches in STR for REGEXP with NEWTEXT string.
1534
Optional LITERAL non-nil means do a literal replacement.
1535
Otherwise treat \\ in NEWTEXT string as special:
1536
\\& means substitute original matched text,
1537
\\N means substitute match for \(...\) number N,
1538
\\\\ means insert one \\."
1539
(if (not (stringp str))
1540
(error "(replace-in-string): First argument must be a string: %s" str))
1541
(if (stringp newtext)
1542
nil
1543
(error "(replace-in-string): 3rd arg must be a string: %s"
1544
newtext))
1545
(let ((rtn-str "")
1546
(start 0)
1547
(special)
1548
match prev-start)
1549
(while (setq match (string-match regexp str start))
1550
(setq prev-start start
1551
start (match-end 0)
1552
rtn-str
1553
(concat
1554
rtn-str
1555
(substring str prev-start match)
1556
(cond (literal newtext)
1557
(t (mapconcat
1558
(function
1559
(lambda (c)
1560
(if special
1561
(progn
1562
(setq special nil)
1563
(cond ((eq c ?\\) "\\")
1564
((eq c ?&)
1565
(substring str
1566
(match-beginning 0)
1567
(match-end 0)))
1568
((and (>= c ?0) (<= c ?9))
1569
(if (> c (+ ?0 (length
1570
(match-data))))
1571
;; Invalid match num
1572
(error "(replace-in-string) Invalid match num: %c" c)
1573
(setq c (- c ?0))
1574
(substring str
1575
(match-beginning c)
1576
(match-end c))))
1577
(t (char-to-string c))))
1578
(if (eq c ?\\) (progn (setq special t) nil)
1579
(char-to-string c)))))
1580
newtext ""))))))
1581
(concat rtn-str (substring str start))))
1582
1583
1584
1585
;;*;; Evaluating lines, paragraphs, regions, and buffers.
1586
1587
;;--- The two basic building blocks [called by all other ess-eval..] are
1588
;; (ess-eval-linewise ....)
1589
;; and
1590
;; (ess-eval-region ....)
1591
1592
(defun ess-eval-linewise (text &optional invisibly eob even-empty
1593
wait-last-prompt sleep-sec wait-sec)
1594
;; RDB 28/8/92 added optional arg eob
1595
;; MM 2006-08-23: added 'timeout-ms' -- but the effect seems "nil"
1596
;; VS 2012-01-18 it was actually nil, replaced with wait-sec - 0.001 default
1597
;; MM 2007-01-05: added 'sleep-sec' VS:? this one seems redundant to wait-last-prompt
1598
"Evaluate TEXT in the ESS process buffer as if typed in w/o tabs.
1599
Waits for prompt after each line of input, so won't break on large texts.
1600
1601
If optional second arg INVISIBLY is non-nil, don't echo commands.
1602
If it is a string, just include that string. If optional third
1603
arg EOB is non-nil go to end of ESS process buffer after
1604
evaluation. If optional 4th arg EVEN-EMPTY is non-nil, also send
1605
empty text (e.g. an empty line). If 5th arg WAIT-LAST-PROMPT is
1606
non-nil, also wait for the prompt after the last line; if 6th arg
1607
SLEEP-SEC is a number, ESS will call '(\\[sleep-for] SLEEP-SEC)
1608
at the end of this function. If the 7th arg WAIT-SEC is set, it
1609
will be used instead of the default .001s and be passed to
1610
\\[ess-wait-for-process].
1611
1612
Run `comint-input-filter-functions' and
1613
`ess-presend-filter-functions' of the associated PROCESS on the
1614
TEXT.
1615
"
1616
1617
(if (ess-ddeclient-p)
1618
(ess-eval-linewise-ddeclient text
1619
invisibly eob even-empty
1620
(if wait-last-prompt
1621
ess-eval-ddeclient-sleep))
1622
1623
;; else: "normal", non-DDE behavior:
1624
(unless (numberp wait-sec)
1625
(setq wait-sec 0.001)) ;;don't make it lower (0.); xemacs is stuck
1626
1627
(ess-force-buffer-current "Process to use: ")
1628
1629
;; Use this to evaluate some code, but don't wait for output.
1630
(let* ((deactivate-mark); keep local {do *not* deactivate wrongly}
1631
(cbuffer (current-buffer))
1632
(sprocess (ess-get-process ess-current-process-name))
1633
(sbuffer (process-buffer sprocess))
1634
(win (get-buffer-window sbuffer t))
1635
;; (text (ess-replace-in-string text "\t" " "))
1636
com pos txt-gt-0)
1637
1638
(setq text (ess--concat-new-line-maybe
1639
(ess--run-presend-hooks sprocess text)))
1640
1641
(with-current-buffer sbuffer
1642
1643
;; (when (and win
1644
;; (null eob)
1645
;; (<= (process-mark sprocess) (point)))
1646
;; (setq eob t))
1647
;; (setq wait-last-prompt t)
1648
;; (dbg eob)
1649
1650
;; the following is required to make sure things work!
1651
(when (string= ess-language "STA")
1652
(if ess-sta-delimiter-friendly;; RAS: mindless replacement of semi-colons
1653
(setq text (ess-replace-in-string text ";" "\n")))
1654
(setq invisibly t))
1655
(setq text (propertize text 'field 'input 'front-sticky t))
1656
1657
(goto-char (marker-position (process-mark sprocess)))
1658
(if (stringp invisibly)
1659
(insert-before-markers (concat "*** " invisibly " ***\n")))
1660
;; dbg:
1661
;; dbg (ess-write-to-dribble-buffer
1662
;; dbg (format "(eval-visibly 2): text[%d]= '%s'\n" (length text) text))
1663
(while (or (setq txt-gt-0 (> (length text) 0))
1664
even-empty)
1665
(setq even-empty nil)
1666
(if txt-gt-0
1667
(progn
1668
(setq pos (string-match "\n\\|$" text))
1669
(setq com (concat (substring text 0 pos) "\n"))
1670
(setq text (substring text (min (length text) (1+ pos)))))
1671
;; else 0-length text
1672
(setq com "\n"))
1673
(goto-char (marker-position (process-mark sprocess)))
1674
(if win (set-window-point win (process-mark sprocess)))
1675
(when (not invisibly)
1676
(insert (propertize com 'font-lock-face 'comint-highlight-input)) ;; for consistency with comint :(
1677
(set-marker (process-mark sprocess) (point)))
1678
(inferior-ess-mark-as-busy sprocess)
1679
(process-send-string sprocess com)
1680
(when (or wait-last-prompt
1681
(> (length text) 0))
1682
(ess-wait-for-process sprocess t wait-sec))
1683
)
1684
(if eob (ess-show-buffer (buffer-name sbuffer) nil))
1685
(goto-char (marker-position (process-mark sprocess)))
1686
(when win
1687
(with-selected-window win
1688
(goto-char (point))
1689
(recenter (- -1 scroll-margin))) ;; this recenter is crucial to avoid reseting window-point
1690
)))
1691
1692
(if (numberp sleep-sec)
1693
(sleep-for sleep-sec)))); in addition to timeout-ms
1694
1695
1696
;; VS[06-01-2013]: this how far I got in investingating the emacs reseting of
1697
;; window-point. It really happens out of the blue :(
1698
1699
;; (defun test ()
1700
;; (let* ((cbuffer (get-buffer "*R*"))
1701
;; (proc (get-buffer-process cbuffer))
1702
;; (win (get-buffer-window cbuffer t)))
1703
;; (with-current-buffer cbuffer
1704
;; (proc-send-test proc win "ls()\n")
1705
;; (ess-wait-for-process proc t 0.005)
1706
;; ;; (goto-char (marker-position (process-mark proc)))
1707
;; ;; (set-window-point win (point))
1708
;; (proc-send-test proc win "NA\n")
1709
;; ;; (when win
1710
;; ;; (dbg (point))
1711
;; ;; (set-window-point win (point-max)))
1712
;; )))
1713
1714
1715
;; (defun proc-send-test (proc win com)
1716
;; (with-current-buffer (process-buffer proc)
1717
;; (goto-char (marker-position (process-mark proc)))
1718
;; (inferior-ess-mark-as-busy proc)
1719
;; (insert com)
1720
;; (set-marker (process-mark proc) (point))
1721
;; (set-window-point win (point))
1722
;; (process-send-string proc com)
1723
;; (dbg (window-point win) (window-end win))
1724
;; ))
1725
1726
;;;*;;; Evaluate only
1727
1728
(defvar ess-current-region-overlay
1729
(let ((overlay (make-overlay (point) (point))))
1730
(overlay-put overlay 'face 'highlight)
1731
overlay)
1732
"The overlay for highlighting currently evaluated region or line.")
1733
1734
(defun ess-blink-region (start end)
1735
(when ess-blink-region
1736
(move-overlay ess-current-region-overlay start end)
1737
(run-with-timer ess-blink-delay nil
1738
(lambda ()
1739
(delete-overlay ess-current-region-overlay)))))
1740
1741
1742
(defun ess-eval-region (start end toggle &optional message inject)
1743
"Send the current region to the inferior ESS process.
1744
With prefix argument toggle the meaning of `ess-eval-visibly';
1745
this does not apply when using the S-plus GUI, see `ess-eval-region-ddeclient'.
1746
1747
If INJECT is non-nil the region will be pre-processed in a
1748
dialect specific way to include source references"
1749
1750
(interactive "r\nP")
1751
;;(untabify (point-min) (point-max))
1752
;;(untabify start end); do we really need to save-excursion?
1753
(ess-force-buffer-current "Process to use: ")
1754
1755
(unless ess-local-customize-alist
1756
;; external applications might call ess-eval-* functions; make it easier for them
1757
(ess-setq-vars-local (symbol-value (ess-get-process-variable 'ess-local-customize-alist))))
1758
1759
(message "Starting evaluation...")
1760
(setq message (or message "Eval region"))
1761
1762
(save-excursion
1763
;; don't send new lines (avoid screwing the debugger)
1764
(goto-char start)
1765
(skip-chars-forward "\n\t ")
1766
(setq start (point))
1767
1768
(unless mark-active
1769
(ess-blink-region start end))
1770
1771
;; don't send new lines at the end (avoid screwing the debugger)
1772
(goto-char end)
1773
(skip-chars-backward "\n\t ")
1774
(setq end (point)))
1775
1776
(let* ((proc (get-process ess-local-process-name))
1777
(visibly (if toggle (not ess-eval-visibly) ess-eval-visibly))
1778
(dev-p (or ess-developer
1779
(ess-get-process-variable 'ess-developer)))
1780
(tb-p (process-get proc 'tracebug)))
1781
(cond
1782
(dev-p (ess-developer-send-region proc start end visibly message tb-p))
1783
(tb-p (ess-tracebug-send-region proc start end visibly message inject))
1784
(t (ess-send-region proc start end visibly message))))
1785
1786
(if (and (fboundp 'deactivate-mark) ess-eval-deactivate-mark)
1787
(deactivate-mark))
1788
;; return value
1789
(list start end))
1790
1791
(defun ess-eval-buffer (vis)
1792
"Send the current buffer to the inferior ESS process.
1793
Arg has same meaning as for `ess-eval-region'."
1794
(interactive "P")
1795
(ess-eval-region (point-min) (point-max) vis "Eval buffer" 'buffer))
1796
1797
(defun ess-eval-buffer-from-beg-to-here (vis)
1798
(interactive "P")
1799
(ess-eval-region (point-min) (point) vis "Eval buffer from the beginning
1800
of the buffer until here, i.e. 'point'"))
1801
1802
(defun ess-eval-buffer-from-here-to-end (vis)
1803
(interactive "P")
1804
(ess-eval-region (point) (point-max) vis "Eval buffer from here ('point') until
1805
the end of the buffer"))
1806
1807
1808
(defun ess-eval-function (vis &optional no-error)
1809
"Send the current function to the inferior ESS process.
1810
Arg has same meaning as for `ess-eval-region'.
1811
1812
If NO-ERROR is non-nil and the function was successfully
1813
evaluated, return '(beg end) representing the beginning and end
1814
of the current function, otherwise (in case of an error) return
1815
nil."
1816
(interactive "P")
1817
(ess-force-buffer-current "Process to use: ")
1818
(save-excursion
1819
(ignore-errors
1820
;; evaluation is forward oriented
1821
(forward-line -1)
1822
(ess-next-code-line 1))
1823
(let ((beg-end (ess-end-of-function nil no-error)))
1824
(if beg-end
1825
(let* ((beg (nth 0 beg-end))
1826
(end (nth 1 beg-end))
1827
(proc (get-process ess-local-process-name))
1828
(tb-p (process-get proc 'tracebug))
1829
(dev-p (or ess-developer
1830
(ess-get-process-variable 'ess-developer)))
1831
(name (progn (goto-char beg)
1832
(forward-word) ;;func names starting with . are not recognized??
1833
(ess-read-object-name-default)))
1834
(mess (format "Eval function %s"
1835
(propertize (or name "???")
1836
'face 'font-lock-function-name-face)))
1837
(visibly (if vis (not ess-eval-visibly) ess-eval-visibly)))
1838
1839
(ess-blink-region beg end)
1840
(cond
1841
(dev-p (ess-developer-send-function proc beg end name visibly mess tb-p))
1842
(tb-p (ess-tracebug-send-function proc beg end visibly mess))
1843
(t (ess-send-region proc beg end visibly mess)))
1844
beg-end)
1845
nil))))
1846
1847
1848
;; This is from Mary Lindstrom <[email protected]>
1849
;; 31 Aug 1995 14:11:43 To: [email protected]
1850
(defun ess-eval-paragraph (vis)
1851
"Send the current paragraph to the inferior ESS process.
1852
Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'."
1853
(interactive "P")
1854
(save-excursion
1855
(forward-paragraph)
1856
(let ((end (point)))
1857
(backward-paragraph)
1858
(ess-eval-region (point) end vis "Eval paragraph"))))
1859
1860
;; ;; Experimental - after suggestion from Jenny Brian for an 'eval-multiline'
1861
;; ;; 'sentence' is too much : almost like 'paragraph'
1862
;; ;; 'sexp' is close, but too little [when point is inside function call;
1863
;; ;; it moves all the way to the end - which is fine]
1864
;; (defun ess-eval-sexp (vis)
1865
;; "Send the current sexp to the inferior ESS process.
1866
;; Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'."
1867
;; (interactive "P")
1868
;; (save-excursion
1869
;; (forward-sexp)
1870
;; (let ((end (point)))
1871
;; (backward-sexp)
1872
;; (ess-eval-region (point) end vis "Eval sexp"))))
1873
1874
1875
(defun ess-eval-function-or-paragraph (vis)
1876
"Send the current function if \\[point] is inside one, otherwise the current
1877
paragraph other to the inferior ESS process.
1878
Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'."
1879
(interactive "P")
1880
(let ((beg-end (ess-eval-function vis 'no-error)))
1881
(if (null beg-end) ; not a function
1882
(ess-eval-paragraph vis))))
1883
1884
(defun ess-eval-function-or-paragraph-and-step (vis)
1885
"Send the current function if \\[point] is inside one, otherwise the current
1886
paragraph other to the inferior ESS process.
1887
Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'."
1888
(interactive "P")
1889
(let ((beg-end (ignore-errors (ess-eval-function vis 'no-error)))) ;; ignore-errors is a hack, ess-eval-function gives stupid errors sometimes
1890
(if (null beg-end) ; not a function
1891
(ess-eval-paragraph-and-step vis)
1892
(goto-char (cadr beg-end))
1893
(if ess-eval-empty
1894
(forward-line 1)
1895
(ess-next-code-line 1)))))
1896
1897
(defun ess-eval-region-or-function-or-paragraph (vis)
1898
"Send the current region if mark is active, if not, send
1899
function if \\[point] is inside one, otherwise the current
1900
paragraph.
1901
1902
Prefix arg VIS toggles visibility of ess-code as for
1903
`ess-eval-region'."
1904
(interactive "P")
1905
(if (and transient-mark-mode mark-active ;; xemacs doesn't have use-region-p
1906
(> (region-end) (region-beginning)))
1907
(ess-eval-region (region-beginning) (region-end) vis)
1908
(ess-eval-function-or-paragraph vis)))
1909
1910
1911
(defun ess-eval-region-or-function-or-paragraph-and-step (vis)
1912
"Send the current region if mark is active, if not, send
1913
function if \\[point] is inside one, otherwise the current
1914
paragraph. After evaluation step to the next code line or to the
1915
end of region if region was active.
1916
1917
Prefix arg VIS toggles visibility of ess-code as for
1918
`ess-eval-region'."
1919
(interactive "P")
1920
(if (and transient-mark-mode mark-active ;; xemacs doesn't have use-region-p
1921
(> (region-end) (region-beginning)))
1922
(let ((end (region-end)))
1923
(ess-eval-region (region-beginning) end vis)
1924
(goto-char end))
1925
(ess-eval-function-or-paragraph-and-step vis)))
1926
1927
1928
(defun ess-eval-line (vis)
1929
"Send the current line to the inferior ESS process.
1930
Arg has same meaning as for `ess-eval-region'."
1931
(interactive "P")
1932
(save-excursion
1933
(end-of-line)
1934
(let ((end (point)))
1935
(beginning-of-line)
1936
(princ (concat "Loading line: " (ess-extract-word-name) " ...") t)
1937
(ess-eval-region (point) end vis "Eval line"))))
1938
1939
1940
1941
(defun ess-next-code-line (&optional arg skip-to-eob)
1942
"Move ARG lines of code forward (backward if ARG is negative).
1943
Skips past all empty and comment lines. Default for ARG is 1.
1944
Don't skip the last empty and comment lines in the buffer unless
1945
SKIP-TO-EOB is non-nil.
1946
1947
On success, return 0. Otherwise, go as far as possible and return -1."
1948
(interactive "p")
1949
(or arg (setq arg 1))
1950
(beginning-of-line)
1951
(let ((pos (point))
1952
(n 0)
1953
(inc (if (> arg 0) 1 -1)))
1954
(while (and (/= arg 0) (= n 0))
1955
(setq n (forward-line inc)); n=0 is success
1956
(if (not (fboundp 'comment-beginning))
1957
(while (and (= n 0)
1958
(looking-at "\\s-*\\($\\|\\s<\\)"))
1959
(setq n (forward-line inc)))
1960
(comment-beginning)
1961
(beginning-of-line)
1962
(forward-comment (* inc (buffer-size))) ;; as suggested in info file
1963
)
1964
(if (or skip-to-eob
1965
(not (looking-at ess-no-skip-regexp))) ;; don't go to eob or whatever
1966
(setq arg (- arg inc))
1967
(goto-char pos)
1968
(setq arg 0)
1969
(forward-line 1));; stop at next empty line
1970
(setq pos (point)))
1971
(goto-char pos)
1972
n))
1973
1974
(defun ess-eval-line-and-step (&optional simple-next even-empty invisibly)
1975
"Evaluate the current line visibly and step to the \"next\" line.
1976
If SIMPLE-NEXT is non-nil, possibly via prefix arg, first skip
1977
empty and commented lines. If 2nd arg EVEN-EMPTY [prefix as
1978
well], also send empty lines. When the variable `ess-eval-empty'
1979
is non-nil both SIMPLE-NEXT and EVEN-EMPTY are interpreted as
1980
true."
1981
;; From an idea by Rod Ball ([email protected])
1982
(interactive "P\nP"); prefix sets BOTH !
1983
(ess-force-buffer-current "Process to load into: ")
1984
(save-excursion
1985
(end-of-line)
1986
(let ((end (point)))
1987
(beginning-of-line)
1988
;; go to end of process buffer so user can see result
1989
(ess-eval-linewise (buffer-substring (point) end)
1990
invisibly 'eob (or even-empty ess-eval-empty))))
1991
(if (or simple-next ess-eval-empty even-empty)
1992
(forward-line 1)
1993
(ess-next-code-line 1)))
1994
1995
(defun ess-eval-region-or-line-and-step (&optional vis)
1996
"Evaluate region if there is an active one, otherwise the current line.
1997
1998
Prefix arg VIS toggles visibility of ess-code when evaluating
1999
the region (as for `ess-eval-region') and has no effect for
2000
evaluation of the line.
2001
"
2002
(interactive "P")
2003
(if (and transient-mark-mode mark-active ;; xemacs doesn't have use-region-p
2004
(> (region-end) (region-beginning)))
2005
(ess-eval-region (region-beginning) (region-end) vis)
2006
(ess-eval-line-and-step)
2007
))
2008
2009
(defun ess-eval-line-and-step-invisibly ()
2010
"Evaluate the current line invisibly and step to the next line.
2011
Evaluate all comments and empty lines."
2012
(interactive)
2013
(ess-eval-line-and-step t t t))
2014
2015
;; goes to the real front, in case you do double function definition
2016
;; 29-Jul-92 -FER
2017
;; don't know why David changed it.
2018
2019
;; FER's versions don't work properly with nested functions. Replaced
2020
;; mine. DMS 16 Nov 92
2021
2022
;;;*;;; Evaluate and switch to S
2023
2024
(defun ess-eval-region-and-go (start end vis)
2025
"Send the current region to the inferior S and switch to the process buffer.
2026
Arg has same meaning as for `ess-eval-region'."
2027
(interactive "r\nP")
2028
(ess-eval-region start end vis)
2029
(ess-switch-to-ESS t))
2030
2031
(defun ess-eval-buffer-and-go (vis)
2032
"Send the current buffer to the inferior S and switch to the process buffer.
2033
Arg has same meaning as for `ess-eval-region'."
2034
(interactive "P")
2035
(ess-eval-buffer vis)
2036
(ess-switch-to-ESS t))
2037
2038
(defun ess-eval-function-and-go (vis)
2039
"Send the current function to the inferior ESS process and switch to
2040
the process buffer. Arg has same meaning as for `ess-eval-region'."
2041
(interactive "P")
2042
(ess-eval-function vis)
2043
(ess-switch-to-ESS t))
2044
2045
(defun ess-eval-line-and-go (vis)
2046
"Send the current line to the inferior ESS process and switch to the
2047
process buffer. Arg has same meaning as for `ess-eval-region'."
2048
(interactive "P")
2049
(ess-eval-line vis)
2050
(ess-switch-to-ESS t))
2051
2052
(defun ess-eval-paragraph-and-go (vis)
2053
"Send the current paragraph to the inferior ESS process and switch to the
2054
process buffer. Arg has same meaning as for `ess-eval-region'."
2055
(interactive "P")
2056
(ess-eval-paragraph vis)
2057
(ess-switch-to-ESS t))
2058
2059
(defun ess-eval-paragraph-and-step (vis)
2060
"Send the current paragraph to the inferior ESS process and
2061
move forward to the first line after the paragraph. If not
2062
inside a paragraph, evaluate next one. Arg has same meaning as
2063
for `ess-eval-region'."
2064
(interactive "P")
2065
(let ((beg-end (ess-eval-paragraph vis)))
2066
(goto-char (cadr beg-end))
2067
(if ess-eval-empty
2068
(forward-line 1)
2069
(ess-next-code-line 1)))
2070
)
2071
2072
;;; Related to the ess-eval-* commands, there are the ess-load
2073
;;; commands. Need to add appropriate stuff...
2074
2075
2076
(defun ess-load-file (&optional filename)
2077
"Load an S source file into an inferior ESS process."
2078
(interactive (list
2079
(or
2080
(and (eq major-mode 'ess-mode)
2081
(buffer-file-name))
2082
(expand-file-name
2083
(read-file-name "Load S file: " nil nil t)))))
2084
(ess-force-buffer-current "Process to load into: ")
2085
(if (or ess-developer
2086
(ess-get-process-variable 'ess-developer))
2087
(ess-developer-source-current-file filename)
2088
(let ((filename (if (and (fboundp 'tramp-tramp-file-p)
2089
(tramp-tramp-file-p filename))
2090
(tramp-file-name-localname (tramp-dissect-file-name filename))
2091
filename)))
2092
(if ess-microsoft-p
2093
(setq filename (ess-replace-in-string filename "[\\]" "/")))
2094
(if (fboundp (ess-process-get 'source-file-function))
2095
(funcall (ess-process-get 'source-file-function) filename)
2096
(let ((source-buffer (get-file-buffer filename)))
2097
(if (ess-check-source filename)
2098
(error "Buffer %s has not been saved" (buffer-name source-buffer)))
2099
;; else
2100
(if (ess-ddeclient-p)
2101
(ess-load-file-ddeclient filename)
2102
2103
;; else: "normal", non-DDE behavior:
2104
;; Find the process to load into
2105
(if source-buffer
2106
(with-current-buffer source-buffer
2107
(ess-force-buffer-current "Process to load into: ")
2108
(ess-check-modifications)))
2109
(let ((errbuffer (ess-create-temp-buffer ess-error-buffer-name))
2110
error-occurred nomessage)
2111
(ess-eval-linewise (format ess-load-command filename))
2112
)))))))
2113
2114
;; C-c C-l *used to* eval code:
2115
(defun ess-msg-and-comint-dynamic-list-input-ring ()
2116
"Display a list of recent inputs entered into the current buffer."
2117
(interactive)
2118
(message "C-c C-l no longer loads a source file in [iESS], rather use C-c M-l instead")
2119
(comint-dynamic-list-input-ring))
2120
2121
; Inferior S mode
2122
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2123
;;;; In this section:
2124
;;;;
2125
;;;; * The major mode inferior-ess-mode
2126
;;;; * Process handling code
2127
;;;; * Completion code
2128
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2129
2130
;;*;; Major mode definition
2131
2132
(defvar inferior-ess-mode-map
2133
(let ((map (make-sparse-keymap)))
2134
(set-keymap-parent map comint-mode-map)
2135
2136
(define-key map "\C-y" 'ess-yank)
2137
;; Use syntax valid *both* for GNU emacs and XEmacs :
2138
(define-key map "\r" 'inferior-ess-send-input)
2139
(define-key map "\C-a" 'comint-bol)
2140
2141
;; 2010-06-03 SJE
2142
;; disabled this in favour of ess-dirs. Martin was not sure why this
2143
;; key was defined anyway in this mode.
2144
;;(define-key map "\M-\r" 'ess-transcript-send-command-and-move)
2145
(define-key map "\C-c\M-l" 'ess-load-file);; no longer overwrites C-c C-l;
2146
;; but for now the user deserves a message:
2147
(define-key map "\C-c\C-l" 'ess-msg-and-comint-dynamic-list-input-ring)
2148
(define-key map "\C-c`" 'ess-show-traceback)
2149
(define-key map [(control ?c) ?~] 'ess-show-call-stack)
2150
(define-key map "\C-c\C-d" 'ess-dump-object-into-edit-buffer)
2151
(define-key map "\C-c\C-v" 'ess-display-help-on-object)
2152
(define-key map "\C-c\C-q" 'ess-quit)
2153
(define-key map "\C-c\C-s" 'ess-execute-search)
2154
(define-key map "\C-c\C-x" 'ess-execute-objects)
2155
(define-key map "\C-c\034" 'ess-abort) ; \C-c\C-backslash
2156
(define-key map "\C-c\C-z" 'ess-switch-to-inferior-or-script-buffer) ; mask comint map
2157
(define-key map "\C-d" 'delete-char) ; EOF no good in S
2158
(if (and (featurep 'emacs) (>= emacs-major-version 24))
2159
(define-key map "\t" 'completion-at-point)
2160
(define-key map "\t" 'comint-dynamic-complete)
2161
(define-key map "\M-\t" 'comint-dynamic-complete))
2162
(define-key map "\C-c\t" 'ess-complete-object-name-deprecated)
2163
(define-key map "\M-?" 'ess-list-object-completions)
2164
(define-key map "\C-c\C-k" 'ess-request-a-process)
2165
(define-key map "," 'ess-smart-comma)
2166
2167
(define-key map "\C-c\C-d" 'ess-doc-map)
2168
(define-key map "\C-c\C-e" 'ess-extra-map)
2169
(define-key map "\C-c\C-t" 'ess-dev-map)
2170
map)
2171
"Keymap for `inferior-ess' mode.")
2172
2173
(easy-menu-define
2174
inferior-ess-mode-menu inferior-ess-mode-map
2175
"Menu for use in Inferior S mode"
2176
'("iESS"
2177
["What is this? (beta)" ess-mouse-me t]
2178
["Quit" ess-quit t]
2179
;; ["Send and move" ess-transcript-send-command-and-move t]
2180
["Copy command" comint-copy-old-input t]
2181
["Send command" inferior-ess-send-input t]
2182
["Switch to Script Buffer" ess-switch-to-inferior-or-script-buffer t]
2183
["Get help on S object" ess-display-help-on-object t]
2184
"------"
2185
("Process"
2186
["Process Echoes" (lambda () (interactive)
2187
(setq comint-process-echoes (not comint-process-echoes)))
2188
:active t
2189
:style toggle
2190
:selected comint-process-echoes]
2191
("Eval visibly "
2192
:filter ess--generate-eval-visibly-submenu ))
2193
"------"
2194
("Utils"
2195
;; need a toggle switch for above, AJR.
2196
["Attach directory" ess-execute-attach t]
2197
["Display object list" ess-execute-objects t]
2198
["Display search list" ess-execute-search t]
2199
["Edit S Object" ess-dump-object-into-edit-buffer t]
2200
["Enter S command" ess-execute t]
2201
["Jump to Error" ess-parse-errors t]
2202
["Load source file" ess-load-file t]
2203
["Resynch S completions" ess-resynch t]
2204
["Recreate R versions known to ESS" (ess-r-versions-create) t]
2205
)
2206
"------"
2207
("start-dev" :visible nil); <-- ??
2208
("end-dev" :visible nil)
2209
"------"
2210
("Font Lock"
2211
:active inferior-ess-font-lock-keywords
2212
:filter ess--generate-font-lock-submenu)
2213
"------"
2214
["Describe" describe-mode t]
2215
["Send bug report" ess-submit-bug-report t]
2216
["About" (ess-goto-info "Entering Commands") t]
2217
))
2218
2219
2220
2221
(defun inferior-ess-mode-xemacs-menu ()
2222
"Hook to install `ess-mode' menu for XEmacs (w/ easymenu)."
2223
(if 'inferior-ess-mode
2224
(easy-menu-add inferior-ess-mode-menu)
2225
(easy-menu-remove inferior-ess-mode-menu)))
2226
2227
(if (string-match "XEmacs" emacs-version)
2228
(add-hook 'inferior-ess-mode-hook 'inferior-ess-mode-xemacs-menu))
2229
2230
(defvar ess-mode-minibuffer-map
2231
(let ((map (make-sparse-keymap)))
2232
(set-keymap-parent map minibuffer-local-map)
2233
2234
(define-key map "\t" 'ess-complete-object-name)
2235
(define-key map "\C-\M-i" 'ess-complete-object-name) ;; doesn't work:(
2236
(define-key map "\C-c\C-s" 'ess-execute-search)
2237
(define-key map "\C-c\C-x" 'ess-execute-objects)
2238
map)
2239
"Keymap used in `ess-execute'"
2240
)
2241
2242
(defun inferior-ess-mode ()
2243
"Major mode for interacting with an inferior ESS process.
2244
Runs an S interactive job as a subprocess of Emacs, with I/O through an
2245
Emacs buffer. Variable `inferior-ess-program' controls which S
2246
is run.
2247
2248
Commands are sent to the ESS process by typing them, and pressing
2249
\\[inferior-ess-send-input]. Pressing \\[complete-dynamic-complete]
2250
completes known object names or filenames, as appropriate. Other
2251
keybindings for this mode are:
2252
2253
\\{inferior-ess-mode-map}
2254
2255
When editing S objects, the use of \\[ess-load-file] is advocated.
2256
`ess-load-file' keeps source files (if `ess-keep-dump-files' is non-nil) in
2257
the directory specified by `ess-source-directory', with the
2258
filename chosen according to `ess-dump-filename-template'. When a file is
2259
loaded, `ess-mode' parses error messages and jumps to the appropriate file
2260
if errors occur. The ess-eval- commands do not do this.
2261
2262
Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
2263
`inferior-ess-mode-hook' (in that order).
2264
2265
You can send text to the inferior ESS process from other buffers containing
2266
S source. The key bindings of these commands can be found by typing
2267
C-h m (help for mode) in the other buffers.
2268
`ess-eval-region' sends the current region to the ESS process.
2269
`ess-eval-buffer' sends the current buffer to the ESS process.
2270
`ess-eval-function' sends the current function to the ESS process.
2271
`ess-eval-line' sends the current line to the ESS process.
2272
`ess-beginning-of-function' and `ess-end-of-function' move the point to
2273
the beginning and end of the current S function.
2274
`ess-switch-to-ESS' switches the current buffer to the ESS process buffer.
2275
`ess-switch-to-end-of-ESS' switches the current buffer to the ESS process
2276
buffer and puts point at the end of it.
2277
2278
`ess-eval-region-and-go', `ess-eval-buffer-and-go',
2279
`ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S
2280
process buffer after sending their text.
2281
`ess-dump-object-into-edit-buffer' moves an S object into a temporary file
2282
and buffer for editing
2283
`ess-load-file' sources a file of commands to the ESS process.
2284
2285
Commands:
2286
Return after the end of the process' output sends the text from the
2287
end of process to point.
2288
Return before the end of the process' output copies the sexp ending at point
2289
to the end of the process' output, and sends it.
2290
Delete converts tabs to spaces as it moves back.
2291
C-M-q does Tab on each line starting within following expression.
2292
Paragraphs are separated only by blank lines. Crosshatches start comments.
2293
If you accidentally suspend your process, use \\[comint-continue-subjob]
2294
to continue it."
2295
(interactive)
2296
2297
(comint-mode)
2298
2299
(set (make-local-variable 'comint-input-sender) 'inferior-ess-input-sender)
2300
(set (make-local-variable 'process-connection-type) t)
2301
;; initialize all custom vars:
2302
(ess-setq-vars-local ess-customize-alist) ; (current-buffer))
2303
2304
;; If comint-process-echoes is t inferior-ess-input-sender
2305
;; recopies the input, otherwise not. VS[03-09-2012]: should be in customize-alist
2306
(set (make-local-variable 'comint-process-echoes)
2307
(not (member ess-language '("SAS" "XLS" "OMG" "julia")))) ;; these don't echo
2308
2309
(when (and (member ess-dialect '("R")) ;; S+ echoes!!
2310
(not (eq ess-eval-visibly t)))
2311
;; when 'nowait or nil, don't wait for process
2312
(setq comint-process-echoes nil))
2313
2314
(when comint-use-prompt-regexp ;; why comint is not setting this? bug?
2315
(set (make-local-variable 'inhibit-field-text-motion) t))
2316
2317
(unless inferior-ess-prompt ;; build when unset
2318
(setq inferior-ess-prompt
2319
(concat "\\("
2320
inferior-ess-primary-prompt
2321
(when inferior-ess-secondary-prompt "\\|")
2322
inferior-ess-secondary-prompt
2323
"\\)")))
2324
(setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
2325
(setq comint-get-old-input 'inferior-ess-get-old-input) ;; todo: this is R specific
2326
(add-hook 'comint-input-filter-functions 'ess-search-path-tracker nil 'local) ;; R and S specific
2327
2328
(setq major-mode 'inferior-ess-mode)
2329
(setq mode-name "iESS") ;(concat "iESS:" ess-dialect))
2330
(setq mode-line-process
2331
'(" ["
2332
ess--mode-line-process-indicator
2333
ess--local-mode-line-process-indicator
2334
"]: %s"))
2335
(use-local-map inferior-ess-mode-map)
2336
(if ess-mode-syntax-table
2337
(set-syntax-table ess-mode-syntax-table)
2338
;; FIXME: need to do something if not set! Get from the proper place!
2339
)
2340
2341
(ess-write-to-dribble-buffer
2342
(format "(i-ess 1): buf=%s, lang=%s, comint..echo=%s, comint..sender=%s,\n"
2343
(current-buffer) ess-language
2344
comint-process-echoes comint-input-sender))
2345
2346
(when (string= ess-language "S") ;; todo: what is this doing here?
2347
(local-set-key "\M-\r" 'ess-dirs))
2348
2349
;; Font-lock support
2350
;; AJR: This (the following local-var is already the case!
2351
;; KH sez: only in XEmacs :-(. (& Emacs 22.1, SJE).
2352
(when inferior-ess-font-lock-keywords ;; new system
2353
(setq inferior-ess-font-lock-defaults
2354
(ess--extract-default-fl-keywords inferior-ess-font-lock-keywords)))
2355
2356
(set (make-local-variable 'font-lock-defaults)
2357
'(inferior-ess-font-lock-defaults nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))
2358
2359
;; SJE 2007-06-28: Emacs 22.1 has a bug in that comint-mode will set
2360
;; this variable to t, when we need it to be nil. The Emacs 22
2361
;; solution to this bug is to use define-derived-mode to derive
2362
;; inferior-ess-mode from comint-mode. Not sure if we can go down
2363
;; that route yet. I've used the when condition so that if the var
2364
;; is nil, don't bother setting it -- as setting it will make a new
2365
;; local var.
2366
(when font-lock-keywords-only
2367
(setq font-lock-keywords-only nil))
2368
2369
;;; Completion support ----------------
2370
2371
;; SJE: comint-dynamic-complete-functions is regarded as a hook, rather
2372
;; than a regular variable. Note order of completion (thanks David Brahm):
2373
2374
(if (and (featurep 'emacs ) (>= emacs-major-version 24))
2375
(progn
2376
(remove-hook 'completion-at-point-functions 'comint-completion-at-point t) ;; reset the thook
2377
(add-hook 'completion-at-point-functions 'comint-c-a-p-replace-by-expanded-history nil 'local)
2378
(add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local))
2379
(add-hook 'comint-dynamic-complete-functions
2380
'ess-complete-filename 'append 'local)
2381
(add-hook 'comint-dynamic-complete-functions ;; only for R, is it ok?
2382
'ess-complete-object-name 'append 'local)
2383
(add-hook 'comint-dynamic-complete-functions
2384
'comint-replace-by-expanded-history 'append 'local)
2385
2386
;; When a hook is buffer-local, the dummy function `t' is added to
2387
;; indicate that the functions in the global value of the hook
2388
;; should also be run. SJE: I have removed this, as I think it
2389
;; interferes with our normal completion.
2390
(remove-hook 'comint-dynamic-complete-functions 't 'local))
2391
2392
;; (setq comint-completion-addsuffix nil) ; To avoid spaces after filenames
2393
;; KH: next 2 lines solve.
2394
(set (make-local-variable 'comint-completion-addsuffix)
2395
(cons "/" ""))
2396
2397
(setq comint-input-autoexpand t) ; Only for completion, not on input.
2398
2399
;; timers
2400
(add-hook 'ess-idle-timer-functions 'ess-cache-search-list nil 'local)
2401
(add-hook 'ess-idle-timer-functions 'ess-synchronize-dirs nil 'local)
2402
2403
;;; Keep <tabs> out of the code.
2404
(set (make-local-variable 'indent-tabs-mode) nil)
2405
2406
(set (make-local-variable 'paragraph-start)
2407
(concat inferior-ess-primary-prompt "\\|\^L"))
2408
(set (make-local-variable 'paragraph-separate) "\^L")
2409
2410
;; SJE Tue 28 Dec 2004: do not attempt to load object name db.
2411
;; (ess-load-object-name-db-file)
2412
;; (sleep-for 0.5)
2413
(make-local-variable 'kill-buffer-hook)
2414
(add-hook 'kill-buffer-hook 'ess-kill-buffer-function)
2415
(run-hooks 'inferior-ess-mode-hook)
2416
2417
(ess-write-to-dribble-buffer
2418
(format "(i-ess end): buf=%s, lang=%s, comint..echo=%s, comint..sender=%s,\n"
2419
(current-buffer) ess-language
2420
comint-process-echoes comint-input-sender))
2421
2422
(message
2423
(concat (substitute-command-keys
2424
"Type \\[describe-mode] for help on ESS version ")
2425
ess-version)))
2426
2427
;;*;; Commands used exclusively in inferior-ess-mode
2428
2429
;;;*;;; Main user commands
2430
2431
(defun inferior-ess-input-sender (proc string)
2432
(inferior-ess--interrupt-subjob-maybe proc)
2433
(let ((comint-input-filter-functions nil)) ; comint runs them, don't run twise.
2434
(if comint-process-echoes
2435
(ess-eval-linewise string nil nil ess-eval-empty)
2436
(ess-send-string proc string))))
2437
2438
2439
(defvar ess-help-arg-regexp "\\(['\"]?\\)\\([^,=)'\"]*\\)\\1"
2440
"Reg(ular) Ex(pression) of help(.) arguments. MUST: 2nd \\(.\\) = arg.")
2441
(defconst inferior-R--input-help (format "^ *help *(%s)" ess-help-arg-regexp))
2442
;; (defconst inferior-R-2-input-help (format "^ *\\? *%s" ess-help-arg-regexp))
2443
(defconst inferior-R--input-?-help-regexp
2444
"^ *\\(?:\\(?1:[a-zA-Z ]*?\\?\\{1,2\\}\\) *\\(?2:.+\\)\\)")
2445
(defconst inferior-R--page-regexp (format "^ *page *(%s)" ess-help-arg-regexp))
2446
2447
(defun ess-R--sanitize-help-topic (string)
2448
;; enclose help topics into `` to avoid ?while ?if etc hangs
2449
(if (string-match "\\([^:]*:+\\)\\(.*\\)$" string) ; treat foo::bar corectly
2450
(format "%s`%s`" (match-string 1 string) (match-string 2 string))
2451
(format "`%s`" string)))
2452
2453
(defun inferior-R-input-sender (proc string)
2454
(save-current-buffer
2455
(let ((help-match (and (string-match inferior-R--input-help string)
2456
(match-string 2 string)))
2457
(help-?-match (and (string-match inferior-R--input-?-help-regexp string)
2458
string))
2459
(page-match (and (string-match inferior-R--page-regexp string)
2460
(match-string 2 string))))
2461
(cond (help-match
2462
(ess-display-help-on-object help-match)
2463
(process-send-string proc "\n"))
2464
(help-?-match
2465
(if (string-match "\\?\\?\\(.+\\)" help-?-match)
2466
(ess--display-indexed-help-page (concat help-?-match "\n")
2467
"^\\([^ \t\n]+::[^ \t\n]+\\)[ \t\n]+"
2468
(format "*ess-apropos[%s](%s)*"
2469
ess-current-process-name (match-string 1 help-?-match))
2470
'appropos)
2471
(if (string-match "^ *\\? *\\([^:]+\\)$" help-?-match) ; help(foo::bar) doesn't work
2472
(ess-display-help-on-object (match-string 1 help-?-match))
2473
;; anything else we send to process almost unchanged
2474
(let ((help-?-match (and (string-match inferior-R--input-?-help-regexp string)
2475
(format "%s%s" (match-string 1 string)
2476
(ess-R--sanitize-help-topic (match-string 2 string))))))
2477
(ess-display-help-on-object help-?-match "%s\n"))))
2478
(process-send-string proc "\n"))
2479
(page-match
2480
(switch-to-buffer-other-window
2481
(ess-command (concat page-match "\n")
2482
(get-buffer-create (concat page-match ".rt"))))
2483
(R-transcript-mode)
2484
(process-send-string proc "\n"))
2485
2486
(t ;; normal command
2487
(inferior-ess-input-sender proc string)
2488
)))))
2489
2490
(defun inferior-ess-send-input ()
2491
"Sends the command on the current line to the ESS process."
2492
(interactive)
2493
(run-hooks 'ess-send-input-hook)
2494
;; (let ((proc (get-buffer-process (current-buffer))))
2495
;; (if (not proc)
2496
;; (user-error "Current buffer has no process")
2497
;; (let ((comint-process-echoes (or comint-process-echoes
2498
;; (< (point) (marker-position (process-mark proc))))))
2499
;; (comint-send-input))))
2500
(comint-send-input)
2501
(setq ess-object-list nil)) ;; Will be reconstructed from cache if needs be
2502
2503
(defun inferior-ess--goto-input-start:field ()
2504
"Move point to the begining of input skiping all continuation lines.
2505
If in the output field, goes to the begining of previous input
2506
field.
2507
Note: inferior-ess-secondary-prompt should match exactly.
2508
"
2509
(goto-char (field-beginning))
2510
;; move to the begining of non-output field
2511
(while (and (not (= (point) (point-min)))
2512
(eq (field-at-pos (point)) 'output))
2513
(goto-char (field-beginning nil t)))
2514
;; skip all secondary prompts
2515
(let ((pos (field-beginning (point) t))
2516
(secondary-prompt (concat "^" inferior-ess-secondary-prompt)))
2517
(while (and pos
2518
(if (eq (get-text-property pos 'field) 'output)
2519
(string-match secondary-prompt (field-string-no-properties pos))
2520
t))
2521
(goto-char pos)
2522
(setq pos (previous-single-property-change pos 'field))))
2523
)
2524
2525
(defun inferior-ess--goto-input-end:field ()
2526
"Move point to the end of input skiping all continuation lines.
2527
If in the output field, goes to the begining of previous input field.
2528
2529
NOTE: to be used only with fields, see `comint-use-prompt-regexp'.
2530
" ;; this func is not used but might be useful some day
2531
(goto-char (field-end))
2532
(let ((pos (point))
2533
(secondary-prompt (concat "^" inferior-ess-secondary-prompt)))
2534
(while (and pos
2535
(if (eq (get-text-property pos 'field) 'output)
2536
(string-match secondary-prompt (field-string-no-properties pos))
2537
t))
2538
(goto-char pos)
2539
(setq pos (next-single-property-change pos 'field)))
2540
))
2541
2542
(defun inferior-ess--get-old-input:field ()
2543
"Return the ESS command surrounding point (use with fields)."
2544
(save-excursion
2545
(if (eq (field-at-pos (point)) 'output)
2546
(if (called-interactively-p 'any)
2547
(error "No command on this line")
2548
;; else, just return ""
2549
"")
2550
(inferior-ess--goto-input-start:field)
2551
(let ((command (field-string-no-properties (point)))
2552
(pos (next-single-property-change (point) 'field ))
2553
(secondary-prompt (concat "^" inferior-ess-secondary-prompt)))
2554
(while (and pos
2555
(cond
2556
((eq (get-text-property pos 'field) 'input)
2557
(setq command (concat command "\n" (field-string-no-properties pos))))
2558
((eq (get-text-property pos 'field) 'output)
2559
(string-match secondary-prompt (field-string-no-properties pos)))
2560
(t)));; just skip if unknown
2561
(setq pos (next-single-property-change pos 'field)))
2562
command))))
2563
2564
;; todo: error when entering a multiline function
2565
;; check.integer <- function(N){
2566
;; is.integer(N) | !length(grep("[^[:digit:]]", as.character(N)))
2567
;; }
2568
(defun inferior-ess--goto-input-start:regexp ()
2569
"Move point to the begining of input skiping all continuation lines.
2570
If in the output field, goes to the begining of previous input.
2571
"
2572
(beginning-of-line)
2573
(unless (looking-at inferior-ess-prompt)
2574
(re-search-backward (concat "^" inferior-ess-prompt)))
2575
;; at bol
2576
(when (and inferior-ess-secondary-prompt
2577
(looking-at inferior-ess-secondary-prompt))
2578
(while (and (> (forward-line -1) -1)
2579
(looking-at inferior-ess-secondary-prompt))))
2580
(unless (looking-at inferior-ess-prompt)
2581
(ess-error "Beggining of input not found"))
2582
(comint-skip-prompt)
2583
)
2584
2585
(defun inferior-ess--get-old-input:regexp ()
2586
"Return the ESS command surrounding point (use regexp)."
2587
;;VS[03-09-2012]: This should not rise errors!! Troubles comint-interrupt-subjob
2588
(save-excursion
2589
(let* ((inhibit-field-text-motion t)
2590
command)
2591
(beginning-of-line)
2592
(when (and inferior-ess-secondary-prompt
2593
(looking-at inferior-ess-secondary-prompt))
2594
(inferior-ess--goto-input-start:regexp))
2595
(beginning-of-line)
2596
(if (looking-at inferior-ess-prompt) ; cust.var, might not include sec-prompt
2597
(progn
2598
(comint-skip-prompt)
2599
(setq command (buffer-substring-no-properties (point) (point-at-eol)))
2600
(when inferior-ess-secondary-prompt
2601
(while (progn (forward-line 1)
2602
(looking-at inferior-ess-secondary-prompt))
2603
(re-search-forward inferior-ess-secondary-prompt (point-at-eol))
2604
(setq command (concat command "\n"
2605
(buffer-substring-no-properties (point) (point-at-eol))))
2606
))
2607
(forward-line -1)
2608
(setq ess-temp-point (point)) ;; this is ugly, used by transcript
2609
command)
2610
(message "No command at this point")
2611
"")
2612
)))
2613
2614
(defun inferior-ess-get-old-input ()
2615
"Return the ESS command surrounding point."
2616
(if comint-use-prompt-regexp
2617
(inferior-ess--get-old-input:regexp)
2618
(inferior-ess--get-old-input:field))
2619
)
2620
2621
;;;*;;; Hot key commands
2622
2623
(defun ess-execute-objects (posn)
2624
"Send the objects() command to the ESS process.
2625
By default, gives the objects at position 1.
2626
A prefix argument toggles the meaning of `ess-execute-in-process-buffer'.
2627
A prefix argument of 2 or more means get objects for that position.
2628
A negative prefix argument gets the objects for that position
2629
and toggles `ess-execute-in-process-buffer' as well."
2630
(interactive "P")
2631
(ess-make-buffer-current)
2632
(let* ((num-arg (if (listp posn)
2633
(if posn -1 1)
2634
(prefix-numeric-value posn)))
2635
(the-posn (if (< num-arg 0) (- num-arg) num-arg))
2636
(invert (< num-arg 0))
2637
(the-command (format inferior-ess-objects-command the-posn ".*"))
2638
(the-message (concat ">>> Position "
2639
(number-to-string the-posn)
2640
" ("
2641
(nth (1- the-posn) (ess-search-list))
2642
")\n")))
2643
(ess-execute the-command invert "S objects" the-message)))
2644
2645
(defun ess-execute-search (invert)
2646
"Send the `inferior-ess-search-list-command' command to the `ess-language' process.
2647
[search(..) in S]"
2648
(interactive "P")
2649
(ess-execute inferior-ess-search-list-command invert "S search list"))
2650
2651
;; FIXME --- this *only* works in S / S-plus; not in R
2652
;; ----- ("at least" is not assigned to any key by default)
2653
(defun ess-execute-attach (dir &optional posn)
2654
"Attach a directory in the `ess-language' process with the attach() command.
2655
When used interactively, user is prompted for DIR to attach and
2656
prefix argument is used for POSN (or 2, if absent.)
2657
Doesn't work for data frames."
2658
(interactive "Attach directory: \nP")
2659
(ess-execute (concat "attach(\""
2660
(directory-file-name (expand-file-name dir))
2661
"\""
2662
(if posn (concat "," (number-to-string
2663
(prefix-numeric-value posn))))
2664
")") 'buffer)
2665
(ess-process-put 'sp-for-help-changed? t))
2666
2667
(defun ess-execute-screen-options ()
2668
"Cause S to set the \"width\" option to 1 less than the window width.
2669
Also sets the \"length\" option to 99999.
2670
This is a good thing to put in `ess-post-run-hook' --- for the S dialects."
2671
(interactive)
2672
(if (string= ess-language "S")
2673
(ess-eval-linewise (format "options(width=%d, length=99999)"
2674
(- (window-width) 2))
2675
nil nil nil 'wait-prompt)))
2676
2677
(defun ess-execute (command &optional invert buff message)
2678
"Send a command to the ESS process.
2679
A newline is automatically added to COMMAND. Prefix arg (or second arg
2680
INVERT) means invert the meaning of
2681
`ess-execute-in-process-buffer'. If INVERT is 'buffer, output is
2682
forced to go to the process buffer. If the output is going to a
2683
buffer, name it *BUFF*. This buffer is erased before use. Optional
2684
fourth arg MESSAGE is text to print at the top of the buffer (defaults
2685
to the command if BUFF is not given.)"
2686
(interactive (list
2687
;; simpler way to set proc name in mb?
2688
(let ((enable-recursive-minibuffers t)
2689
(proc-name (progn (ess-force-buffer-current)
2690
ess-local-process-name)))
2691
(with-current-buffer (get-buffer " *Minibuf-1*") ;; fixme: hardcoded name
2692
(setq ess-local-process-name proc-name))
2693
(read-from-minibuffer "Execute> " nil
2694
ess-mode-minibuffer-map))
2695
current-prefix-arg))
2696
(ess-make-buffer-current)
2697
(let ((the-command (concat command "\n"))
2698
(buff-name (concat "*" (or buff "ess-output") "*"))
2699
(in-pbuff (if invert (or (eq invert 'buffer)
2700
(not ess-execute-in-process-buffer))
2701
ess-execute-in-process-buffer)))
2702
(if in-pbuff
2703
(ess-eval-linewise the-command)
2704
(let ((buff (ess-create-temp-buffer buff-name)))
2705
(ess-command the-command buff);; sleep?
2706
(with-current-buffer buff
2707
(goto-char (point-min))
2708
(if message (insert message)
2709
(if buff nil
2710
;; Print the command in the buffer if it has not been
2711
;; given a special name
2712
(insert "> " the-command)))
2713
(setq ess-local-process-name ess-current-process-name))
2714
(ess-display-temp-buffer buff)))))
2715
2716
;;;*;;; Quitting
2717
2718
(defun ess-quit ()
2719
"Issue an exiting command to the inferior process, additionally
2720
also running \\[ess-cleanup]. For R, runs \\[ess-quit-r], see there."
2721
(interactive)
2722
(if (string-equal ess-dialect "R")
2723
(ess-quit-r)
2724
;; else: non-R
2725
(ess-force-buffer-current "Process to quit: " nil 'no-autostart)
2726
(ess-make-buffer-current)
2727
(let ((sprocess (ess-get-process ess-current-process-name)))
2728
(if (not sprocess) (error "No ESS process running"))
2729
(when (y-or-n-p (format "Really quit ESS process %s? " sprocess))
2730
(ess-cleanup)
2731
(goto-char (marker-position (process-mark sprocess)))
2732
(insert inferior-ess-exit-command)
2733
(process-send-string sprocess inferior-ess-exit-command)
2734
;;SJE - suggest no need to rename buffer upon exit.
2735
;;(rename-buffer (concat (buffer-name) "-exited") t)
2736
))))
2737
2738
(defun ess-quit-r ()
2739
"Issue an exiting command to an inferior R process, and optionally clean up.
2740
This version is for killing *R* processes; it asks the extra question
2741
regarding whether the workspace image should be saved."
2742
(ess-force-buffer-current "Process to quit: " nil 'no-autostart)
2743
(ess-make-buffer-current)
2744
(let (cmd
2745
;;Q response
2746
(sprocess (ess-get-process ess-current-process-name)))
2747
(if (not sprocess) (error "No ESS process running"))
2748
;;Q (setq response (completing-read "Save workspace image? "
2749
;;Q '( ( "yes".1) ("no" . 1) ("cancel" . 1))
2750
;;Q nil t))
2751
;;Q (if (string-equal response "")
2752
;;Q (setq response "default")); which will ask again (in most situations)
2753
;;Q (unless (string-equal response "cancel")
2754
(ess-cleanup)
2755
;;Q (setq cmd (format "q(\"%s\")\n" response))
2756
(setq cmd "q()\n")
2757
(goto-char (marker-position (process-mark sprocess)))
2758
(process-send-string sprocess cmd)
2759
;;(rename-buffer (concat (buffer-name) "-exited") t)
2760
;;Q )
2761
))
2762
2763
(defun ess-abort ()
2764
"Kill the ESS process, without executing .Last or terminating devices.
2765
If you want to finish your session, use \\[ess-quit] instead."
2766
;;; Provided as a safety measure over the default binding of C-c C-z in
2767
;;; comint-mode-map.
2768
(interactive)
2769
(ding)
2770
(message "WARNING: \\[inferior-ess-exit-command] will not be executed and graphics devices won't finish properly!")
2771
(sit-for 2)
2772
(if (yes-or-no-p "Still abort? ")
2773
(comint-quit-subjob)
2774
(message "Good move.")))
2775
2776
(defun ess-cleanup ()
2777
"Possibly kill or offer to kill, depending on the value of
2778
`ess-S-quit-kill-buffers-p', all buffers associated with this ESS process.
2779
Leaves you in the ESS process buffer. It's a good idea to run this
2780
before you quit. It is run automatically by \\[ess-quit]."
2781
(interactive)
2782
(let ((the-procname (or (ess-make-buffer-current) ess-local-process-name)))
2783
(unless the-procname
2784
(error "I don't know which ESS process to clean up after!"))
2785
(when
2786
(or (eq ess-S-quit-kill-buffers-p t)
2787
(and
2788
(eq ess-S-quit-kill-buffers-p 'ask)
2789
(y-or-n-p
2790
(format
2791
"Delete all buffers associated with process %s? " the-procname))))
2792
(dolist (buf (buffer-list))
2793
(with-current-buffer buf
2794
;; Consider buffers for which ess-local-process-name is
2795
;; the same as the-procname
2796
(when (and (not (get-buffer-process buf))
2797
ess-local-process-name
2798
(equal ess-local-process-name the-procname))
2799
(kill-buffer buf)))))
2800
(ess-switch-to-ESS nil)))
2801
2802
(defun ess-kill-buffer-function ()
2803
"Function run just before an ESS process buffer is killed."
2804
;; This simply deletes the buffers process to avoid an Emacs bug
2805
;; where the sentinel is run *after* the buffer is deleted
2806
(let ((proc (get-buffer-process (current-buffer))))
2807
(if (processp proc) (delete-process proc))))
2808
2809
2810
(defun ess-list-object-completions nil
2811
"List all possible completions of the object name at point."
2812
(interactive)
2813
(ess-complete-object-name))
2814
2815
;;;*;;; Support functions
2816
(defun ess-extract-onames-from-alist (alist posn &optional force)
2817
"Return the object names in position POSN of ALIST.
2818
ALIST is an alist like `ess-sl-modtime-alist'. POSN should be in 1 .. (length
2819
ALIST). If optional third arg FORCE is t, the corresponding element
2820
of the search list is re-read. Otherwise it is only re-read if it's a
2821
directory and has been modified since it was last read."
2822
(let* ((entry (nth (1- posn) alist))
2823
(dir (car entry))
2824
(timestamp (car (cdr entry)))
2825
(new-modtime (ess-dir-modtime dir)))
2826
;; Refresh the object listing if necessary
2827
(if (or force (not (equal new-modtime timestamp)))
2828
(setcdr (cdr entry) (ess-object-names dir posn)))
2829
(cdr (cdr entry))))
2830
2831
(defun ess-dir-modtime (dir)
2832
"Return the last modtime if DIR is a directory, and nil otherwise."
2833
(and ess-filenames-map
2834
(file-directory-p dir)
2835
(nth 5 (file-attributes dir))))
2836
2837
(defun ess-object-modtime (object)
2838
"Return the modtime of the S object OBJECT (a string).
2839
Searches along the search list for a file named OBJECT and returns its modtime
2840
Returns nil if that file cannot be found, i.e., for R or any non-S language!"
2841
(let ((path (ess-search-list))
2842
result)
2843
(while (and (not result) path)
2844
(setq result (file-attributes
2845
(concat (file-name-as-directory (car path))
2846
object)))
2847
(setq path (cdr path)))
2848
(nth 5 result)))
2849
2850
(defun ess-modtime-gt (mod1 mod2)
2851
"Return t if MOD1 is later than MOD2."
2852
(and mod1
2853
(or (> (car mod1) (car mod2))
2854
(and (= (car mod1) (car mod2))
2855
(> (car (cdr mod1)) (car (cdr mod2)))))))
2856
2857
(defun ess-get-object-list (name &optional exclude-first)
2858
"Return a list of current S object names associated with process NAME,
2859
using `ess-object-list' if that is non-nil.
2860
If exclude-first is non-nil, don't return objects in first positon (.GlobalEnv)."
2861
(or ess-object-list ;; <<- MM: this is now always(?) nil; we cache the *-modtime-alist
2862
(with-current-buffer (process-buffer (ess-get-process name))
2863
(ess-make-buffer-current)
2864
(ess-write-to-dribble-buffer (format "(get-object-list %s) .." name))
2865
(if (or (not ess-sl-modtime-alist)
2866
(ess-process-get 'sp-for-help-changed?))
2867
(progn (ess-write-to-dribble-buffer "--> (ess-get-modtime-list)\n")
2868
(ess-get-modtime-list))
2869
;;else
2870
(ess-write-to-dribble-buffer " using existing ess-sl-modtime-alist\n")
2871
)
2872
(let* ((alist ess-sl-modtime-alist)
2873
(i 2)
2874
(n (length alist))
2875
result)
2876
(ess-write-to-dribble-buffer (format " (length alist) : %d\n" n))
2877
(unless exclude-first
2878
;; re-read of position 1 :
2879
(setq result (ess-extract-onames-from-alist alist 1 'force)))
2880
(ess-write-to-dribble-buffer
2881
(format " have re-read pos=1: -> length %d\n" (length result)))
2882
;; Re-read remaining directories if necessary.
2883
(while (<= i n)
2884
(setq result
2885
(append result
2886
(ess-extract-onames-from-alist alist i)))
2887
(setq i (1+ i)))
2888
(setq ess-object-list (ess-uniq-list result))))))
2889
2890
(defun ess-get-words-from-vector (command &optional no-prompt-check wait proc)
2891
"Evaluate the S command COMMAND, which returns a character vector.
2892
Return the elements of the result of COMMAND as an alist of
2893
strings. COMMAND should have a terminating newline. WAIT is
2894
passed to `ess-command'.
2895
2896
To avoid truncation of long vectors, wrap your
2897
command (%s) like this, or a version with explicit options(max.print=1e6):
2898
2899
local({ out <- try({%s}); print(out, max=1e6) })\n
2900
"
2901
(let ((tbuffer (get-buffer-create
2902
" *ess-get-words*")); initial space: disable-undo
2903
words)
2904
(ess-if-verbose-write (format "ess-get-words*(%s).. " command))
2905
(ess-command command tbuffer 'sleep no-prompt-check wait proc)
2906
(ess-if-verbose-write " [ok] ..")
2907
(with-current-buffer tbuffer
2908
(goto-char (point-min))
2909
;; this is bad, only R specific test
2910
;; (if (not (looking-at "[+ \t>\n]*\\[1\\]"))
2911
;; (progn (ess-if-verbose-write "not seeing \"[1]\".. ")
2912
;; (setq words nil)
2913
;; )
2914
(while (re-search-forward "\"\\(\\(\\\\\\\"\\|[^\"]\\)*\\)\"\\( \\|$\\)" nil t);match \"
2915
(setq words (cons (buffer-substring (match-beginning 1)
2916
(match-end 1)) words))))
2917
(ess-if-verbose-write
2918
(if (> (length words) 5)
2919
(format " |-> (length words)= %d\n" (length words))
2920
(format " |-> words= '%s'\n" words)))
2921
(reverse words)))
2922
2923
(defun ess-compiled-dir (dir)
2924
"Return non-nil if DIR is an S object directory with special files.
2925
I.e. if the filenames in DIR are not representative of the objects in DIR."
2926
(or (file-exists-p (concat (file-name-as-directory dir) "___nonfile"))
2927
(file-exists-p (concat (file-name-as-directory dir) "__BIGIN"))
2928
(file-exists-p (concat (file-name-as-directory dir) "___NONFI"))))
2929
2930
(defun ess-object-names (obj &optional pos)
2931
"Return alist of S object names in directory (or object) OBJ.
2932
If OBJ is a directory name (begins with `/') returns a listing of that dir.
2933
This may use the search list position POS if necessary.
2934
If OBJ is an object name, returns result of the command `inferior-ess-safe-names-command'.
2935
If POS is supplied return the result of the command in `inferior-ess-objects-command'
2936
If OBJ is nil or not a directory, POS must be supplied.
2937
In all cases, the value is an list of object names."
2938
2939
(cond ((and (stringp obj)
2940
(string-match-p "ESSR" obj))
2941
nil)
2942
;; FIXME: in both cases below, the same fallback "objects(POS)" is used -- merge!
2943
((and obj (file-accessible-directory-p obj))
2944
;; Check the pre-compiled object list in ess-object-name-db first
2945
2946
;; FIXME: If used at all, ess-object-name-db should not only
2947
;; ----- be used in the directory case !!
2948
(or (cdr-safe (assoc obj ess-object-name-db))
2949
;; Take a directory listing
2950
(and ess-filenames-map
2951
;; first try .Data subdirectory:
2952
;;FIXME: move ".Data" or ``this function'' to ess-sp6-d.el etc:
2953
(let ((dir (concat (file-name-as-directory obj) ".Data")))
2954
(if (not (file-accessible-directory-p dir))
2955
(setq dir obj))
2956
(and (not (ess-compiled-dir dir))
2957
(directory-files dir))))
2958
;; Get objects(pos) instead
2959
(and (or (ess-write-to-dribble-buffer
2960
(format "(ess-object-names ..): directory %s not used\n" obj))
2961
t)
2962
pos
2963
(ess-get-words-from-vector
2964
(format inferior-ess-objects-command pos)))))
2965
((and obj ;; want names(obj)
2966
(ess-get-words-from-vector
2967
(format inferior-ess-safe-names-command obj))))
2968
(pos
2969
(ess-get-words-from-vector
2970
(format inferior-ess-objects-command pos)))))
2971
2972
(defun ess-slot-names (obj)
2973
"Return alist of S4 slot names of S4 object OBJ."
2974
(ess-get-words-from-vector (format "slotNames(%s)\n" obj)))
2975
2976
2977
;;; SJE: Wed 29 Dec 2004 --- remove this function.
2978
;;; rmh: Wed 5 Jan 2005 --- bring it back for use on Windows
2979
(defun ess-create-object-name-db ()
2980
"Create a database of object names in standard S directories. This
2981
database is saved in the file specified by `ess-object-name-db-file',
2982
and is loaded when `ess-mode' is loaded. It defines the variable
2983
`ess-object-name-db', which is used for completions.
2984
2985
Before you call this function, modify the S search list so that it contains
2986
all the non-changing (i.e. system) S directories. All positions of the search
2987
list except for position 1 are searched and stored in the database.
2988
2989
After running this command, you should move ess-namedb.el to a directory in
2990
the `load-path'."
2991
(interactive)
2992
(setq ess-object-name-db nil)
2993
(let ((search-list (cdr (ess-search-list)))
2994
(pos 2)
2995
name
2996
(buffer (get-buffer-create " *ess-db*"))
2997
(temp-object-name-db nil)
2998
(temp-object-name-db-file ess-object-name-db-file))
2999
3000
(ess-write-to-dribble-buffer
3001
(format "(object db): search-list=%s \n " search-list))
3002
(while search-list
3003
(message "Searching %s" (car search-list))
3004
(setq temp-object-name-db (cons (cons (car search-list)
3005
(ess-object-names nil pos))
3006
temp-object-name-db))
3007
(setq search-list (cdr search-list))
3008
(ess-write-to-dribble-buffer
3009
(format "(object db): temp-obj-name-db=%s \n pos=%s"
3010
temp-object-name-db pos))
3011
(setq pos (1+ pos)))
3012
3013
(with-current-buffer buffer
3014
(erase-buffer)
3015
(insert "(setq ess-object-name-db '")
3016
(prin1 temp-object-name-db (current-buffer))
3017
(insert ")\n")
3018
(setq name (expand-file-name ess-object-name-db-file))
3019
(write-region (point-min) (point-max) name)
3020
(message "Wrote %s" name))
3021
(kill-buffer buffer)
3022
(setq ess-object-name-db temp-object-name-db)))
3023
3024
(defun ess-resynch nil
3025
"Reread all directories/objects in variable `ess-search-list' to
3026
form completions."
3027
(interactive)
3028
3029
(if (ess-make-buffer-current) nil
3030
(error "Not an ESS process buffer"))
3031
(setq ess-sl-modtime-alist nil)
3032
(setq ess-object-list nil)
3033
(setq ess-object-name-db nil) ; perhaps it would be better to reload?
3034
(ess-process-put 'sp-for-help-changed? t)
3035
(ess-get-modtime-list))
3036
3037
(defun ess-filename-completion ()
3038
;; > emacs 24
3039
"Return completion only within string or comment."
3040
(save-restriction ;; explicitely handle inferior-ess
3041
(ignore-errors
3042
(when (and (eq major-mode 'inferior-ess-mode)
3043
(> (point) (process-mark (get-buffer-process (current-buffer)))))
3044
(narrow-to-region (process-mark (get-buffer-process (current-buffer)))
3045
(point-max))))
3046
(when (ess-inside-string-or-comment-p (point))
3047
(append (comint-filename-completion) '(:exclusive no)))))
3048
3049
3050
(defun ess-complete-filename ()
3051
"Do file completion only within strings."
3052
(save-restriction ;; explicitely handle inferior-ess
3053
(ignore-errors
3054
(when (and (eq major-mode 'inferior-ess-mode)
3055
(> (point) (process-mark (get-buffer-process (current-buffer)))))
3056
(narrow-to-region (process-mark (get-buffer-process (current-buffer)))
3057
(point-max))))
3058
(when (or (ess-inside-string-or-comment-p (point))) ;; usable within ess-mode as well
3059
(comint-dynamic-complete-filename))))
3060
3061
(defun ess-after-pathname-p nil
3062
;; Heuristic: after partial pathname if it looks like we're in a
3063
;; string, and that string looks like a pathname. Not the best for
3064
;; use with unix() (or it's alias, !). Oh well.
3065
(save-excursion
3066
(save-match-data
3067
(let ((opoint (point)))
3068
(and (re-search-backward "\\(\"\\|'\\)[~/#$.a-zA-Z0-9][^ \t\n\"']*"
3069
nil t)
3070
(eq opoint (match-end 0)))))))
3071
3072
;;*;; Functions handling the search list
3073
3074
(defun ess-search-list (&optional force-update)
3075
"Return the current search list as a list of strings.
3076
Elements which are apparently directories are expanded to full dirnames.
3077
Don't try to use cache if FORCE-UPDATE is non-nil.
3078
3079
Is *NOT* used by \\[ess-execute-search],
3080
but by \\[ess-resynch], \\[ess-get-object-list], \\[ess-get-modtime-list],
3081
\\[ess-execute-objects], \\[ess-object-modtime], \\[ess-create-object-name-db],
3082
and (indirectly) by \\[ess-get-help-files-list]."
3083
(with-current-buffer
3084
(ess-get-process-buffer ess-current-process-name);to get *its* local vars
3085
(let ((result nil)
3086
(slist (ess-process-get 'search-list))
3087
(tramp-mode nil)) ;; hack for bogus file-directory-p below
3088
(if (and slist
3089
(not force-update)
3090
(not (ess-process-get 'sp-for-help-changed?)))
3091
slist
3092
;; else, re-compute:
3093
(ess-write-to-dribble-buffer " (ess-search-list ... ) ")
3094
(let ((tbuffer (get-buffer-create " *search-list*"))
3095
(homedir ess-directory)
3096
(my-search-cmd inferior-ess-search-list-command); from ess-buffer
3097
elt)
3098
(ess-command my-search-cmd tbuffer 0.05); <- sleep for dde only; does (erase-buffer)
3099
(with-current-buffer tbuffer
3100
;; guaranteed by the initial space in its name: (buffer-disable-undo)
3101
(goto-char (point-min))
3102
(ess-write-to-dribble-buffer
3103
(format "after '%s', point-max=%d\n" my-search-cmd (point-max)))
3104
(while (re-search-forward "\"\\([^\"]*\\)\"" nil t)
3105
(setq elt (buffer-substring (match-beginning 1) (match-end 1)))
3106
;;Dbg: (ess-write-to-dribble-buffer (format " .. elt= %s \t" elt))
3107
(if (and (string-match "^[^/]" elt)
3108
(file-directory-p (concat ess-directory elt)))
3109
(progn
3110
;;Dbg: (ess-write-to-dribble-buffer "*IS* directory\n")
3111
(setq elt (concat homedir elt)))
3112
;;else
3113
;;dbg
3114
;;- (ess-write-to-dribble-buffer "not dir.\n")
3115
)
3116
(setq result (append result (list elt))))
3117
(kill-buffer tbuffer)))
3118
result))))
3119
3120
;;; ess-sl-modtime-alist is a list with elements as follows:
3121
;;; * key (directory or object name)
3122
;;; * modtime (list of 2 integers)
3123
;;; * name, name ... (accessible objects in search list posn labeled by key)
3124
;;; It is a buffer-local variable (belonging to e.g. *R*, *S+6*, .. etc)
3125
;;; and has the same number of elements and is in the same order as the
3126
;;; S search list
3127
3128
(defun ess-get-modtime-list ()
3129
"Record the modification times of the directories in the search list,
3130
and the objects in those directories.
3131
The result is stored in `ess-sl-modtime-alist'."
3132
;; Operation applies to process of current buffer
3133
(let* ((searchlist (ess-search-list))
3134
(index 1)
3135
posn
3136
newalist)
3137
(while searchlist
3138
(setq posn (car searchlist))
3139
(setq newalist
3140
(append
3141
newalist
3142
(list (or (assoc posn ess-sl-modtime-alist)
3143
(append
3144
(list posn (ess-dir-modtime posn))
3145
(prog2
3146
(message "Forming completions for %s..." posn)
3147
(ess-object-names posn index)
3148
(message "Forming completions for %s...done" posn)
3149
))))))
3150
(setq index (1+ index))
3151
(setq searchlist (cdr searchlist)))
3152
;;DBG:
3153
(ess-write-to-dribble-buffer
3154
(format "(ess-get-modtime-list): created new alist of length %d\n"
3155
(length newalist)));; todo : also give length of components!
3156
3157
(setq ess-sl-modtime-alist newalist)))
3158
3159
3160
(defun ess-search-path-tracker (str)
3161
"Check if input STR changed the search path.
3162
This function monitors user input to the inferior ESS process so
3163
that Emacs can keep the process variable 'search-list' up to
3164
date. `ess-completing-read' in \\[ess-read-object-name] uses this
3165
list indirectly when it prompts for help or for an object to
3166
dump.
3167
3168
From ESS 12.09 this is not necessary anymore, as the search path
3169
is checked on idle time. It is kept for robustness and backward
3170
compatibility only."
3171
(when ess-change-sp-regexp
3172
(if (string-match ess-change-sp-regexp str)
3173
(ess-process-put 'sp-for-help-changed? t))))
3174
3175
; Miscellaneous routines
3176
3177
;;;*;;; Routines for reading object names
3178
(defun ess-read-object-name (p-string)
3179
"Read an S object name from the minibuffer with completion, and return it.
3180
P-STRING is the prompt string."
3181
(let* ((default (ess-read-object-name-dump))
3182
(object-list (ess-get-object-list ess-local-process-name))
3183
(spec (ess-completing-read p-string object-list nil nil nil nil default)))
3184
(list (cond
3185
((string= spec "") default)
3186
(t spec)))))
3187
3188
(defun ess-read-object-name-default ()
3189
"Return the object name at point, or nil if none."
3190
(condition-case ()
3191
(save-excursion
3192
;; The following line circumvents an 18.57 bug in following-char
3193
(if (eobp) (backward-char 1)) ; Hopefully buffer is not empty!
3194
;; Get onto a symbol
3195
(catch 'nosym ; bail out if there's no symbol at all before point
3196
(while (/= (char-syntax (following-char)) ?w)
3197
(if (bobp) (throw 'nosym nil) (backward-char 1)))
3198
(let*
3199
((end (progn (forward-sexp 1) (point)))
3200
(beg (progn (backward-sexp 1) (point))))
3201
(buffer-substring-no-properties beg end))))
3202
(error nil)))
3203
3204
(defun ess-read-object-name-dump ()
3205
"Return the object name at point, or \"Temporary\" if none."
3206
(condition-case ()
3207
(save-excursion
3208
;; The following line circumvents an 18.57 bug in following-char
3209
(if (eobp) (backward-char 1)) ; Hopefully buffer is not empty!
3210
;; Get onto a symbol
3211
(catch 'nosym ; bail out if there's no symbol at all before point
3212
(while (/= (char-syntax (following-char)) ?w)
3213
(if (bobp) (throw 'nosym nil) (backward-char 1)))
3214
(let*
3215
((end (progn (forward-sexp 1) (point)))
3216
(beg (progn (backward-sexp 1) (point)))
3217
(object-name (buffer-substring beg end)))
3218
(or object-name "Temporary"))))
3219
(error nil)))
3220
3221
;;;; start of ess-smart-operators
3222
;;;; inspired by slime repl shortcuts
3223
3224
(defvar ess--handy-history nil)
3225
3226
(defun ess-handy-commands ()
3227
"Request and execute a command from `ess-handy-commands' list."
3228
(interactive)
3229
(let* ((commands (or ess--local-handy-commands
3230
ess-handy-commands))
3231
(hist (and (assoc (car ess--handy-history)
3232
commands)
3233
(car ess--handy-history))))
3234
(call-interactively
3235
(cdr (assoc (ess-completing-read "Execute"
3236
(sort (mapcar 'car commands)
3237
'string-lessp) nil t nil
3238
'ess--handy-history hist)
3239
commands)))))
3240
3241
(defun ess-smart-comma ()
3242
"If comma is invoked at the process marker of an ESS inferior
3243
buffer, request and execute a command from `ess-handy-commands'
3244
list."
3245
(interactive)
3246
(let ((proc (get-buffer-process (current-buffer))))
3247
(if (and proc
3248
(eq (point) (marker-position (process-mark proc))))
3249
(ess-handy-commands)
3250
(if ess-smart-operators
3251
(progn
3252
(delete-horizontal-space)
3253
(insert ", ")
3254
(unless (eq major-mode 'inferior-ess-mode)
3255
(ess-indent-line)))
3256
(insert ","))
3257
)))
3258
3259
; directories
3260
(defun ess-set-working-directory (path &optional no-error)
3261
"Set the current working directory to PATH for both ESS
3262
subprocess and Emacs buffer `default-directory'."
3263
(interactive "DChange working directory to: ")
3264
(if ess-setwd-command
3265
(let* ((remote (file-remote-p path))
3266
(path (if remote
3267
(tramp-sh-handle-expand-file-name path)
3268
path))
3269
(lpath (if remote
3270
(with-parsed-tramp-file-name path v v-localname)
3271
path)))
3272
(ess-eval-linewise (format ess-setwd-command lpath))
3273
;; use file-name-as-directory to ensure it has trailing /
3274
(setq default-directory (file-name-as-directory path)))
3275
(unless no-error
3276
(error "Not implemented for dialect %s" ess-dialect))))
3277
3278
(defalias 'ess-change-directory 'ess-set-working-directory)
3279
3280
(defun ess-get-working-directory (&optional no-error)
3281
"Retrive the current working directory from the current ess process."
3282
(if ess-getwd-command
3283
(car (ess-get-words-from-vector ess-getwd-command))
3284
(unless no-error
3285
(error "Not implemented for dialect %s" ess-dialect))))
3286
3287
3288
(defun ess-synchronize-dirs ()
3289
"Set Emacs' current directory to be the same as the subprocess directory.
3290
Used in `ess-idle-timer-functions'."
3291
(when (and ess-can-eval-in-background
3292
ess-getwd-command)
3293
(ess-when-new-input last-sync-dirs
3294
(ess-if-verbose-write "\n(ess-synchronize-dirs)\n")
3295
(setq default-directory
3296
(car (ess-get-words-from-vector ess-getwd-command)))
3297
default-directory
3298
)))
3299
3300
(defun ess-dirs ()
3301
"Set Emacs' current directory to be the same as the *R* process.
3302
"
3303
;; Note: This function is not necessary anymore. The Emacs
3304
;; default-directory and subprocess working directory are
3305
;; synchronized automatically.
3306
(interactive)
3307
(let ((dir (car (ess-get-words-from-vector "getwd()\n"))))
3308
(message "(ESS / default) directory: %s" dir)
3309
(setq default-directory (file-name-as-directory dir))))
3310
3311
;; (make-obsolete 'ess-dirs 'ess-synchronize-dirs "ESS 12.09")
3312
3313
;; search path
3314
(defun ess--mark-search-list-as-changed ()
3315
"Internal. Marks all the search-list related variables as
3316
changed."
3317
;; other guys might track their own
3318
(ess-process-put 'sp-for-help-changed? t)
3319
(ess-process-put 'sp-for-ac-changed? t))
3320
3321
(defun ess-cache-search-list ()
3322
"Used in `ess-idle-timer-functions', to set
3323
search path related variables."
3324
(when (and ess-can-eval-in-background
3325
inferior-ess-search-list-command)
3326
(ess-when-new-input last-cache-search-list
3327
(let ((path (ess-search-list 'force))
3328
(old-path (process-get *proc* 'search-list)))
3329
(when (not (equal path old-path))
3330
(process-put *proc* 'search-list path)
3331
(ess--mark-search-list-as-changed)
3332
path
3333
)))))
3334
3335
3336
;;*;; Temporary buffer handling
3337
3338
;; (defun ess-create-temp-buffer (name)
3339
;; "Create an empty buffer called NAME, but doesn't display it."
3340
;; (let ((buff (get-buffer-create name)))
3341
;; (save-excursion
3342
;; (set-buffer buff)
3343
;; (erase-buffer))
3344
;; buff))
3345
3346
3347
;; Ed Kademan's version:
3348
;; From: Ed Kademan <[email protected]>
3349
;; Subject: Re: ess-mode 5.1.16; search list
3350
;; To: [email protected] (A.J. Rossini)
3351
;; Cc: Martin Maechler <[email protected]>, [email protected]
3352
;; Date: 26 Jul 2000 16:12:12 -0400
3353
3354
;; Dear Tony Rossini,
3355
3356
;; I was having trouble looking at the search list under ess. When I
3357
;; started up multiple inferior processes---each for a different
3358
;; dialect---ess-mode would issue the wrong variant of the "search"
3359
;; command when I typed C-c C-s. In case it is useful let me tell you
3360
;; what I did to get it to work for me.
3361
3362
;; I added the component:
3363
;; (inferior-ess-search-list-command . "search()\n")
3364
;; to S+3-customize-alist and R-customize-alist, and then I redefined the
3365
;; ess-create-temp-buffer function as follows:
3366
(defun ess-create-temp-buffer (name)
3367
"Create an empty buffer called NAME."
3368
(let ((buff (get-buffer-create name))
3369
(elca (eval ess-local-customize-alist)))
3370
(with-current-buffer buff
3371
(erase-buffer)
3372
(ess-setq-vars-local elca buff))
3373
buff))
3374
;;These two steps seem to insure that the temporary buffer in which the
3375
;;search results appear has the correct version of the local variables.
3376
;;I am not that well acquainted with the ess code and don't know whether
3377
;;this is a good fundamental way of fixing the problem, or even whether
3378
;;or not this breaks some other feature of ess-mode that I never use.
3379
;;Thanks for listening.
3380
;;Ed K.
3381
;;--
3382
;;Ed Kademan 508.651.3700
3383
;;PHZ Capital Partners 508.653.1745 (fax)
3384
;;321 Commonwealth Road <[email protected]>
3385
;;Wayland, MA 01778
3386
3387
3388
3389
(defun ess-display-temp-buffer (buff)
3390
"Display the buffer BUFF using `temp-buffer-show-function' and respecting
3391
`ess-display-buffer-reuse-frames'."
3392
(let ((display-buffer-reuse-frames ess-display-buffer-reuse-frames))
3393
(funcall (or temp-buffer-show-function 'display-buffer) buff)))
3394
3395
;;*;; Error messages
3396
3397
(defun ess-error (msg)
3398
"Something bad has happened.
3399
Display the S buffer, and cause an error displaying MSG."
3400
(display-buffer (process-buffer (ess-get-process ess-current-process-name)))
3401
(error msg))
3402
3403
; Provide package
3404
3405
(provide 'ess-inf)
3406
; Local variables section
3407
3408
;;; This file is automatically placed in Outline minor mode.
3409
;;; The file is structured as follows:
3410
;;; Chapters: ^L ;
3411
;;; Sections: ;;*;;
3412
;;; Subsections: ;;;*;;;
3413
;;; Components: defuns, defvars, defconsts
3414
;;; Random code beginning with a ;;;;* comment
3415
3416
;;; Local variables:
3417
;;; mode: emacs-lisp
3418
;;; outline-minor-mode: nil
3419
;;; mode: outline-minor
3420
;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
3421
;;; End:
3422
3423
;;; ess-inf.el ends here
3424
3425