emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [RFC] [PATCH] Automatically quote the arguments to an eval macro
@ 2015-11-04 14:30 Aaron Ecay
  2015-11-05  8:40 ` Nicolas Goaziou
  0 siblings, 1 reply; 3+ messages in thread
From: Aaron Ecay @ 2015-11-04 14:30 UTC (permalink / raw)
  To: orgmode

[-- Attachment #1: Type: text/plain, Size: 1394 bytes --]

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’s 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’s 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,

-- 
Aaron Ecay

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-macros-automatically-quote-the-arguments-to-an-eval-.patch --]
[-- Type: text/x-diff, Size: 2103 bytes --]

From c44b9b1f9a88e3bb88d1b4d9b59284ae840f02ce Mon Sep 17 00:00:00 2001
From: Aaron Ecay <aaronecay@gmail.com>
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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC] [PATCH] Automatically quote the arguments to an eval macro
  2015-11-04 14:30 [RFC] [PATCH] Automatically quote the arguments to an eval macro Aaron Ecay
@ 2015-11-05  8:40 ` Nicolas Goaziou
  2015-11-05 14:29   ` Aaron Ecay
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Goaziou @ 2015-11-05  8:40 UTC (permalink / raw)
  To: orgmode

Hello,

Aaron Ecay <aaronecay@gmail.com> writes:

> 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’s impossible to pass arguments with a " character to a macro

This can be fixed by removing the `literal' optional argument from
`replace-regexp-in-string' call in `org-macro-expand'.

> 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)

I'm not totally opposed to it but it introduces a limitation: all
arguments must be strings. This is not strictly required, actually. As
a consequence, I slightly prefer fixing the current situation instead.

Is there any strong reason to force string?

> * lisp/org-macro.el (org-macro-expand): Automatically quote the
> arguments to an eval macro.

You would also need to update `org-macro-initialize-templates' and
`org-export-as'.

> +			(cond
> +			 (evalp (format "%S" arg-val))
> +			 (arg-val arg-val)

Nitpick: this is equivalent to (arg-val)


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC] [PATCH] Automatically quote the arguments to an eval macro
  2015-11-05  8:40 ` Nicolas Goaziou
@ 2015-11-05 14:29   ` Aaron Ecay
  0 siblings, 0 replies; 3+ messages in thread
From: Aaron Ecay @ 2015-11-05 14:29 UTC (permalink / raw)
  To: Nicolas Goaziou, orgmode

Hi Nicolas,

Thanks for your feedback.

2015ko azaroak 5an, Nicolas Goaziou-ek idatzi zuen:

[...]

>> This means:
>> 1. Users need to remember to put quotes around $n all the time
>> 2. It’s impossible to pass arguments with a " character to a macro
> 
> This can be fixed by removing the `literal' optional argument from
> `replace-regexp-in-string' call in `org-macro-expand'.

I’ve actually managed to make it work with the code as-is, by escaping
the quote with a single backslash.  I must have been confused about
single- vs. double-escaping.

The inconsistency that remains is that quotes need to be backslash-escaped
for eval macros, but not regular macros.

Here’s a test case (works with current master):

,----
| #+macro: foo $1
| 
| {{{foo(xyz\"abc)}}}
| 
| #+macro: bar (eval "$1")
| 
| {{{bar(xyz\"abc)}}}
`----

Ascii export yields:

,----
| Foo is: xyz\"abc
| 
| Bar is: xyz"abc
`----

> 
>> 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)
> 
> I'm not totally opposed to it but it introduces a limitation: all
> arguments must be strings. This is not strictly required, actually. As
> a consequence, I slightly prefer fixing the current situation instead.
> 
> Is there any strong reason to force string?

I’d say the reason is that (AIUI) macros are for string manipulation
during export.  I’m hard-pressed to come up with a good usage of a macro
that treats its arguments as non-strings.  But maybe that’s just a
function of my limited creativity. :)

> 
>> * lisp/org-macro.el (org-macro-expand): Automatically quote the
>> arguments to an eval macro.
> 
> You would also need to update `org-macro-initialize-templates' and
> `org-export-as'.
> 
>> +			(cond
>> +			 (evalp (format "%S" arg-val))
>> +			 (arg-val arg-val)
> 
> Nitpick: this is equivalent to (arg-val)

I didn’t know this usage of cond....

Thanks again,

-- 
Aaron Ecay

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-11-05 14:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-04 14:30 [RFC] [PATCH] Automatically quote the arguments to an eval macro Aaron Ecay
2015-11-05  8:40 ` Nicolas Goaziou
2015-11-05 14:29   ` Aaron Ecay

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).