From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aaron Ecay Subject: [RFC] [PATCH] Automatically quote the arguments to an eval macro Date: Wed, 04 Nov 2015 14:30:33 +0000 Message-ID: <874mh1x2eu.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:37980) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ztz5C-0000EY-UI for emacs-orgmode@gnu.org; Wed, 04 Nov 2015 09:30:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ztz5A-0005vr-5A for emacs-orgmode@gnu.org; Wed, 04 Nov 2015 09:30:38 -0500 Received: from mail-wi0-x22b.google.com ([2a00:1450:400c:c05::22b]:38785) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ztz59-0005vm-Uy for emacs-orgmode@gnu.org; Wed, 04 Nov 2015 09:30:36 -0500 Received: by wicll6 with SMTP id ll6so33146243wic.1 for ; Wed, 04 Nov 2015 06:30:35 -0800 (PST) Received: from localhost (natvip7.york.ac.uk. [144.32.240.7]) by smtp.gmail.com with ESMTPSA id 5sm29037488wmg.14.2015.11.04.06.30.34 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Nov 2015 06:30:34 -0800 (PST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: orgmode --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hello all, Currently, eval macros need to quote their arguments: #+macro: identity (eval "$1") This means: 1. Users need to remember to put quotes around $n all the time 2. It=E2=80=99s impossible to pass arguments with a " character to a macro The attached patch changes the behavior of eval macro arguments so that $1 etc. expand to the argument with quotation marks. That is, the following is now the correct way to write a macro (note lack of "s): #+macro: identity (eval $1) This solves the above problems but: 1. breaks backwards compatibility of eval macros, since the with-quotes version is now incorrect 2. disables macros like the following, where the macro arguments are interpreted as lisp symbols: #+macro: funcall2 (eval ($1 $2 $3)) {{{funcall2(setq,org-export-with-date,nil)}}} For 1, I can add a check for "$n" constructs (including quotes) to org-lint and/or org-macro, to detect the backwards compatibility error. I believe that macros like in 2 are rather perverse: macro arguments are most similar to strings, not symbols or arbitrary pieces of lisp. (For arbitrary lisp evaluation, there=E2=80=99s babel.) Nonetheless, such macros can be recreated explicitly in the new system using eval+read and string interpolation: #+macro: funcall2 (eval (eval (read (format "(%s %s %s)" $1 $2 $3)))) Thoughts? Thanks, --=20 Aaron Ecay --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-macros-automatically-quote-the-arguments-to-an-eval-.patch >From c44b9b1f9a88e3bb88d1b4d9b59284ae840f02ce Mon Sep 17 00:00:00 2001 From: Aaron Ecay Date: Wed, 4 Nov 2015 12:13:07 +0000 Subject: [PATCH] macros: automatically quote the arguments to an eval macro * lisp/org-macro.el (org-macro-expand): Automatically quote the arguments to an eval macro. --- lisp/org-macro.el | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lisp/org-macro.el b/lisp/org-macro.el index 5f9c227..4858427 100644 --- a/lisp/org-macro.el +++ b/lisp/org-macro.el @@ -159,20 +159,24 @@ MACRO is an object, obtained, for example, with `org-element-context'. TEMPLATES is an alist of templates used for expansion. See `org-macro-templates' for a buffer-local default value. Return nil if no template was found." - (let ((template - ;; Macro names are case-insensitive. - (cdr (assoc-string (org-element-property :key macro) templates t)))) + (let* ((template + ;; Macro names are case-insensitive. + (cdr (assoc-string (org-element-property :key macro) templates t))) + ;; Macro starts with "(eval": it is a s-exp and will be `eval'-ed. + (evalp (string-match "\\`(eval\\>" template))) (when template (let ((value (replace-regexp-in-string "\\$[0-9]+" (lambda (arg) - (or (nth (1- (string-to-number (substring arg 1))) - (org-element-property :args macro)) - ;; No argument: remove place-holder. - "")) + (let ((arg-val (nth (1- (string-to-number (substring arg 1))) + (org-element-property :args macro)))) + (cond + (evalp (format "%S" arg-val)) + (arg-val arg-val) + ;; No argument: remove place-holder. + (t "")))) template nil 'literal))) - ;; VALUE starts with "(eval": it is a s-exp, `eval' it. - (when (string-match "\\`(eval\\>" value) + (when evalp (setq value (eval (read value)))) ;; Return string. (format "%s" (or value "")))))) -- 2.6.2 --=-=-=--