From: Lars Ingebrigtsen Date: Thu, 15 Jul 2021 08:25:41 +0000 (+0200) Subject: Add a new function 'shell-split-string' X-Git-Tag: emacs-28.0.90~1864 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4fb6cf3f38511f3ca9ceb350a41993015969bdc1;p=emacs.git Add a new function 'shell-split-string' * doc/lispref/processes.texi (Shell Arguments): Document it. * lisp/shell.el (shell-split-string): New function. --- diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 0dfdac71479..c8e9f0cea6e 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. + +@smallexample +(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 555b465e84b..29c2d9db73f 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 4339e8c0a3b..15783bb9246 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 d918de771b7..ad54644e556 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