From: taylanbayirli@gmail.com (Taylan Ulrich Bayırlı/Kammer)
To: emacs-devel@gnu.org
Subject: Re: [PATCH] Add shell-quasiquote.
Date: Mon, 19 Oct 2015 14:35:26 +0200 [thread overview]
Message-ID: <878u6znii9.fsf@T420.taylan> (raw)
In-Reply-To: <87si59wj42.fsf@T420.taylan> ("Taylan Ulrich \=\?utf-8\?Q\?\=5C\=22Bay\=C4\=B1rl\=C4\=B1\=2FKammer\=5C\=22\=22's\?\= message of "Sat, 17 Oct 2015 18:33:01 +0200")
[-- Attachment #1: Type: text/plain, Size: 469 bytes --]
taylanbayirli@gmail.com (Taylan Ulrich "Bayırlı/Kammer") writes:
> This is for ELPA.
>
> [...]
Here's a version with slightly improved documentation and a clearer
reasoning for why shell-quote-argument is avoided.
Eli refused to clarify the safety guarantees of shell-quote-argument in
bug#21702, and after all it has significantly different semantics anyway
(it doesn't quote shell keywords like 'if'), so I will not be using
shell-quote-argument.
[-- Attachment #2: 0001-Add-shell-quasiquote.patch --]
[-- Type: text/x-diff, Size: 6233 bytes --]
From 276e3adc61b2f083b0348fd231a97feaa7017e36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Taylan=20Ulrich=20Bay=C4=B1rl=C4=B1/Kammer?=
<taylanbayirli@gmail.com>
Date: Sat, 17 Oct 2015 18:32:22 +0200
Subject: [PATCH 1/3] Add shell-quasiquote.
---
packages/shell-quasiquote/shell-quasiquote.el | 151 ++++++++++++++++++++++++++
1 file changed, 151 insertions(+)
create mode 100644 packages/shell-quasiquote/shell-quasiquote.el
diff --git a/packages/shell-quasiquote/shell-quasiquote.el b/packages/shell-quasiquote/shell-quasiquote.el
new file mode 100644
index 0000000..1f18862
--- /dev/null
+++ b/packages/shell-quasiquote/shell-quasiquote.el
@@ -0,0 +1,151 @@
+;;; shell-quasiquote.el --- Turn s-expressions into shell command strings.
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
+;; Keywords: extensions, unix
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; "Shell quasiquote" -- turn s-expressions into POSIX shell command strings.
+;;
+;; Shells other than POSIX sh are not supported.
+;;
+;; Quoting is automatic and safe against injection.
+;;
+;; (let ((file1 "file one")
+;; (file2 "file two"))
+;; (shqq (cp -r ,file1 ,file2 "My Files")))
+;; => "cp -r 'file one' 'file two' 'My Files'"
+;;
+;; You can splice many arguments into place with ,@foo.
+;;
+;; (let ((files (list "file one" "file two")))
+;; (shqq (cp -r ,@files "My Files")))
+;; => "cp -r 'file one' 'file two' 'My Files'"
+;;
+;; Note that the quoting disables a variety of shell expansions like ~/foo,
+;; $ENV_VAR, and e.g. {x..y} in GNU Bash.
+;;
+;; You can use ,,foo to escape the quoting.
+;;
+;; (let ((files "file1 file2"))
+;; (shqq (cp -r ,,files "My Files")))
+;; => "cp -r file1 file2 'My Files'"
+;;
+;; And ,,@foo to splice and escape quoting.
+;;
+;; (let* ((arglist '("-x 'foo bar' -y baz"))
+;; (arglist (append arglist '("-z 'qux fux'"))))
+;; (shqq (command ,,@arglist)))
+;; => "command -x 'foo bar' -y baz -z 'qux fux'"
+;;
+;; Neat, eh?
+
+\f
+;;; Code:
+
+;;; We don't use `shell-quote-argument' because it doesn't provide any safety
+;;; guarantees, and this quotes shell keywords as well.
+(defun shqq--quote-string (string)
+ (concat "'" (replace-regexp-in-string "'" "'\\\\''" string) "'"))
+
+(defun shqq--atom-to-string (atom)
+ (cond
+ ((symbolp atom) (symbol-name atom))
+ ((stringp atom) atom)
+ ((numberp atom) (number-to-string atom))
+ (t (error "Bad shqq atom: %S" atom))))
+
+(defun shqq--quote-atom (atom)
+ (shqq--quote-string (shqq--atom-to-string atom)))
+
+(defun shqq--match-comma (form)
+ "Matches FORM against ,foo i.e. (\, foo) and returns foo.
+Returns nil if FORM didn't match. You can't disambiguate between
+FORM matching ,nil and not matching."
+ (if (and (consp form)
+ (eq '\, (car form))
+ (consp (cdr form))
+ (null (cddr form)))
+ (cadr form)))
+
+(defun shqq--match-comma2 (form)
+ "Matches FORM against ,,foo i.e. (\, (\, foo)) and returns foo.
+Returns nil if FORM didn't match. You can't disambiguate between
+FORM matching ,,nil and not matching."
+ (if (and (consp form)
+ (eq '\, (car form))
+ (consp (cdr form))
+ (null (cddr form)))
+ (shqq--match-comma (cadr form))))
+
+\f
+(defmacro shqq (parts)
+ "First, PARTS is turned into a list of strings. For this,
+every element of PARTS must be one of:
+
+- a symbol, evaluating to its name,
+
+- a string, evaluating to itself,
+
+- a number, evaluating to its decimal representation,
+
+- \",expr\", where EXPR must evaluate to an atom that will be
+ interpreted according to the previous rules,
+
+- \",@list-expr\", where LIST-EXPR must evaluate to a list whose
+ elements will each be interpreted like the EXPR in an \",EXPR\"
+ form, and spliced into the list of strings,
+
+- \",,expr\", where EXPR is interpreted like in \",expr\",
+
+- or \",,@expr\", where EXPR is interpreted like in \",@expr\".
+
+In the resulting list of strings, all elements except the ones
+resulting from \",,expr\" and \",,@expr\" forms are quoted for
+shell grammar.
+
+Finally, the resulting list of strings is concatenated with
+separating spaces."
+ (let ((parts
+ (mapcar
+ (lambda (part)
+ (cond
+ ((atom part) (shqq--quote-atom part))
+ ;; We use the match-comma helpers because pcase can't match ,foo.
+ (t (pcase part
+ ;; ,,foo i.e. (, (, foo))
+ ((pred shqq--match-comma2)
+ (shqq--match-comma2 part))
+ ;; ,,@foo i.e. (, (,@ foo))
+ ((and (pred shqq--match-comma)
+ (let `,@,form (shqq--match-comma part)))
+ `(mapconcat #'identity ,form " "))
+ ;; ,foo
+ ;; Insert redundant 'and x' to work around debbugs#18554.
+ ((and x (pred shqq--match-comma))
+ `(shqq--quote-atom ,(shqq--match-comma part)))
+ ;; ,@foo
+ (`,@,form
+ `(mapconcat #'shqq--quote-atom ,form " "))
+ (_
+ (error "Bad shqq part: %S" part))))))
+ parts)))
+ `(mapconcat #'identity (list ,@parts) " ")))
+
+(provide 'shell-quasiquote)
+;;; shell-quasiquote.el ends here
--
2.5.0
next prev parent reply other threads:[~2015-10-19 12:35 UTC|newest]
Thread overview: 211+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-17 16:33 [PATCH] Add shell-quasiquote Taylan Ulrich Bayırlı/Kammer
2015-10-17 16:53 ` Eli Zaretskii
2015-10-17 17:14 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 17:28 ` Eli Zaretskii
2015-10-17 18:23 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 19:09 ` Eli Zaretskii
2015-10-17 20:28 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 20:44 ` Dmitry Gutov
2015-10-17 21:25 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 21:32 ` Dmitry Gutov
2015-10-17 22:00 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 7:55 ` Michael Albinus
2015-10-18 10:07 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 10:55 ` Michael Albinus
2015-10-18 12:59 ` Random832
2015-10-18 13:36 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 15:06 ` Michael Albinus
2015-10-18 17:32 ` Eli Zaretskii
2015-10-18 19:17 ` Random832
2015-10-18 19:52 ` Eli Zaretskii
2015-10-19 4:32 ` Stephen J. Turnbull
2015-10-19 5:15 ` Eli Zaretskii
2015-10-19 5:19 ` Daniel Colascione
2015-10-19 5:56 ` Eli Zaretskii
2015-10-19 8:16 ` Taylan Ulrich Bayırlı/Kammer
2015-10-31 17:03 ` Kai Großjohann
2015-10-31 16:50 ` Kai Großjohann
2015-10-31 19:03 ` Michael Albinus
2015-10-17 22:09 ` Random832
2015-10-17 22:45 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 20:47 ` Paul Eggert
2015-10-17 21:20 ` Random832
2015-10-17 21:35 ` Paul Eggert
2015-10-17 21:27 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 21:53 ` Paul Eggert
2015-10-17 22:22 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 2:40 ` Paul Eggert
2015-10-18 10:03 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 15:54 ` Eli Zaretskii
2015-10-18 16:40 ` Taylan Ulrich Bayırlı/Kammer
2015-10-18 17:48 ` John Wiegley
2015-10-18 2:47 ` Eli Zaretskii
2015-10-18 13:35 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 19:14 ` Random832
2015-10-17 19:44 ` Eli Zaretskii
2015-10-17 20:43 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 21:01 ` Random832
2015-10-17 17:23 ` Artur Malabarba
2015-10-17 18:11 ` Taylan Ulrich Bayırlı/Kammer
2015-10-17 18:42 ` Artur Malabarba
2015-10-19 12:35 ` Taylan Ulrich Bayırlı/Kammer [this message]
2015-10-19 12:59 ` David Kastrup
2015-10-19 13:09 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 13:48 ` Random832
2015-10-19 13:53 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 15:10 ` Paul Eggert
2015-10-19 17:06 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 1:41 ` Paul Eggert
2015-10-20 7:41 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 10:16 ` Nicolas Richard
2015-10-20 15:47 ` Dmitry Gutov
2015-10-20 16:41 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 16:59 ` Dmitry Gutov
2015-10-20 17:32 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 17:41 ` Dmitry Gutov
2015-10-20 17:58 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 18:11 ` Dmitry Gutov
2015-10-20 18:19 ` Eli Zaretskii
2015-10-20 23:34 ` Contributors and maintainers (Was: [PATCH] Add shell-quasiquote.) John Wiegley
2015-10-21 7:29 ` Contributors and maintainers Taylan Ulrich Bayırlı/Kammer
2015-10-21 8:27 ` Werner LEMBERG
2015-10-21 8:45 ` David Kastrup
2015-10-21 12:03 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 14:22 ` Eli Zaretskii
2015-10-21 14:40 ` David Kastrup
2015-10-21 16:05 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 18:16 ` Stephen J. Turnbull
2015-10-21 18:37 ` John Wiegley
2015-10-21 14:34 ` Tassilo Horn
2015-10-21 16:53 ` John Wiegley
2015-10-21 17:24 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 18:49 ` John Wiegley
2015-10-21 14:07 ` Eli Zaretskii
2015-10-21 14:36 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 15:44 ` David Kastrup
2015-10-21 16:23 ` Eli Zaretskii
2015-10-21 17:22 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 17:41 ` Eli Zaretskii
2015-10-21 19:58 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 21:21 ` John Wiegley
2015-10-21 23:12 ` David Kastrup
2015-10-22 14:38 ` Eli Zaretskii
2015-10-21 14:45 ` Jay Belanger
2015-10-21 17:05 ` John Wiegley
2015-10-21 17:46 ` Taylan Ulrich Bayırlı/Kammer
2015-10-21 18:12 ` John Wiegley
2015-10-21 18:19 ` Eli Zaretskii
2015-10-21 18:18 ` Stephen J. Turnbull
2015-10-21 18:54 ` John Wiegley
2015-10-22 5:40 ` Maintainers and contributors (was: Contributors and maintainers) John Wiegley
2015-10-22 7:20 ` Maintainers and contributors David Kastrup
2015-10-22 10:34 ` Maintainers and contributors (was: Contributors and maintainers) Artur Malabarba
2015-10-22 11:08 ` Maintainers and contributors David Kastrup
2015-10-22 11:55 ` Artur Malabarba
2015-10-22 12:04 ` Dmitry Gutov
2015-10-22 12:32 ` David Kastrup
2015-10-22 15:10 ` Eli Zaretskii
2015-10-22 18:27 ` John Wiegley
2015-10-22 19:08 ` Dmitry Gutov
2015-10-22 23:37 ` John Wiegley
2015-10-23 0:37 ` Jay Belanger
2015-10-22 18:58 ` Jay Belanger
2015-10-21 3:25 ` [PATCH] Add shell-quasiquote Random832
2015-10-21 4:30 ` David Kastrup
2015-10-21 14:05 ` Eli Zaretskii
2015-10-21 14:18 ` Random832
2015-10-21 14:40 ` Michael Albinus
2015-10-21 16:19 ` Eli Zaretskii
2015-10-21 16:37 ` David Kastrup
2015-10-21 17:18 ` Eli Zaretskii
2015-10-21 17:06 ` Random832
2015-10-21 17:32 ` Eli Zaretskii
2015-10-21 18:11 ` Stephen J. Turnbull
2015-10-21 18:24 ` David Kastrup
2015-10-26 12:58 ` Steinar Bang
2015-10-21 18:24 ` Wolfgang Jenkner
2015-10-21 18:44 ` Eli Zaretskii
2015-10-21 18:57 ` Wolfgang Jenkner
2015-10-21 19:10 ` Eli Zaretskii
2015-10-21 19:30 ` John Wiegley
2015-10-22 10:54 ` Wolfgang Jenkner
2015-10-22 11:21 ` Jeff Clough
2015-10-22 12:47 ` David Kastrup
2015-10-22 15:11 ` Eli Zaretskii
2015-10-22 15:23 ` David Kastrup
2015-10-22 15:51 ` Andreas Schwab
2015-10-22 13:09 ` Wolfgang Jenkner
2015-10-22 15:03 ` Eli Zaretskii
2015-10-22 15:12 ` David Kastrup
2015-11-06 23:35 ` Kai Großjohann
2015-11-07 7:51 ` Eli Zaretskii
2015-10-22 15:41 ` Paul Eggert
2015-10-22 15:52 ` Eli Zaretskii
2015-10-22 17:25 ` Wolfgang Jenkner
2015-10-21 18:11 ` David Kastrup
2015-10-21 18:49 ` Random832
2015-10-21 19:03 ` Eli Zaretskii
2015-10-21 19:10 ` Random832
2015-10-21 19:21 ` Eli Zaretskii
2015-10-21 19:50 ` Random832
2015-10-22 2:38 ` Eli Zaretskii
2015-10-22 7:03 ` David Kastrup
2015-10-22 13:41 ` Random832
2015-10-22 13:53 ` David Kastrup
2015-10-22 14:41 ` Random832
2015-10-22 14:50 ` David Kastrup
2015-10-22 16:18 ` Stephen J. Turnbull
2015-10-22 15:20 ` Eli Zaretskii
2015-11-01 18:39 ` Kai Großjohann
2015-11-01 20:39 ` Eli Zaretskii
2015-11-01 22:34 ` Michael Albinus
2015-10-20 19:00 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 19:48 ` Werner LEMBERG
2015-10-20 20:47 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 21:08 ` Werner LEMBERG
2015-10-21 14:09 ` Eli Zaretskii
2015-10-21 18:22 ` John Wiegley
2015-10-20 16:21 ` Paul Eggert
2015-10-20 17:11 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 17:22 ` Paul Eggert
2015-10-20 17:36 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 18:12 ` Paul Eggert
2015-10-20 18:21 ` Eli Zaretskii
2015-10-20 18:55 ` Taylan Ulrich Bayırlı/Kammer
2015-10-22 3:35 ` Paul Eggert
2015-10-19 13:22 ` Eli Zaretskii
2015-10-19 13:36 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 13:56 ` Eli Zaretskii
2015-10-19 13:41 ` Artur Malabarba
2015-10-19 13:43 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 13:55 ` Dmitry Gutov
2015-10-19 14:09 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 15:13 ` Dmitry Gutov
2015-10-19 17:08 ` Taylan Ulrich Bayırlı/Kammer
2015-10-19 17:11 ` Dmitry Gutov
2015-10-19 17:46 ` Eli Zaretskii
2015-10-20 4:35 ` Stephen J. Turnbull
2015-10-20 7:26 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 7:55 ` David Kastrup
2015-10-20 8:17 ` John Wiegley
2015-10-20 8:38 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 12:48 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 11:45 ` Becoming an Emacs contributor (was: [PATCH] Add shell-quasiquote.) Óscar Fuentes
2015-10-20 12:56 ` Becoming an Emacs contributor Taylan Ulrich Bayırlı/Kammer
2015-10-20 16:26 ` Eli Zaretskii
2015-10-20 17:32 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 17:41 ` Eli Zaretskii
2015-10-20 17:53 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 17:53 ` David Kastrup
2015-10-20 18:44 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 19:12 ` David Kastrup
2015-10-24 17:26 ` Nix
2015-10-20 16:47 ` Becoming an Emacs contributor (was: [PATCH] Add shell-quasiquote.) Kaushal Modi
2015-10-20 8:34 ` [PATCH] Add shell-quasiquote Taylan Ulrich Bayırlı/Kammer
2015-10-20 8:49 ` David Kastrup
2015-10-20 8:54 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 15:40 ` Eli Zaretskii
2015-10-20 16:31 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 16:51 ` Eli Zaretskii
2015-10-20 17:28 ` Taylan Ulrich Bayırlı/Kammer
2015-10-20 18:02 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=878u6znii9.fsf@T420.taylan \
--to=taylanbayirli@gmail.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.