branch: externals/ess
commit 2a8c385d20b61c4329b83fac96f30bf85950af58
Author: Lionel Henry <lionel....@gmail.com>
Commit: Lionel Henry <lionel....@gmail.com>

    Don't enable enriched `ess-command` too early
    
    In case initialization fails. Also simplifies things, we no longer
    need to disable the format command during init.
    
    The format command config is now stored in a process property instead
    of a mode-local variable.
---
 lisp/ess-inf.el          | 49 ++++++++++++++++++++++++++---------------------
 lisp/ess-r-mode.el       | 50 +++++++++++++++++-------------------------------
 test/ess-test-r-utils.el |  3 ++-
 test/ess-test-r.el       |  8 +++++++-
 4 files changed, 54 insertions(+), 56 deletions(-)

diff --git a/lisp/ess-inf.el b/lisp/ess-inf.el
index 89253037f4..0a07ca744f 100644
--- a/lisp/ess-inf.el
+++ b/lisp/ess-inf.el
@@ -923,6 +923,10 @@ it was successfully forced, throws an error otherwise."
   (when ess-local-process-name
     (get-process ess-local-process-name)))
 
+(defun ess-get-current-process-buffer ()
+  (when-let ((proc (ess-get-current-process)))
+    (process-buffer proc)))
+
 (defun ess-get-next-available-process (&optional dialect ignore-busy 
background)
   "Return first available (aka not busy) process of dialect DIALECT.
 DIALECT defaults to the local value of ess-dialect. Return nil if
@@ -1329,19 +1333,6 @@ This handles Tramp when working on a remote."
       (user-error "ESS process not ready. Finish your command before trying 
again")))
   proc)
 
-(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-delimiter' : Whether to wait for an output sentinel. If
-  non-nil, `fun' should get the `cmd-output-delimiter' 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-delimiter-count 0)
 (defun inferior-ess--output-delimiter ()
   (setq inferior-ess--output-delimiter-count (1+ 
inferior-ess--output-delimiter-count))
@@ -1388,15 +1379,16 @@ wrapping the code into:
         (delim (inferior-ess--output-delimiter))
         (timeout (or timeout ess--command-default-timeout)))
     (with-current-buffer (process-buffer proc)
-      (let ((proc-forward-alist (ess--alist (ess-local-process-name
-                                             inferior-ess-primary-prompt)))
-            (use-delimiter (alist-get 'use-delimiter 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-delimiter delim))
-                        cmd))
-            (early-exit t))
+      (let* ((proc-forward-alist (ess--alist (ess-local-process-name
+                                              inferior-ess-primary-prompt)))
+             (format-command-alist (ess-process-get 'format-command-alist))
+             (use-delimiter (alist-get 'use-delimiter format-command-alist))
+             (rich-cmd (if-let ((cmd-fun (alist-get 'fun 
format-command-alist)))
+                           (funcall cmd-fun
+                                    (ess--strip-final-newlines cmd)
+                                    (cons 'output-delimiter delim))
+                         cmd))
+             (early-exit t))
         (ess-if-verbose-write (format "(ess-command '%s' ..)\n" cmd))
         ;; Swap the process buffer with the output buffer before
         ;; sending the command
@@ -1462,6 +1454,19 @@ wrapping the code into:
                              (buffer-substring start end)))))))))))
     out-buffer))
 
