org-element: Allow to escape escaping character before a comma

* lisp/org-element.el (org-element-macro-parser): Allow to escape
  escaping character before a comma.  Also do not trim spaces at
  argument boundaries.
* doc/org.texi (Macro replacement): Update documentation about
  possible locations and escaping mechanism.
* testing/lisp/test-org-element.el: Add tests.

With this patch, macro's arguments are read as the following:

  "a,b"     -> '("a" "b")
  "a\,b"    -> '("a,b")
  "a\\,b"   -> '("a\" "b")
  "a\\\,b"  -> '("a\,b")
  "a\\\\,b" -> '(a"\\" "b")

Note that with the patch, you only need to escape backslashes before
a comma:

  "a\\b\,c" -> '("a\\b,c")
This commit is contained in:
Nicolas Goaziou 2013-03-23 19:10:41 +01:00
parent 7847b4d7a8
commit 42e1a6351d
3 changed files with 30 additions and 18 deletions

View File

@ -9655,18 +9655,21 @@ You can define text snippets with
#+MACRO: name replacement text $1, $2 are arguments
@end example
@noindent which can be referenced anywhere in the document (even in
code examples) with @code{@{@{@{name(arg1,arg2)@}@}@}}. In addition to
defined macros, @code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc.,
will reference information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and
similar lines. Also, @code{@{@{@{date(@var{FORMAT})@}@}@}} and
@noindent which can be referenced in
paragraphs, verse blocks, table cells and some keywords with
@code{@{@{@{name(arg1,arg2)@}@}@}}@footnote{Since commas separate arguments,
commas within arguments have to be escaped with a backslash character.
Conversely, backslash characters before a comma, and only them, need to be
escaped with another backslash character.}. In addition to defined macros,
@code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, etc., will reference
information set by the @code{#+TITLE:}, @code{#+AUTHOR:}, and similar lines.
Also, @code{@{@{@{date(@var{FORMAT})@}@}@}} and
@code{@{@{@{modification-time(@var{FORMAT})@}@}@}} refer to current date time
and to the modification time of the file being exported, respectively.
@var{FORMAT} should be a format string understood by
@code{format-time-string}.
Macro expansion takes place during export, and some people use it to
construct complex HTML code.
Macro expansion takes place during export.
@node Embedded @LaTeX{}, , Macro replacement, Markup

View File

@ -3117,20 +3117,19 @@ Assume point is at the macro."
(post-blank (progn (goto-char (match-end 0))
(skip-chars-forward " \t")))
(end (point))
(args (let ((args (org-match-string-no-properties 3)) args2)
(args (let ((args (org-match-string-no-properties 3)))
(when args
;; Do not use `org-split-string' since empty
;; strings are meaningful here.
(setq args (split-string args ","))
(while args
(while (string-match "\\\\\\'" (car args))
;; Repair bad splits, when comma is protected,
;; and thus not a real separator.
(setcar (cdr args) (concat (substring (car args) 0 -1)
"," (nth 1 args)))
(pop args))
(push (pop args) args2))
(mapcar 'org-trim (nreverse args2))))))
(split-string
(replace-regexp-in-string
"\\(\\\\*\\)\\(,\\)"
(lambda (str)
(let ((len (length (match-string 1 str))))
(concat (make-string (/ len 2) ?\\)
(if (zerop (mod len 2)) "\000" ","))))
args nil t)
"\000")))))
(list 'macro
(list :key key
:value value

View File

@ -1345,6 +1345,16 @@ e^{i\\pi}+1=0
(should
(equal '("C-,")
(org-test-with-temp-text "{{{macro(C-\\,)}}}"
(org-element-property :args (org-element-context)))))
;; Allow to escape escaping character.
(should
(equal '("C-\\" "")
(org-test-with-temp-text "{{{macro(C-\\\\,)}}}"
(org-element-property :args (org-element-context)))))
;; No need to escape backslashes elsewhere.
(should
(equal '("\\")
(org-test-with-temp-text "{{{macro(\\)}}}"
(org-element-property :args (org-element-context))))))