From 4d34815b9ac32fb5055a79d10f112d34e48ae2a6 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 1 Jun 2024 18:03:42 +0300 Subject: [PATCH] shell-command-mode: New major mode for async-shell-command * etc/NEWS: Mention the additions. * lisp/shell.el (shell-command-mode): New major mode (bug#71049). * lisp/simple.el (async-shell-command-mode): New variable, with default value pointing to that mode. (shell-command): Refer to it here. (async-shell-command): Update docstring. * lisp/net/tramp.el (tramp-handle-shell-command): Use the new variable when available. (cherry picked from commit a154f0aa73bceeaaeefcd243e7db9d09e3f450d7) --- etc/NEWS | 5 +++++ lisp/net/tramp.el | 9 +++++++-- lisp/shell.el | 7 +++++++ lisp/simple.el | 19 +++++++++++-------- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index b97f8219317..19474b933a4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1999,6 +1999,11 @@ than regular expressions, but less complexity than context-free grammars. The Info manual "(elisp) Parsing Expression Grammars" has documentation and examples. +** New major mode 'shell-command-mode'. +This mode is used by default for the output of 'async-shell-command'. +To revert to the previous behavior, set the (also new) variable +'async-shell-command-mode' to 'shell-mode'. Any hooks or mode-specific +variables used should be adapted appropriately. * Incompatible Lisp Changes in Emacs 30.1 diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index eb7de36b560..06ba0cd59eb 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -5249,8 +5249,13 @@ support symbolic links." ;; Display output. (with-current-buffer output-buffer (setq mode-line-process '(":%s")) - (unless (eq major-mode 'shell-mode) - (shell-mode)) + (cond + ((boundp 'async-shell-command-mode) + ;; Emacs 30+ + (unless (eq major-mode async-shell-command-mode) + (funcall async-shell-command-mode))) + ((not (eq major-mode 'shell-mode)) + (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 eb05cddd15b..56ae1e1b15a 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -838,6 +838,13 @@ Sentinels will always get the two parameters PROCESS and EVENT." (with-current-buffer buf (insert (format "\nProcess %s %s\n" process event)))))) +(define-derived-mode shell-command-mode comint-mode "Shell" + "Major mode for the output of asynchronous `shell-command'." + (setq-local font-lock-defaults '(shell-font-lock-keywords t)) + ;; See comments in `shell-mode'. + (setq-local ansi-color-apply-face-function #'shell-apply-ansi-color) + (setq list-buffers-directory (expand-file-name default-directory))) + ;;;###autoload (defun shell (&optional buffer file-name) "Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*'). diff --git a/lisp/simple.el b/lisp/simple.el index 0211a65ed46..28642755b02 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -31,7 +31,6 @@ (eval-when-compile (require 'cl-lib)) (declare-function widget-convert "wid-edit" (type &rest args)) -(declare-function shell-mode "shell" ()) ;;; From compile.el (defvar compilation-current-error) @@ -4538,9 +4537,10 @@ to execute it asynchronously. The output appears in OUTPUT-BUFFER, which could be a buffer or the name of a buffer, and defaults to `shell-command-buffer-name-async' -if nil or omitted. That buffer is in shell mode. Note that, unlike -with `shell-command', OUTPUT-BUFFER can only be a buffer, a buffer's -name (a string), or nil. +if nil or omitted. That buffer is in major mode specified by the +variable `async-shell-command-mode'. Note that, unlike with +`shell-command', OUTPUT-BUFFER can only be a buffer, a buffer's name +(a string), or nil. You can customize `async-shell-command-buffer' to specify what to do when the buffer specified by `shell-command-buffer-name-async' is @@ -4584,6 +4584,9 @@ a shell (with its need to quote arguments)." (declare-function comint-output-filter "comint" (process string)) (declare-function comint-term-environment "comint" ()) +(defvar async-shell-command-mode 'shell-command-mode + "Major mode to use for the output of asynchronous `shell-command'.") + (defun shell-command (command &optional output-buffer error-buffer) "Execute string COMMAND in inferior shell; display output, if any. With prefix argument, insert the COMMAND's output at point. @@ -4594,9 +4597,9 @@ directory in the prompt. If COMMAND ends in `&', execute it asynchronously. The output appears in the buffer whose name is specified -by `shell-command-buffer-name-async'. That buffer is in shell -mode. You can also use `async-shell-command' that automatically -adds `&'. +by `shell-command-buffer-name-async'. That buffer is in major mode +specified by the variable `async-shell-command-mode'. You can also use +`async-shell-command' that automatically adds `&'. Otherwise, COMMAND is executed synchronously. The output appears in the buffer named by `shell-command-buffer-name'. If the output is @@ -4772,7 +4775,7 @@ impose the use of a shell (with its need to quote arguments)." (setq proc (start-process-shell-command "Shell" buffer command))) (setq mode-line-process '(":%s")) - (shell-mode) + (funcall async-shell-command-mode) (setq-local revert-buffer-function (lambda (&rest _) (async-shell-command command buffer))) -- 2.39.2