]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix grep-like functions when running on a remote host
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 22 Mar 2022 09:29:16 +0000 (10:29 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Tue, 22 Mar 2022 09:29:16 +0000 (10:29 +0100)
* doc/lispref/processes.texi (Shell Arguments):
* etc/NEWS: Describe change in 'shell-quote-argument'.  Fix typos.

* lisp/subr.el (shell-quote-argument): New optional argument POSIX.

* lisp/progmodes/grep.el (grep-compute-defaults)
(grep-default-command, grep-expand-keywords, lgrep)
(rgrep-default-command): Use POSIX argument in
`shell-quote-argument'.  (Bug#54487)

doc/lispref/processes.texi
etc/NEWS
lisp/progmodes/grep.el
lisp/subr.el

index ed07c1cbf7035ea38a6cb4a33c7a12c4d8771e87..ea51abda4b74a2ccbeb1946eeec3ed21d54ac7f0 100644 (file)
@@ -197,7 +197,7 @@ gives special treatment to certain characters, and if these characters
 occur in the file name, they will confuse the shell.  To handle these
 characters, use the function @code{shell-quote-argument}:
 
-@defun shell-quote-argument argument
+@defun shell-quote-argument argument &optional posix
 This function returns a string that represents, in shell syntax,
 an argument whose actual contents are @var{argument}.  It should
 work reliably to concatenate the return value into a shell command
@@ -227,6 +227,15 @@ a shell command:
         " "
         (shell-quote-argument newfile))
 @end example
+
+If the optional @var{posix} argument is non-@code{nil}, @var{argument}
+is quoted according to POSIX shell quoting rules, regardless of the
+system’s shell.  This is useful when your shell could run on a remote
+host, which requires a POSIX shell in general.
+
+@example
+(shell-quote-argument "foo > bar" (file-remote-p default-directory))
+@end example
 @end defun
 
 @cindex quoting and unquoting command-line arguments
index ebf1346daee433606a2137ff2ed34980b1abb6e0..e64fe2d23bd2ca48bc5b7f8e9880a635a95747ba 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -578,9 +578,9 @@ the "*Completions*" buffer.  Available styles are no sorting,
 alphabetical (the default), or a custom sort function.
 
 +++
-*** New values for the 'completion-auto-help' option.
+*** New values for the 'completion-auto-help' user option.
 There are two new values to control the way "*Completions*" behave after
-a <tab> if completion is not unique.  'always' updates or shows
+a 'TAB' if completion is not unique.  'always' updates or shows
 the "*Completions*" buffer after any attempt to complete.  'visual' is
 like 'always', but only update the completions if they are already
 visible.  The default value 't' always hides the completion buffer after
@@ -591,16 +591,16 @@ some completion is made.
 This option limits the height of the "*Completions*" buffer.
 
 +++
-*** New option 'completions-header-format'
+*** New user option 'completions-header-format'
 This is a string to control the message to show before completions.
-It may contain a "%s" to show the total number of completions. If nil no
+It may contain a "%s" to show the total number of completions.  If nil no
 completions are shown.
 
 +++
-*** New option 'completions-highlight-face'.
-When this variable is a face name, it highlights the current candidate
-in the "*Completions*" buffer with that face.  When the value is nil,
-no highlighting is performed at all.
+*** New user option 'completions-highlight-face'.
+When this user option is a face name, it highlights the current
+candidate in the "*Completions*" buffer with that face.  When the
+value is nil, no highlighting is performed at all.
 
 ** Isearch and Replace
 
@@ -1207,7 +1207,7 @@ like:
 ---
 ** The 'inhibit-changing-match-data' variable is now obsolete.
 Instead, functions like 'string-match' and 'looking-at' now take an
-optional 'inhibit-modify' argument.
+optional INHIBIT-MODIFY argument.
 
 ---
 ** 'gnus-define-keys' is now obsolete.
@@ -1330,7 +1330,7 @@ This allows setting a minimum display width for a region of text.
 ** New 'cursor-face' text property.
 This uses 'cursor-face' instead of the default face when cursor is on or
 near the character and 'cursor-face-highlight-mode' is enabled.  The
-variable 'cursor-face-highlight-nonselected-window' is similar to
+user option 'cursor-face-highlight-nonselected-window' is similar to
 'highlight-nonselected-windows', but for this property.
 
 +++
@@ -1470,8 +1470,8 @@ This command lets you examine all data in the current selection and
 the clipboard, and insert it into the buffer.
 
 ---
-** New hook 'minibuffer-lazy-highlight-setup'.
-This hook is intended to be added to 'minibuffer-setup-hook'.
+** New function 'minibuffer-lazy-highlight-setup'.
+This function is intended to be added to 'minibuffer-setup-hook'.
 It sets up the minibuffer for lazy highlighting of matches
 in the original window.
 
@@ -1542,8 +1542,7 @@ from a specified amount of pixels above or below a position.
 ---
 ** 'eshell-eval-using-options' now follows POSIX/GNU argument syntax conventions.
 Built-in commands in Eshell now accept command-line options with
-values passed as a single token, such as '-oVALUE' or
-'--option=VALUE'.
+values passed as a single token, such as '-oVALUE' or '--option=VALUE'.
 
 ** XDG support
 
@@ -1748,11 +1747,16 @@ This is recorded in the `function-history` symbol property.
 ** 'indian-tml-base-table' no longer translates digits.
 Use 'indian-tml-base-digits-table' if you want digits translation.
 
---
+---
 ** 'indian-tml-itrans-v5-hash' no longer translates digits.
 Use 'indian-tml-itrans-digits-v5-hash' if you want digits
 translation.
 
++++
+** 'shell-quote-argument' has a new optional parameter POSIX.
+This is useful when quoting shell arguments for a remote shell
+invocation.  Such shells are POSIX conform by default.
+
 \f
 * Changes in Emacs 29.1 on Non-Free Operating Systems
 
index ccc58e6773c8aa566490d04bb4494edaa32f8798..21280888562fedf05064d5350375467e59be673f 100644 (file)
@@ -632,12 +632,12 @@ The value depends on `grep-command', `grep-template',
               ,grep-use-null-filename-separator)
             (grep-find-use-xargs ,grep-find-use-xargs)
             (grep-highlight-matches ,grep-highlight-matches)))))
