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

From: Michael Albinus <[email-masked]>
Date: Sun, 02 Jun 2024 10:36:24 +0200

Dmitry Gutov <[email-masked]> writes:

> Hi Michael,

Hi Dmitry,

> Looking at it again, it does seem like it could still be useful to
> override or disable the remote history file (right?).
>
> But with your patch, what happens when tramp-history-override is a
> string? Both Tramp and shell will write to it its commands, and upon
> loading shell will also read history from it, including all of the
> commands that Tramp had sent to the remote host. Am I reading it
> correctly?
>
> Perhaps instead we could have a connection-local variable like
> shell-history-file-name, which could be customized by the user to t to
> disable history - and that could even work per-connection.

Good idea. Something like this?

diff --git a/lisp/shell.el b/lisp/shell.el
index 4352811912a..6fb5768c056 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -419,6 +419,21 @@ shell--start-prog
   "Shell file name started in `shell'.")
 (put 'shell--start-prog 'permanent-local t)

+(defcustom shell-history-file-name nil
+  "The history file name used in `shell-mode'.
+When it is a string, this file name will be used.
+When it is nil, the environment variable HISTFILE is used.
+When it is t, no history file name is used in `shell-mode'.
+
+The settings obey whether `shell-mode' is invoked in a remote buffer.
+In that case, HISTFILE is taken from the remote host, and the string is
+interpreted as local file name on the remote host.
+
+If `shell-mode' is invoked in a local buffer, and no history file name
+can be determined, a default according to the shell type is used."
+  :type '(choice (const :tag "Default" nil) (const :tag "Suppress" t) file)
+  :version "30.1")
+
 ;;; Basic Procedures

 (defun shell--unquote&requote-argument (qstr &optional upos)
@@ -721,27 +736,33 @@ shell-mode
   (setq list-buffers-directory (expand-file-name default-directory))
   ;; shell-dependent assignments.
   (when (ring-empty-p comint-input-ring)
-    (let ((remote (file-remote-p default-directory))
-          (shell (or shell--start-prog ""))
-          (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")))
+    (let* ((remote (file-remote-p default-directory))
+           (shell (or shell--start-prog ""))
+           (hfile (cond ((stringp shell-history-file-name)
+                         shell-history-file-name)
+                        ((null shell-history-file-name)
+                         (if remote
+                             (shell-command-to-string "echo -n $HISTFILE")
+                           (getenv "HISTFILE")))))
+           hsize)
       (and (string-equal hfile "") (setq hfile nil))
-      (and (stringp hsize)
-	   (integerp (setq hsize (string-to-number hsize)))
-	   (> hsize 0)
-           (setq-local comint-input-ring-size hsize))
-      (setq comint-input-ring-file-name
-            (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")))))
+      (when (and (not remote) (not hfile))
+        (setq hfile
+              (cond ((string-equal shell "bash") "~/.bash_history")
+		    ((string-equal shell "ksh") "~/.sh_history")
+		    ((string-equal shell "zsh") "~/.zsh_history")
+		    (t "~/.history"))))
+      (when (stringp hfile)
+        (setq hsize
+              (if remote
+                  (shell-command-to-string "echo -n $HISTSIZE")
+                (getenv "HISTSIZE")))
+        (and (stringp hsize)
+	     (integerp (setq hsize (string-to-number hsize)))
+	     (> hsize 0)
+             (setq-local comint-input-ring-size hsize))
+        (setq comint-input-ring-file-name
+              (concat remote hfile)))
       (if (or (equal comint-input-ring-file-name "")
 	      (equal (file-truename comint-input-ring-file-name)
 		     (file-truename null-device)))

Best regards, Michael.