update packages
This commit is contained in:
@@ -332,12 +332,12 @@ name. Abbreviation is performed by `abbreviate-file-name'. See
|
||||
(defun ess-gen-proc-buffer-name:project-or-simple (proc-name)
|
||||
"Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*.
|
||||
PROC-NAME is a string representing an internal process name.
|
||||
PROJECT-ROOT is directory name returned by `project-roots'. If no
|
||||
PROJECT-ROOT is directory name returned by `ess-project-root'. If no
|
||||
project directory has been found use
|
||||
`ess-gen-proc-buffer-name:simple'. See
|
||||
`ess-gen-proc-buffer-name-function'."
|
||||
(if-let ((p (project-current))
|
||||
(proj (car (project-roots p))))
|
||||
(proj (ess-project-root p)))
|
||||
(format "*%s:%s*" proc-name (file-name-nondirectory
|
||||
(directory-file-name proj)))
|
||||
(ess-gen-proc-buffer-name:simple proc-name)))
|
||||
@@ -345,12 +345,12 @@ project directory has been found use
|
||||
(defun ess-gen-proc-buffer-name:project-or-directory (proc-name)
|
||||
"Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*.
|
||||
PROC-NAME is a string representing an internal process name.
|
||||
PROJECT-ROOT is directory name returned by `project-roots' if
|
||||
PROJECT-ROOT is directory name returned by `ess-project-root' if
|
||||
defined. If no project directory has been found, use
|
||||
`ess-gen-proc-buffer-name:directory'. See
|
||||
`ess-gen-proc-buffer-name-function'."
|
||||
(if-let ((p (project-current))
|
||||
(proj (car (project-roots p))))
|
||||
(proj (ess-project-root p)))
|
||||
(format "*%s:%s*" proc-name (file-name-nondirectory
|
||||
(directory-file-name proj)))
|
||||
(ess-gen-proc-buffer-name:directory proc-name)))
|
||||
@@ -407,6 +407,24 @@ Return non-nil if the process is in a ready (not busy) state."
|
||||
(string-match (concat "\\(" inferior-ess-secondary-prompt "\\)\\'") string)))
|
||||
ready))
|
||||
|
||||
(defun inferior-ess--set-status-sentinel (proc output-buf sentinel)
|
||||
(with-current-buffer output-buf
|
||||
(save-excursion
|
||||
(save-match-data
|
||||
;; The only assumption is that the prompt finishes with "> "
|
||||
(goto-char (- (point-max) 2))
|
||||
(when (looking-at inferior-ess-primary-prompt)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward (inferior-ess--sentinel-start-re sentinel) nil t)
|
||||
(delete-region (match-beginning 0) (1+ (match-end 0))))
|
||||
(when (re-search-forward (concat "^\\(" sentinel "-END[\n\r]+\\)") nil t)
|
||||
(delete-region (match-beginning 0) (match-end 0))
|
||||
(process-put proc 'busy nil)
|
||||
(process-put proc 'ess-output-sentinel nil)))))))
|
||||
|
||||
(defun inferior-ess--sentinel-start-re (sentinel)
|
||||
(concat "^\\(" sentinel "-START$\\)"))
|
||||
|
||||
(defun inferior-ess-mark-as-busy (proc)
|
||||
"Put PROC's busy value to t."
|
||||
(process-put proc 'busy t)
|
||||
@@ -719,26 +737,35 @@ LANGUAGE is ignored."
|
||||
(error "No ESS processes running; not yet implemented to start (%s,%s)"
|
||||
language dialect)))))
|
||||
|
||||
(defmacro ess--with-no-pop-to-buffer (&rest body)
|
||||
"Disable some effects of `pop-to-buffer'.
|
||||
Prevent `display-buffer' from performing an action and save the
|
||||
current buffer to prevent `pop-to-buffer' from setting a new
|
||||
current buffer."
|
||||
;; `pop-to-buffer' might still raise windows and frames so it may be
|
||||
;; better to have our own configurable `ess--pop-to-buffer' wrapper.
|
||||
(declare (indent 0)
|
||||
(debug (&rest form)))
|
||||
`(let ((display-buffer-overriding-action '(display-buffer-no-window (allow-no-window . t))))
|
||||
(save-current-buffer
|
||||
,@body)))
|
||||
|
||||
(defun ess-request-a-process (message &optional noswitch ask-if-1)
|
||||
"Ask for a process, and make it the current ESS process.
|
||||
If there is exactly one process, only ask if ASK-IF-1 is non-nil.
|
||||
Also switches to the process buffer unless NOSWITCH is non-nil. Interactively,
|
||||
NOSWITCH can be set by giving a prefix argument.
|
||||
Returns the name of the selected process."
|
||||
(interactive
|
||||
(list "Switch to which ESS process? " current-prefix-arg))
|
||||
; prefix sets 'noswitch
|
||||
(ess-write-to-dribble-buffer "ess-request-a-process: {beginning}\n")
|
||||
Also switches to the process buffer unless NOSWITCH is non-nil.
|
||||
Interactively, NOSWITCH can be set by giving a prefix argument.
|
||||
Returns the name of the selected process. MESSAGE may get passed
|
||||
to `ess-completing-read'."
|
||||
(interactive (list "Switch to which ESS process? " current-prefix-arg))
|
||||
(update-ess-process-name-list)
|
||||
|
||||
(setq ess-dialect (or ess-dialect
|
||||
(ess-completing-read
|
||||
"Set `ess-dialect'"
|
||||
(delete-dups (list "R" "S+" (or (bound-and-true-p S+-dialect-name) "S+")
|
||||
"stata" (or (bound-and-true-p STA-dialect-name) "stata")
|
||||
"julia" "SAS" "XLS" "ViSta")))))
|
||||
|
||||
(let* ((pname-list (delq nil ;; keep only those matching dialect
|
||||
(let* ((ess-dialect (or ess-dialect
|
||||
(ess-completing-read
|
||||
"Set `ess-dialect'"
|
||||
(delete-dups (list "R" "S+" (or (bound-and-true-p S+-dialect-name) "S+")
|
||||
"stata" (or (bound-and-true-p STA-dialect-name) "stata")
|
||||
"julia" "SAS")))))
|
||||
(pname-list (delq nil ;; keep only those matching dialect
|
||||
(append
|
||||
(mapcar (lambda (lproc)
|
||||
(and (equal ess-dialect
|
||||
@@ -752,56 +779,47 @@ Returns the name of the selected process."
|
||||
(when (assoc ess-local-process-name ess-process-name-list)
|
||||
(list ess-local-process-name)))))
|
||||
(num-processes (length pname-list))
|
||||
(auto-started?))
|
||||
(if (or (= 0 num-processes)
|
||||
(and (= 1 num-processes)
|
||||
(not (equal ess-dialect ;; don't auto connect if from different dialect
|
||||
(buffer-local-value
|
||||
'ess-dialect
|
||||
(process-buffer (get-process
|
||||
(car pname-list))))))))
|
||||
;; try to start "the appropriate" process
|
||||
(progn
|
||||
(ess-write-to-dribble-buffer
|
||||
(concat " ... request-a-process:\n "
|
||||
(format
|
||||
"major mode %s; current buff: %s; ess-language: %s, ess-dialect: %s\n"
|
||||
major-mode (current-buffer) ess-language ess-dialect)))
|
||||
(ess-start-process-specific ess-language ess-dialect)
|
||||
(ess-write-to-dribble-buffer
|
||||
(format " ... request-a-process: buf=%s\n" (current-buffer)))
|
||||
(setq num-processes 1
|
||||
pname-list (car ess-process-name-list)
|
||||
auto-started? t)))
|
||||
proc auto-started?)
|
||||
(when (or (= 0 num-processes)
|
||||
(and (= 1 num-processes)
|
||||
(not (equal ess-dialect ;; don't auto connect if from different dialect
|
||||
(buffer-local-value
|
||||
'ess-dialect
|
||||
(process-buffer (get-process
|
||||
(car pname-list))))))))
|
||||
;; try to start "the appropriate" process, don't show the buffer
|
||||
;; since we handle that explicitly with no-switch
|
||||
(ess--with-no-pop-to-buffer
|
||||
(ess-start-process-specific ess-language ess-dialect))
|
||||
(setq num-processes 1
|
||||
pname-list (car ess-process-name-list)
|
||||
auto-started? t))
|
||||
;; now num-processes >= 1 :
|
||||
(let* ((proc-buffers (mapcar (lambda (lproc)
|
||||
(buffer-name (process-buffer (get-process lproc))))
|
||||
pname-list))
|
||||
(proc
|
||||
pname-list)))
|
||||
(setq proc
|
||||
(if (or auto-started?
|
||||
(and (not ask-if-1) (= 1 num-processes)))
|
||||
(progn
|
||||
(message "using process '%s'" (car proc-buffers))
|
||||
(car pname-list))
|
||||
;; else
|
||||
(and (not ask-if-1)
|
||||
(= 1 num-processes)
|
||||
(message "Using process `%s'" (car proc-buffers))))
|
||||
(car pname-list)
|
||||
(unless (and ess-current-process-name
|
||||
(get-process ess-current-process-name))
|
||||
(setq ess-current-process-name nil))
|
||||
(when message
|
||||
(setq message (replace-regexp-in-string ": +\\'" "" message))) ;; <- why is this here??
|
||||
;; ask for buffer name not the *real* process name:
|
||||
(let ((buf (ess-completing-read message (append proc-buffers (list "*new*")) nil t nil nil)))
|
||||
(if (equal buf "*new*")
|
||||
(progn
|
||||
(ess-start-process-specific ess-language ess-dialect) ;; switches to proc-buff
|
||||
(caar ess-process-name-list))
|
||||
(process-name (get-buffer-process buf))
|
||||
))
|
||||
)))
|
||||
(if noswitch
|
||||
(pop-to-buffer (current-buffer)) ;; VS: this is weird, but is necessary
|
||||
(pop-to-buffer (buffer-name (process-buffer (get-process proc)))))
|
||||
proc)))
|
||||
(if (not (equal buf "*new*"))
|
||||
(process-name (get-buffer-process buf))
|
||||
;; Prevent new process buffer from being popped
|
||||
;; because we handle display depending on the value
|
||||
;; of `no-switch`
|
||||
(ess--with-no-pop-to-buffer
|
||||
(ess-start-process-specific ess-language ess-dialect))
|
||||
(caar ess-process-name-list))))))
|
||||
(unless noswitch
|
||||
(pop-to-buffer (ess-get-process-buffer proc)))
|
||||
proc))
|
||||
|
||||
(defun ess-force-buffer-current (&optional prompt force no-autostart ask-if-1)
|
||||
"Make sure the current buffer is attached to an ESS process.
|
||||
@@ -900,9 +918,10 @@ toggled."
|
||||
(message "Found no buffers for `ess-dialect' %s associated with process %s"
|
||||
dialect proc-name)))
|
||||
(ess-switch-to-ESS eob))
|
||||
(set-transient-map (let ((map (make-sparse-keymap))
|
||||
(key (vector last-command-event)))
|
||||
(define-key map key #'ess-switch-to-inferior-or-script-buffer) map))))
|
||||
(when (called-interactively-p 'any)
|
||||
(set-transient-map (let ((map (make-sparse-keymap))
|
||||
(key (vector last-command-event)))
|
||||
(define-key map key #'ess-switch-to-inferior-or-script-buffer) map)))))
|
||||
|
||||
|
||||
(defun ess-get-process-buffer (&optional name)
|
||||
@@ -956,7 +975,9 @@ is non-nil wait for WAIT seconds for process output before the
|
||||
prompt check, default 0.002s. When FORCE-REDISPLAY is non-nil
|
||||
force redisplay. You better use WAIT >= 0.1 if you need
|
||||
FORCE-REDISPLAY to avoid excessive redisplay. If TIMEOUT is
|
||||
non-nil stop waiting for output after TIMEOUT seconds."
|
||||
non-nil stop waiting for output after TIMEOUT seconds.
|
||||
|
||||
Returns nil if TIMEOUT was reached, non-nil otherwise."
|
||||
(setq proc (or proc (get-process ess-local-process-name)))
|
||||
(setq wait (or wait 0.005))
|
||||
(setq timeout (or timeout most-positive-fixnum))
|
||||
@@ -977,14 +998,20 @@ non-nil stop waiting for output after TIMEOUT seconds."
|
||||
(redisplay 'force))
|
||||
(setq elapsed (- (float-time) start-time))
|
||||
(when (> elapsed .3)
|
||||
(setq wait .3))))))
|
||||
(setq wait .3))))
|
||||
(< elapsed timeout)))
|
||||
|
||||
(defun inferior-ess-ordinary-filter (proc string)
|
||||
(inferior-ess--set-status proc string)
|
||||
(ess--if-verbose-write-process-state proc string "ordinary-filter")
|
||||
(inferior-ess-run-callback proc string)
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(insert string)))
|
||||
(let ((sentinel (process-get proc 'ess-output-sentinel)))
|
||||
(unless sentinel
|
||||
(inferior-ess--set-status proc string)
|
||||
(inferior-ess-run-callback proc string))
|
||||
(ess--if-verbose-write-process-state proc string "ordinary-filter")
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(insert string))
|
||||
(when sentinel
|
||||
(inferior-ess--set-status-sentinel proc (process-buffer proc) sentinel)
|
||||
(inferior-ess-run-callback proc string))))
|
||||
|
||||
(defvar ess-presend-filter-functions nil
|
||||
"List of functions to call before sending the input string to the process.
|
||||
@@ -1191,16 +1218,45 @@ This handles Tramp when working on a remote."
|
||||
(user-error "ESS process not ready. Finish your command before trying again")))
|
||||
proc)
|
||||
|
||||
(defun ess-command (cmd &optional out-buffer _sleep no-prompt-check wait proc force-redisplay)
|
||||
(defvar-local ess-format-command-alist nil
|
||||
"Alist of mode-specific parameters for formatting a command.
|
||||
All elements are optional.
|
||||
|
||||
- `fun': A formatting function for running a command. First
|
||||
argument is the background command to run. Must include a
|
||||
catch-all `&rest` parameter for extensibility.
|
||||
|
||||
- `use-sentinel' : Whether to wait for an output sentinel. If
|
||||
non-nil, `fun' should get the `output-sentinel' element of the
|
||||
alist of parameters and ensure the sentinel is written to the
|
||||
process output at the end of the command.")
|
||||
|
||||
(defvar inferior-ess--output-sentinel-count 0)
|
||||
(defun inferior-ess--output-sentinel ()
|
||||
(setq inferior-ess--output-sentinel-count (1+ inferior-ess--output-sentinel-count))
|
||||
(format "ess-output-sentinel%s" inferior-ess--output-sentinel-count))
|
||||
|
||||
;; NOTE: We might want to switch to somethig like `cl-defun' with
|
||||
;; keyword arguments given the length of the signature. Would also
|
||||
;; make it easier to deprecate arguments.
|
||||
(defun ess-command (cmd &optional out-buffer _sleep no-prompt-check wait proc
|
||||
force-redisplay timeout)
|
||||
"Send the ESS process CMD and delete the output from the ESS process buffer.
|
||||
If an optional second argument OUT-BUFFER exists save the output
|
||||
in that buffer. OUT-BUFFER is erased before use. CMD should have
|
||||
a terminating newline. Guarantees that the value of `.Last.value'
|
||||
will be preserved.
|
||||
|
||||
SLEEP is deprecated and no longer has any effect. WAIT and
|
||||
FORCE-REDISPLAY are as in `ess-wait-for-process' and are passed
|
||||
to `ess-wait-for-process'.
|
||||
`ess-command' is executes CMD in the background synchronously,
|
||||
meaning that the Emacs UI blocks while CMD is running. Make sure
|
||||
that CMD returns immediately. Blocking the UI for more than 0.1
|
||||
seconds should generally be considered a bug.
|
||||
|
||||
SLEEP is deprecated and no longer has any effect. WAIT,
|
||||
FORCE-REDISPLAY, and TIMEOUT are as in `ess-wait-for-process' and
|
||||
are passed to `ess-wait-for-process'. The default timeout is 1
|
||||
second. The process is interrupted with `interrupt-process' when
|
||||
the timeout is reached or when an error occurs.
|
||||
|
||||
PROC should be a process, if nil the process name is taken from
|
||||
`ess-local-process-name'. This command doesn't set 'last-eval
|
||||
@@ -1219,47 +1275,78 @@ wrapping the code into:
|
||||
;; Set `inhibit-quit' to t to avoid dumping R output to the
|
||||
;; process buffer if `ess-command' gets interrupted for some
|
||||
;; reason. See bugs #794 and #842
|
||||
(inhibit-quit t))
|
||||
(inhibit-quit t)
|
||||
(sentinel (inferior-ess--output-sentinel))
|
||||
(timeout (or timeout 1)))
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(let ((primary-prompt inferior-ess-primary-prompt)
|
||||
(let ((proc-alist (ess--alist (ess-local-process-name
|
||||
inferior-ess-primary-prompt)))
|
||||
(oldpb (process-buffer proc))
|
||||
(oldpf (process-filter proc))
|
||||
(oldpm (marker-position (process-mark proc))))
|
||||
(oldpm (marker-position (process-mark proc)))
|
||||
(use-sentinel (alist-get 'use-sentinel ess-format-command-alist))
|
||||
(rich-cmd (if-let ((cmd-fun (alist-get 'fun ess-format-command-alist)))
|
||||
(funcall cmd-fun
|
||||
(ess--strip-final-newlines cmd)
|
||||
(cons 'output-sentinel sentinel))
|
||||
cmd))
|
||||
(early-exit t))
|
||||
(ess-if-verbose-write (format "(ess-command %s ..)" cmd))
|
||||
;; Swap the process buffer with the output buffer before
|
||||
;; sending the command
|
||||
(unwind-protect
|
||||
(progn
|
||||
(when use-sentinel
|
||||
(process-put proc 'ess-output-sentinel sentinel))
|
||||
(set-process-buffer proc out-buffer)
|
||||
(set-process-filter proc 'inferior-ess-ordinary-filter)
|
||||
(with-current-buffer out-buffer
|
||||
(setq inferior-ess-primary-prompt primary-prompt)
|
||||
(ess-setq-vars-local proc-alist)
|
||||
(setq buffer-read-only nil)
|
||||
(erase-buffer)
|
||||
(set-marker (process-mark proc) (point-min))
|
||||
(inferior-ess-mark-as-busy proc)
|
||||
(process-send-string proc cmd)
|
||||
(process-send-string proc rich-cmd)
|
||||
;; Need time for ess-create-object-name-db on PC
|
||||
(if no-prompt-check
|
||||
(sleep-for 0.02) ; 0.1 is noticeable!
|
||||
(ess-wait-for-process proc nil wait force-redisplay)
|
||||
;; Should (almost) never be incomplete unless the message
|
||||
;; contains "> " and was accidentally split by the process
|
||||
;; right there.
|
||||
(while (eq :incomplete (ess-mpi-handle-messages (current-buffer)))
|
||||
(ess-wait-for-process proc nil wait force-redisplay))
|
||||
;; Remove prompt
|
||||
;; If output is cat(..)ed this deletes the output
|
||||
(unless (ess-wait-for-process proc nil wait force-redisplay timeout)
|
||||
(error "Timeout during background ESS command '%s'"
|
||||
(ess--strip-final-newlines cmd)))
|
||||
;; Remove prompt. If output is cat(..)ed without a
|
||||
;; final newline, this deletes the last line of output.
|
||||
(goto-char (point-max))
|
||||
(delete-region (point-at-bol) (point-max)))
|
||||
(ess-if-verbose-write " .. ok{ess-command}")))
|
||||
(ess-if-verbose-write " .. exiting{ess-command}\n")
|
||||
(delete-region (point-at-bol) (point-max))))
|
||||
(setq early-exit nil))
|
||||
;; Restore the process buffer in its previous state
|
||||
(when early-exit
|
||||
(with-current-buffer out-buffer
|
||||
(goto-char (point-min))
|
||||
(when (and use-sentinel
|
||||
(not (re-search-forward
|
||||
(inferior-ess--sentinel-start-re sentinel)
|
||||
nil t)))
|
||||
;; CMD probably failed to parse if the start sentinel
|
||||
;; can't be found in the output. Disable the sentinel
|
||||
;; before interrupt to avoid a freeze.
|
||||
(process-put proc 'ess-output-sentinel nil))
|
||||
(goto-char (point-max))
|
||||
(ess-interrupt)))
|
||||
(process-put proc 'ess-output-sentinel nil)
|
||||
(set-process-buffer proc oldpb)
|
||||
(set-process-filter proc oldpf)
|
||||
(set-marker (process-mark proc) oldpm))))
|
||||
out-buffer))
|
||||
|
||||
;; TODO: Needs some Julia tests as well
|
||||
(defun ess--foreground-command (cmd &optional out-buffer _sleep no-prompt-check wait proc)
|
||||
"Same as `ess-command' but does not timeout.
|
||||
Currently blocks the Emacs UI. Eventually it would make sense to
|
||||
lock the inferior to prevent interactions and use
|
||||
`ess-async-command' with a callback."
|
||||
(let ((timeout most-positive-fixnum))
|
||||
(ess-command cmd out-buffer nil no-prompt-check wait proc nil timeout)))
|
||||
|
||||
(defun ess-boolean-command (com &optional buf wait)
|
||||
"Like `ess-command' but expects COM to print TRUE or FALSE.
|
||||
If TRUE (or true) is found return non-nil otherwise nil.
|
||||
@@ -1357,40 +1444,38 @@ similar to `load-library' Emacs function."
|
||||
|
||||
;;*;; Evaluating lines, paragraphs, regions, and buffers.
|
||||
|
||||
(defun ess-eval-linewise
|
||||
(text &optional invisibly eob even-empty wait-last-prompt sleep-sec wait-sec)
|
||||
(defun ess-eval-linewise (text &optional invisibly eob even-empty
|
||||
wait-last-prompt sleep-sec wait-sec)
|
||||
"Evaluate TEXT in the ESS process buffer as if typed in w/o tabs.
|
||||
Waits for prompt after each line of input, so won't break on large texts.
|
||||
|
||||
If optional second arg INVISIBLY is non-nil, don't echo commands.
|
||||
If it is a string, just include that string. If optional third
|
||||
arg EOB is non-nil go to end of ESS process buffer after
|
||||
evaluation. If optional 4th arg EVEN-EMPTY is non-nil, also send
|
||||
empty text (e.g. an empty line). If 5th arg WAIT-LAST-PROMPT is
|
||||
arg EOB is non-nil, display ESS process buffer after evaluation.
|
||||
If optional 4th arg EVEN-EMPTY is non-nil, also send empty
|
||||
text (e.g. an empty line). If 5th arg WAIT-LAST-PROMPT is
|
||||
non-nil, also wait for the prompt after the last line; if 6th arg
|
||||
SLEEP-SEC is a number, ESS will call '(\\[sleep-for] SLEEP-SEC)
|
||||
at the end of this function. If the 7th arg WAIT-SEC is set, it
|
||||
at the end of this function. If the 7th arg WAIT-SEC is set, it
|
||||
will be used instead of the default .001s and be passed to
|
||||
\\[ess-wait-for-process].
|
||||
|
||||
Run `comint-input-filter-functions' and
|
||||
`ess-presend-filter-functions' of the associated PROCESS on the
|
||||
TEXT."
|
||||
(unless (numberp wait-sec)
|
||||
(setq wait-sec 0.001))
|
||||
(ess-force-buffer-current "Process to use: ")
|
||||
;; Use this to evaluate some code, but don't wait for output.
|
||||
(let* ((deactivate-mark) ; keep local {do *not* deactivate wrongly}
|
||||
(sprocess (ess-get-process ess-current-process-name))
|
||||
(sbuffer (process-buffer sprocess))
|
||||
(win (get-buffer-window sbuffer t)))
|
||||
(inf-proc (ess-get-process ess-current-process-name))
|
||||
(inf-buf (process-buffer inf-proc))
|
||||
(win (get-buffer-window inf-buf t)))
|
||||
(setq text (ess--concat-new-line-maybe
|
||||
(ess--run-presend-hooks sprocess text)))
|
||||
(with-current-buffer sbuffer
|
||||
(ess--run-presend-hooks inf-proc text)))
|
||||
(with-current-buffer inf-buf
|
||||
(setq text (propertize text 'field 'input 'front-sticky t))
|
||||
(goto-char (marker-position (process-mark sprocess)))
|
||||
(if (stringp invisibly)
|
||||
(insert-before-markers (concat "*** " invisibly " ***\n")))
|
||||
(goto-char (marker-position (process-mark inf-proc)))
|
||||
(when (stringp invisibly)
|
||||
(insert-before-markers (concat "*** " invisibly " ***\n")))
|
||||
;; dbg:
|
||||
;; dbg (ess-write-to-dribble-buffer
|
||||
;; dbg (format "(eval-visibly 2): text[%d]= '%s'\n" (length text) text))
|
||||
@@ -1401,26 +1486,30 @@ TEXT."
|
||||
"\n"
|
||||
(concat (substring text 0 pos) "\n"))))
|
||||
(setq text (substring text (min (length text) (1+ pos))))
|
||||
(goto-char (marker-position (process-mark sprocess)))
|
||||
(if win (set-window-point win (process-mark sprocess)))
|
||||
(goto-char (marker-position (process-mark inf-proc)))
|
||||
(when win
|
||||
(set-window-point win (process-mark inf-proc)))
|
||||
(unless invisibly
|
||||
;; for consistency with comint :(
|
||||
(insert (propertize input 'font-lock-face 'comint-highlight-input))
|
||||
(set-marker (process-mark sprocess) (point)))
|
||||
(inferior-ess-mark-as-busy sprocess)
|
||||
(process-send-string sprocess input))
|
||||
(set-marker (process-mark inf-proc) (point)))
|
||||
(inferior-ess-mark-as-busy inf-proc)
|
||||
(process-send-string inf-proc input))
|
||||
(when (or (> (length text) 0)
|
||||
wait-last-prompt)
|
||||
(ess-wait-for-process sprocess t wait-sec)))
|
||||
(if eob (with-temp-buffer (buffer-name sbuffer)))
|
||||
(goto-char (marker-position (process-mark sprocess)))
|
||||
(ess-wait-for-process inf-proc t (or wait-sec 0.001))))
|
||||
(when eob
|
||||
(display-buffer inf-buf))
|
||||
;; This used to be conditioned on EOB but this is no longer the
|
||||
;; case since commit fd90550d in 2012 (probably an accident)
|
||||
(goto-char (marker-position (process-mark inf-proc)))
|
||||
(when win
|
||||
(with-selected-window win
|
||||
(goto-char (point))
|
||||
;; this is crucial to avoid resetting window-point
|
||||
(recenter (- -1 scroll-margin))))))
|
||||
(if (numberp sleep-sec)
|
||||
(sleep-for sleep-sec)))
|
||||
(when (numberp sleep-sec)
|
||||
(sleep-for sleep-sec)))
|
||||
|
||||
|
||||
;;;*;;; Evaluate only
|
||||
@@ -2173,18 +2262,18 @@ method, see `ess-quit--override'."
|
||||
This sends an interrupt and quits a debugging session."
|
||||
(interactive)
|
||||
(inferior-ess-force)
|
||||
(let ((proc (ess-get-process)))
|
||||
(let ((proc (ess-get-process))
|
||||
(timeout 1))
|
||||
;; Interrupt current task before reloading. Useful if the process is
|
||||
;; prompting for input, for instance in R in case of a crash
|
||||
(interrupt-process proc comint-ptyp)
|
||||
;; Workaround for Windows terminals
|
||||
(unless (memq system-type '(gnu/linux darwin))
|
||||
(process-send-string nil "\n"))
|
||||
(ess-wait-for-process proc)
|
||||
;; Quit debugging session before reloading
|
||||
(when (ess-debug-active-p)
|
||||
(ess-debug-command-quit)
|
||||
(ess-wait-for-process proc))))
|
||||
(unless (ess-wait-for-process proc nil nil nil timeout)
|
||||
(error "Timeout while interrupting process"))
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(goto-char (process-mark proc)))))
|
||||
|
||||
(defun ess-abort ()
|
||||
"Kill the ESS process, without executing .Last or terminating devices.
|
||||
@@ -2240,12 +2329,16 @@ START-ARGS gets passed to the dialect-specific
|
||||
(start-args (or start-args (cdr inf-start-data))))
|
||||
;; Interrupt early so we can get working directory
|
||||
(ess-interrupt)
|
||||
;; Quit debugging session before reloading
|
||||
(when (ess-debug-active-p)
|
||||
(ess-debug-command-quit)
|
||||
(ess-wait-for-process inf-proc nil nil nil 1))
|
||||
(save-window-excursion
|
||||
;; Make sure we don't ask for directory again
|
||||
;; Use current working directory as default
|
||||
(let ((project-find-functions nil)
|
||||
(ess-directory-function nil)
|
||||
(ess-startup-directory (ess-get-working-directory))
|
||||
(ess-startup-directory (ess-get-process-variable 'default-directory))
|
||||
(ess-ask-for-ess-directory nil))
|
||||
(ess-quit 'no-save)
|
||||
(inferior-ess--wait-for-exit inf-proc)
|
||||
@@ -2342,11 +2435,13 @@ non-nil, don't return objects in first positon (.GlobalEnv)."
|
||||
(setq i (1+ i)))
|
||||
(setq ess-object-list (delete-dups result))))))
|
||||
|
||||
(defun ess-get-words-from-vector (command &optional no-prompt-check wait proc)
|
||||
(defun ess-get-words-from-vector (command &optional no-prompt-check wait proc
|
||||
timeout)
|
||||
"Evaluate the S command COMMAND, which returns a character vector.
|
||||
Return the elements of the result of COMMAND as an alist of
|
||||
strings. COMMAND should have a terminating newline.
|
||||
NO-PROMPT-CHECK, WAIT, and PROC are passed to `ess-command'.
|
||||
NO-PROMPT-CHECK, WAIT, PROC, and TIMEOUT are passed to `ess-command'.
|
||||
|
||||
FILTER may be the keyword 'non-... or nil. To avoid truncation of
|
||||
long vectors, wrap your command (%s) like this, or a version with
|
||||
explicit options(max.print=1e6): \"local({ out <- try({%s});
|
||||
@@ -2365,7 +2460,7 @@ print(out, max=1e6) })\n\"."
|
||||
"\\( \\|$\\)"; space or end
|
||||
))
|
||||
words)
|
||||
(ess-command command tbuffer 'sleep no-prompt-check wait proc)
|
||||
(ess-command command tbuffer 'sleep no-prompt-check wait proc nil timeout)
|
||||
(with-current-buffer tbuffer
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward full-word-regexp nil t)
|
||||
@@ -2377,6 +2472,10 @@ print(out, max=1e6) })\n\"."
|
||||
(format " |-> words= '%s'\n" words)))
|
||||
(reverse words)))
|
||||
|
||||
(defun ess-get-words-from-vector--foreground (command &optional no-prompt-check wait proc)
|
||||
(let ((timeout most-positive-fixnum))
|
||||
(ess-get-words-from-vector command no-prompt-check wait proc timeout)))
|
||||
|
||||
(defun ess-compiled-dir (dir)
|
||||
"Return non-nil if DIR is an S object directory with special files.
|
||||
I.e. if the filenames in DIR are not representative of the objects in DIR."
|
||||
@@ -2800,8 +2899,9 @@ To be used in `ess-idle-timer-functions'."
|
||||
(inferior-ess-available-p))
|
||||
(ess-when-new-input last-sync-dirs
|
||||
(ess-if-verbose-write "\n(ess-synchronize-dirs)\n")
|
||||
(setq default-directory
|
||||
(car (ess-get-words-from-vector ess-getwd-command)))
|
||||
(let ((lpath (car (ess-get-words-from-vector ess-getwd-command))))
|
||||
(setq default-directory
|
||||
(ess--derive-connection-path default-directory lpath)))
|
||||
default-directory)))
|
||||
|
||||
(defun ess-dirs ()
|
||||
@@ -2810,9 +2910,19 @@ To be used in `ess-idle-timer-functions'."
|
||||
;; default-directory and subprocess working directory are
|
||||
;; synchronized automatically.
|
||||
(interactive)
|
||||
(let ((dir (car (ess-get-words-from-vector "getwd()\n"))))
|
||||
(let* ((dir (car (ess-get-words-from-vector "getwd()\n")))
|
||||
(new-default-dir (ess--derive-connection-path default-directory dir)))
|
||||
(message "(ESS / default) directory: %s" dir)
|
||||
(setq default-directory (file-name-as-directory dir))))
|
||||
(setq default-directory (file-name-as-directory new-default-dir))))
|
||||
|
||||
(defun ess--derive-connection-path (old new)
|
||||
"Derive a (possibly remote) path with an updated local filename.
|
||||
A new connection path is derived from OLD (a path) and NEW (a
|
||||
path), in such a way that the host and connection information (if
|
||||
any) in OLD is retained in the NEW path. NEW must be an absolute
|
||||
path, and can be a remote path"
|
||||
(concat (file-remote-p old)
|
||||
(or (file-remote-p new 'localname) new)))
|
||||
|
||||
;; search path
|
||||
(defun ess--mark-search-list-as-changed ()
|
||||
|
||||
Reference in New Issue
Block a user