+;; (ess-process-get 'ess-format-command-alist)
+;;   "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-delimiter' : Whether to wait for an output sentinel. If
+;;   non-nil, `fun' should get the `cmd-output-delimiter' element of the
+;;   alist of parameters and ensure the sentinel is written to the
+;;   process output at the end of the command."
+
 (defun ess--command-make-restore-function (proc)
   (let ((old-pf (process-filter proc)))
     (lambda ()
diff --git a/lisp/ess-r-mode.el b/lisp/ess-r-mode.el
index e3648c780e..305fc36b89 100644
--- a/lisp/ess-r-mode.el
+++ b/lisp/ess-r-mode.el
@@ -442,7 +442,6 @@ To be used as part of `font-lock-defaults' keywords."
    '((ess-local-customize-alist             . 'ess-r-customize-alist)
      (ess-dialect                           . "R")
      (ess-suffix                            . "R")
-     (ess-format-command-alist              . ess-r-format-command-alist)
      (ess-traceback-command                 . ess-r-traceback-command)
      (ess-call-stack-command                . ess-r-call-stack-command)
      (ess-mode-completion-syntax-table      . ess-r-completion-syntax-table)
@@ -629,17 +628,6 @@ will be prompted to enter arguments interactively."
 (defun inferior-ess-r--init-callback (_proc _name)
   (ess-r-initialize))
 
-(defmacro ess-r--without-format-command (&rest body)
-  (declare (indent 0)
-           (debug (&rest form)))
-  `(with-current-buffer (process-buffer (ess-command--get-proc nil nil))
-     (let ((old-alist ess-format-command-alist))
-       (unwind-protect
-           (progn
-             (setq ess-format-command-alist nil)
-             ,@body)
-         (setq ess-format-command-alist old-alist)))))
-
 (defvar ess-r--init-timeout 5
   "Maximum time for R to become available on startup.
 If the timeout is reached, an error is thrown advising the user
@@ -654,13 +642,12 @@ Executed in process buffer."
       (progn
         (unless (ess-wait-for-process nil nil nil nil ess-r--init-timeout)
           (error "Process is busy"))
-        (ess-r--without-format-command
-          (ess-command (ess-r--init-options-command))
-          ;; TODO: Detect early exits on the R side and communicate
-          ;; them to lisp
-          (ess-r-load-ESSR)))
+        (ess-command (ess-r--init-options-command))
+        (ess-r-load-ESSR))
     (error (ess-r--init-error-handler err))
     (quit (ess-r--init-error-handler)))
+  (ess-process-put 'format-command-alist ess-r-format-command-alist)
+  (ess-process-put 'bg-eval-disabled nil)
   (ess-execute-screen-options t)
   (ess-set-working-directory default-directory)
   (when ess-use-tracebug
@@ -1559,21 +1546,20 @@ process."
   ;; `.ess.command()` is not defined until ESSR is loaded so disable
   ;; it temporarily. Would be helpful to implement an `inferior-ess-let'
   ;; macro .
-  (ess-r--without-format-command
-    (cond
-     ((file-remote-p (ess-get-process-variable 'default-directory))
-      (if (eq ess-r-fetch-ESSR-on-remotes t)
-          (or (ess-r--fetch-ESSR-remote)
-              (ess-r--load-ESSR-remote))
-        (ess-r--load-ESSR-remote)))
-     ((and (bound-and-true-p ess-remote))
-      ;; NB: With ess-remote we send by chunks because sending large sources is
-      ;; fragile
-      (if ess-r-fetch-ESSR-on-remotes
-          (or (ess-r--fetch-ESSR-remote)
-              (ess-r--load-ESSR-remote t))
-        (ess-r--load-ESSR-remote t)))
-     (t (ess-r--load-ESSR-local)))))
+  (cond
+   ((file-remote-p (ess-get-process-variable 'default-directory))
+    (if (eq ess-r-fetch-ESSR-on-remotes t)
+        (or (ess-r--fetch-ESSR-remote)
+            (ess-r--load-ESSR-remote))
+      (ess-r--load-ESSR-remote)))
+   ((and (bound-and-true-p ess-remote))
+    ;; NB: With ess-remote we send by chunks because sending large sources is
+    ;; fragile
+    (if ess-r-fetch-ESSR-on-remotes
+        (or (ess-r--fetch-ESSR-remote)
+            (ess-r--load-ESSR-remote t))
+      (ess-r--load-ESSR-remote t)))
+   (t (ess-r--load-ESSR-local))))
 
 (defun ess-r--load-ESSR-local ()
   "Load ESSR into a local process.
diff --git a/test/ess-test-r-utils.el b/test/ess-test-r-utils.el
index 48fbb8328e..432796300e 100644
--- a/test/ess-test-r-utils.el
+++ b/test/ess-test-r-utils.el
@@ -335,6 +335,7 @@ Note that if `ess--essr-detach' is successful then it is 
critical
 that we don't run `ess--essr-remove-global-objs' because
 .ess.command doesn't exist in the R runtime environment (and
 which is relied upon by `ess-command')."
+  (ess-process-put 'format-command-alist nil)
   (or (ess--essr-detach)
       (ess--essr-remove-global-objs)))
 
@@ -372,7 +373,7 @@ Throws an error if unsuccesful."
       ;; global environment
       (ess--essr-remove)
       ;; inject environment and attach
-      (ess-r--without-format-command (funcall ess-r--load-ESSR-fcn))
+      (funcall ess-r--load-ESSR-fcn)
       ;; check for successful ESSR injection
       (should (not (ess--essr-check-if-in-globalenv)))
       (should (ess--essr-check-if-attached))
diff --git a/test/ess-test-r.el b/test/ess-test-r.el
index e138771347..62dd414219 100644
--- a/test/ess-test-r.el
+++ b/test/ess-test-r.el
@@ -919,7 +919,13 @@ 
https://github.com/emacs-ess/ESS/issues/725#issuecomment-431781558";
           (with-current-buffer inferior-ess--last-started-process-buffer
             (should (string-match-p "Loading failed with a nice message."
                                     (caddr err)))
-            (should (not (ess-can-eval-in-background))))))
+            (should (not (ess-can-eval-in-background)))
+            (should (not (ess-process-get 'format-command-alist)))
+            (ess-send-string (ess-get-current-process) 
"Sys.unsetenv('ESSR_TEST_LOAD_ERROR')\n")
+            ;; Can recover manually
+            (ess-r-initialize)
+            (should (ess-can-eval-in-background))
+            (should (ess-process-get 'format-command-alist)))))
     (setenv "ESSR_TEST_LOAD_ERROR" nil)))
 
 (etest-deftest ess-r-command-error-test ()

Reply via email to