-  (let* ((host-id
-         (intern (or (file-remote-p default-directory) "localhost")))
+  (let* ((remote (file-remote-p default-directory))
+         (host-id (intern (or remote "localhost")))
         (host-defaults (assq host-id grep-host-defaults-alist))
         (defaults (assq nil grep-host-defaults-alist))
-         (quot-braces (shell-quote-argument "{}"))
-         (quot-scolon (shell-quote-argument ";")))
+         (quot-braces (shell-quote-argument "{}" remote))
+         (quot-scolon (shell-quote-argument ";" remote)))
     ;; There are different defaults on different hosts.  They must be
     ;; computed for every host once.
     (dolist (setting '(grep-command grep-template
@@ -820,7 +820,9 @@ The value depends on `grep-command', `grep-template',
 
 (defun grep-default-command ()
   "Compute the default grep command for \\[universal-argument] \\[grep] to offer."
-  (let ((tag-default (shell-quote-argument (grep-tag-default)))
+  (let ((tag-default
+         (shell-quote-argument
+          (grep-tag-default) (file-remote-p default-directory)))
        ;; This a regexp to match single shell arguments.
        ;; Could someone please add comments explaining it?
        (sh-arg-re
@@ -963,7 +965,8 @@ easily repeat a find command."
     ("<F>" . files)
     ("<N>" . (null-device))
     ("<X>" . excl)
-    ("<R>" . (shell-quote-argument (or regexp ""))))
+    ("<R>" . (shell-quote-argument
+              (or regexp "") (file-remote-p (expand-file-name (or dir "."))))))
   "List of substitutions performed by `grep-expand-template'.
 If car of an element matches, the cdr is evalled in order to get the
 substitution string.
@@ -1112,11 +1115,12 @@ command before it's run."
   (when (and (stringp regexp) (> (length regexp) 0))
     (unless (and dir (file-accessible-directory-p dir))
       (setq dir default-directory))
-    (let ((command regexp))
+    (let ((command regexp) remote)
       (if (null files)
          (if (string= command grep-command)
              (setq command nil))
-       (setq dir (file-name-as-directory (expand-file-name dir)))
+       (setq dir (file-name-as-directory (expand-file-name dir))
+              remote (file-remote-p dir))
        (unless (or (not grep-use-directories-skip)
                     (eq grep-use-directories-skip t))
          (setq grep-use-directories-skip
@@ -1134,11 +1138,12 @@ command before it's run."
                                    (mapconcat
                                      (lambda (ignore)
                                        (cond ((stringp ignore)
-                                              (shell-quote-argument ignore))
+                                              (shell-quote-argument
+                                               ignore remote))
                                              ((consp ignore)
                                               (and (funcall (car ignore) dir)
                                                    (shell-quote-argument
-                                                    (cdr ignore))))))
+                                                    (cdr ignore) remote)))))
                                     grep-find-ignored-files
                                     " --exclude=")))
                       (and (eq grep-use-directories-skip t)
@@ -1242,48 +1247,50 @@ command before it's run."
 (defun rgrep-default-command (regexp files dir)
   "Compute the command for \\[rgrep] to use by default."
   (require 'find-dired)      ; for `find-name-arg'
-  (grep-expand-template
-   grep-find-template
-   regexp
-   (concat (shell-quote-argument "(")
-           " " find-name-arg " "
-           (mapconcat
-            #'shell-quote-argument
-            (split-string files)
-            (concat " -o " find-name-arg " "))
-           " "
-           (shell-quote-argument ")"))
-   dir
-   (concat
-    (and grep-find-ignored-directories
-         (concat "-type d "
-                 (shell-quote-argument "(")
-                 ;; we should use shell-quote-argument here
-                 " -path "
-                 (mapconcat (lambda (d) (shell-quote-argument (concat "*/" d)))
-                            (rgrep-find-ignored-directories dir)
-                            " -o -path ")
-                 " "
-                 (shell-quote-argument ")")
-                 " -prune -o "))
-    (and grep-find-ignored-files
-         (concat (shell-quote-argument "!") " -type d "
-                 (shell-quote-argument "(")
-                 ;; we should use shell-quote-argument here
-                 " -name "
-                 (mapconcat
-                  (lambda (ignore)
-                    (cond ((stringp ignore)
-                           (shell-quote-argument ignore))
-                          ((consp ignore)
-                           (and (funcall (car ignore) dir)
-                                (shell-quote-argument
-                                 (cdr ignore))))))
-                  grep-find-ignored-files
-                  " -o -name ")
-                 " "
-                 (shell-quote-argument ")")
-                 " -prune -o ")))))
+  (let ((remote (file-remote-p (or dir default-directory))))
+    (grep-expand-template
+     grep-find-template
+     regexp
+     (concat (shell-quote-argument "(" remote)
+             " " find-name-arg " "
+             (mapconcat
+              (lambda (x) (shell-quote-argument x remote))
+              (split-string files)
+              (concat " -o " find-name-arg " "))
+             " "
+             (shell-quote-argument ")" remote))
+     dir
+     (concat
+      (and grep-find-ignored-directories
+           (concat "-type d "
+                   (shell-quote-argument "(" remote)
+                   ;; we should use shell-quote-argument here
+                   " -path "
+                   (mapconcat
+                    (lambda (d) (shell-quote-argument (concat "*/" d) remote))
+                    (rgrep-find-ignored-directories dir)
+                    " -o -path ")
+                   " "
+                   (shell-quote-argument ")" remote)
+                   " -prune -o "))
+      (and grep-find-ignored-files
+           (concat (shell-quote-argument "!" remote) " -type d "
+                   (shell-quote-argument "(" remote)
+                   ;; we should use shell-quote-argument here
+                   " -name "
+                   (mapconcat
+                    (lambda (ignore)
+                      (cond ((stringp ignore)
+                             (shell-quote-argument ignore remote))
+                            ((consp ignore)
+                             (and (funcall (car ignore) dir)
+                                  (shell-quote-argument
+                                   (cdr ignore) remote)))))
+                    grep-find-ignored-files
+                    " -o -name ")
+                   " "
+                   (shell-quote-argument ")" remote)
+                   " -prune -o "))))))
 
 (defun grep-find-toggle-abbreviation ()
   "Toggle showing the hidden part of rgrep/lgrep/zrgrep command line."
index 8aadcfd453c9f882d47e16a879a456d83ad0a38a..603acffea7a1d67b9f643dbdecc3ea5e6c547752 100644 (file)
@@ -3760,14 +3760,18 @@ Note: :data and :device are currently not supported on Windows."
 
 (declare-function w32-shell-dos-semantics "w32-fns" nil)
 
-(defun shell-quote-argument (argument)
+(defun shell-quote-argument (argument &optional posix)
   "Quote ARGUMENT for passing as argument to an inferior shell.
 
 This function is designed to work with the syntax of your system's
 standard shell, and might produce incorrect results with unusual shells.
-See Info node `(elisp)Security Considerations'."
-  (cond
-   ((eq system-type 'ms-dos)
+See Info node `(elisp)Security Considerations'.
+
+If the optional POSIX argument is non-nil, ARGUMENT is quoted
+according to POSIX shell quoting rules, regardless of the
+system's shell."
+(cond
+   ((and (not posix) (eq system-type 'ms-dos))
     ;; Quote using double quotes, but escape any existing quotes in
     ;; the argument with backslashes.
     (let ((result "")
@@ -3782,7 +3786,7 @@ See Info node `(elisp)Security Considerations'."
                   start (1+ end))))
       (concat "\"" result (substring argument start) "\"")))
 
-   ((and (eq system-type 'windows-nt) (w32-shell-dos-semantics))
+   ((and (not posix) (eq system-type 'windows-nt) (w32-shell-dos-semantics))
 
     ;; First, quote argument so that CommandLineToArgvW will
     ;; understand it.  See