Subject: Re: bug#71049: async-shell-command ends with "Process *Async Shell Command* finished" when remote "direct-async-process"

From: Michael Albinus <[email-masked]>
Date: Sun, 26 May 2024 16:18:05 +0200

Michael Albinus <[email-masked]> writes:

Hi Dmitry,
>
>> So it seems to me that fixing shell-mode would be good for the default
>> behavior, and then one could use tramp-histfile-override to add extra
>> performance on top.
>
> I'll see whether I could make it more fine-grained, for example by
> distinguishing the shell and shell-command cases.

I've puzzled the appended patch together. It does the following:

- Obey 'tramp-histfile-override' also for direct async processes.

- Use 'tramp-histfile-override' in 'shell-mode', whether the remote
  history file shall be read. A value of t suppresses this.

- Support connection-local setting of 'tramp-histfile-override' in
  'shell'. Use something like

--8<---------------cut here---------------start------------->8---
  (connection-local-set-profile-variables
   'remote-tramp-histfile-override '((tramp-histfile-override . nil)))

  (connection-local-set-profiles
   '(:application tramp :machine "remotehost")
   'remote-tramp-histfile-override)
--8<---------------cut here---------------end--------------->8---

- Support connection-local setting of 'tramp-histfile-override' in
  'shell-command'. In order to distinguish this from the setting for
  'shell', another :application is used ('shell-command' instead of
  'tramp'). Use something like

--8<---------------cut here---------------start------------->8---
  (connection-local-set-profile-variables
   'another-tramp-histfile-override '((tramp-histfile-override . t)))

  (connection-local-set-profiles
   '(:application shell-command :machine "remotehost")
   'another-tramp-histfile-override)
--8<---------------cut here---------------end--------------->8---

It is recommended to set 'tramp-histfile-override' to t for
asynchronous processes. Comments?

Best regards, Michael.

diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index c079455a444..615f9219448 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -64,6 +64,7 @@ tramp-copy-size-limit
   :group 'tramp
   :type '(choice (const nil) integer))

+;;;###tramp-autoload
 (defcustom tramp-histfile-override "~/.tramp_history"
   "When invoking a shell, override the HISTFILE with this value.
 When setting to a string, it redirects the shell history to that
@@ -80,6 +81,8 @@ tramp-histfile-override
                  (const :tag "Unset HISTFILE" t)
                  (string :tag "Redirect to a file")))

+(put 'tramp-histfile-override 'permanent-local t)
+
 ;; ksh on OpenBSD 4.5 requires that $PS1 contains a `#' character for
 ;; root users.  It uses the `$' character for other users.  In order
 ;; to guarantee a proper prompt, we use "#$ " for the prompt.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 9385b023392..936fdd25e6c 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -4962,6 +4962,18 @@ tramp-handle-make-process
 			      (string-join (tramp-get-remote-path v) ":")))
 			(setenv-internal env "PATH" remote-path 'keep)
 		      env))
+	       ;; Add HISTFILE if indicated.
+	       (env (if-let ((sh-file-name-handler-p))
+			(cond
+			 ((stringp tramp-histfile-override)
+			  (setenv-internal env "HISTFILE" tramp-histfile-override 'keep))
+			 (tramp-histfile-override
+			  (setq env (setenv-internal env "HISTFILE" "''" 'keep))
+			  (setq env (setenv-internal env "HISTSIZE" "0" 'keep))
+			  (setenv-internal env "HISTFILESIZE" "0" 'keep))
+			 (t env))
+		      env))
+	       ;; Add INSIDE_EMACS.
 	       (env (setenv-internal
 		     env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
 	       (env (mapcar #'tramp-shell-quote-argument (delq nil env)))
@@ -5248,7 +5260,8 @@ tramp-handle-shell-command
 	      (with-current-buffer output-buffer
 		(setq mode-line-process '(":%s"))
 		(unless (eq major-mode 'shell-mode)
-		  (shell-mode))
+		  (with-connection-local-application-variables 'shell-command
+		    (shell-mode)))
 		(set-process-filter p #'comint-output-filter)
 		(set-process-sentinel p #'shell-command-sentinel)
 		(when error-file
diff --git a/lisp/shell.el b/lisp/shell.el
index e6b315ee5c0..60a805f33c9 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -609,6 +609,8 @@ sh-shell-file
 (declare-function w32-application-type "w32proc.c"
                   (program) t)

+(defvar tramp-histfile-override)
+
 (define-derived-mode shell-mode comint-mode "Shell"
   "Major mode for interacting with an inferior shell.
 \\<shell-mode-map>
@@ -726,9 +728,11 @@ shell-mode
           (hsize (getenv "HISTSIZE"))
           (hfile (getenv "HISTFILE")))
       (when remote
-        ;; `shell-snarf-envar' does not work trustworthy.
-        (setq hsize (shell-command-to-string "echo -n $HISTSIZE")
-              hfile (shell-command-to-string "echo -n $HISTFILE")))
+        (if (eq tramp-histfile-override t)
+            (setq remote "" hfile nil hsize nil)
+          ;; `shell-snarf-envar' does not work trustworthy.
+          (setq hsize (shell-command-to-string "echo -n $HISTSIZE")
+                hfile (shell-command-to-string "echo -n $HISTFILE"))))
       (and (string-equal hfile "") (setq hfile nil))
       (and (stringp hsize)
 	   (integerp (setq hsize (string-to-number hsize)))
@@ -738,10 +742,11 @@ shell-mode
             (concat
              remote
 	     (or hfile
-		 (cond ((string-equal shell "bash") "~/.bash_history")
-		       ((string-equal shell "ksh") "~/.sh_history")
-		       ((string-equal shell "zsh") "~/.zsh_history")
-		       (t "~/.history")))))
+                 (and (not (string-equal remote ""))
+		      (cond ((string-equal shell "bash") "~/.bash_history")
+		            ((string-equal shell "ksh") "~/.sh_history")
+		            ((string-equal shell "zsh") "~/.zsh_history")
+		            (t "~/.history"))))))
       (if (or (equal comint-input-ring-file-name "")
 	      (equal (file-truename comint-input-ring-file-name)
 		     (file-truename null-device)))