[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4fb6cf3: Add a new function 'shell-split-string'

From: Lars Ingebrigtsen
Subject: master 4fb6cf3: Add a new function 'shell-split-string'
Date: Thu, 15 Jul 2021 04:25:50 -0400 (EDT)

branch: master
commit 4fb6cf3f38511f3ca9ceb350a41993015969bdc1
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Add a new function 'shell-split-string'
    * doc/lispref/processes.texi (Shell Arguments): Document it.
    * lisp/shell.el (shell-split-string): New function.
 doc/lispref/processes.texi | 10 ++++++++++
 etc/NEWS                   |  5 +++++
 lisp/shell.el              |  9 +++++++++
 test/lisp/shell-tests.el   | 14 ++++++++++++++
 4 files changed, 38 insertions(+)

diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 0dfdac7..c8e9f0c 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -247,6 +247,16 @@ protected by @code{shell-quote-argument};
 @code{combine-and-quote-strings} is @emph{not} intended to protect
 special characters from shell evaluation.
+@defun shell-split-string string
+This function splits @var{string} into substrings, respecting double
+and single quotes, as well as backslash quoting.
+(shell-split-string "ls /tmp/'foo bar'")
+     @result{} ("ls" "/tmp/foo bar")
+@end smallexample
+@end defun
 @defun split-string-and-unquote string &optional separators
 This function splits @var{string} into substrings at matches for the
 regular expression @var{separators}, like @code{split-string} does
diff --git a/etc/NEWS b/etc/NEWS
index 555b465..29c2d9d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2970,6 +2970,11 @@ The former is now declared obsolete.
 * Lisp Changes in Emacs 28.1
+*** New function 'shell-split-string'.
+This splits a shell string into separate components, respecting single
+and double quotes, as well as backslash quoting.
 *** ':safe' settings in 'defcustom' are now propagated to the loaddefs files.
diff --git a/lisp/shell.el b/lisp/shell.el
index 4339e8c..15783bb 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -459,6 +459,15 @@ Useful for shells like zsh that has this feature."
           (push (mapconcat #'identity (nreverse arg) "") args)))
       (cons (nreverse args) (nreverse begins)))))
+(defun shell-split-string (string)
+  "Split STRING (a shell command) into a list of strings.
+General shell syntax, like single and double quoting, as well as
+backslash quoting, is respected."
+  (with-temp-buffer
+    (insert string)
+    (let ((comint-file-name-quote-list shell-file-name-quote-list))
+      (car (shell--parse-pcomplete-arguments)))))
 (defun shell-command-completion-function ()
   "Completion function for shell command names.
 This is the value of `pcomplete-command-completion-function' for
diff --git a/test/lisp/shell-tests.el b/test/lisp/shell-tests.el
index d918de7..ad54644 100644
--- a/test/lisp/shell-tests.el
+++ b/test/lisp/shell-tests.el
@@ -45,4 +45,18 @@
     (should (equal (shell--parse-pcomplete-arguments)
                    '(("cd" "ba" "") 1 4 7)))))
+(ert-deftest shell-tests-split-string ()
+  (should (equal (shell-split-string "ls /tmp")
+                 '("ls" "/tmp")))
+  (should (equal (shell-split-string "ls '/tmp/foo bar'")
+                 '("ls" "/tmp/foo bar")))
+  (should (equal (shell-split-string "ls \"/tmp/foo bar\"")
+                 '("ls" "/tmp/foo bar")))
+  (should (equal (shell-split-string "ls /tmp/'foo bar'")
+                 '("ls" "/tmp/foo bar")))
+  (should (equal (shell-split-string "ls /tmp/'foo\\ bar'")
+                 '("ls" "/tmp/foo\\ bar")))
+  (should (equal (shell-split-string "ls /tmp/foo\\ bar")
+                 '("ls" "/tmp/foo bar"))))
 ;;; shell-tests.el ends here

reply via email to

[Prev in Thread] Current Thread [Next in Thread]