forked from mirrors/org-mode
macro: Implement argument extracting and escaping functions
* lisp/org-macro.el (org-macro-escape-arguments, org-macro-extract-arguments): New functions. * lisp/org-element.el (org-element-macro-parser): Use new function. * testing/lisp/test-org-macro.el (test-org-macro/escape-arguments, test-org-macro/extract-arguments): New tests.
This commit is contained in:
parent
a84c467b8e
commit
ec0706ea40
|
@ -3091,18 +3091,7 @@ Assume point is at the macro."
|
||||||
(skip-chars-forward " \t")))
|
(skip-chars-forward " \t")))
|
||||||
(end (point))
|
(end (point))
|
||||||
(args (let ((args (org-match-string-no-properties 3)))
|
(args (let ((args (org-match-string-no-properties 3)))
|
||||||
(when args
|
(and args (org-macro-extract-arguments args)))))
|
||||||
;; Do not use `org-split-string' since empty
|
|
||||||
;; strings are meaningful here.
|
|
||||||
(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 'macro
|
||||||
(list :key key
|
(list :key key
|
||||||
:value value
|
:value value
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
;; `org-macro-initialize-templates', which recursively calls
|
;; `org-macro-initialize-templates', which recursively calls
|
||||||
;; `org-macro--collect-macros' in order to read setup files.
|
;; `org-macro--collect-macros' in order to read setup files.
|
||||||
|
|
||||||
|
;; Argument in macros are separated with commas. Proper escaping rules
|
||||||
|
;; are implemented in `org-macro-escape-arguments' and arguments can
|
||||||
|
;; be extracted from a string with `org-macro-extract-arguments'.
|
||||||
|
|
||||||
;; Along with macros defined through #+MACRO: keyword, default
|
;; Along with macros defined through #+MACRO: keyword, default
|
||||||
;; templates include the following hard-coded macros:
|
;; templates include the following hard-coded macros:
|
||||||
;; {{{time(format-string)}}}, {{{property(node-property)}}},
|
;; {{{time(format-string)}}}, {{{property(node-property)}}},
|
||||||
|
@ -195,6 +199,47 @@ found in the buffer with no definition in TEMPLATES."
|
||||||
(error "Undefined Org macro: %s; aborting."
|
(error "Undefined Org macro: %s; aborting."
|
||||||
(org-element-property :key object))))))))))))
|
(org-element-property :key object))))))))))))
|
||||||
|
|
||||||
|
(defun org-macro-escape-arguments (&rest args)
|
||||||
|
"Build macro's arguments string from ARGS.
|
||||||
|
ARGS are strings. Return value is a string with arguments
|
||||||
|
properly escaped and separated with commas. This is the opposite
|
||||||
|
of `org-macro-extract-arguments'."
|
||||||
|
(let ((s ""))
|
||||||
|
(dolist (arg (reverse args) (substring s 1))
|
||||||
|
(setq s
|
||||||
|
(concat
|
||||||
|
","
|
||||||
|
(replace-regexp-in-string
|
||||||
|
"\\(\\\\*\\),"
|
||||||
|
(lambda (m)
|
||||||
|
(concat (make-string (1+ (* 2 (length (match-string 1 m)))) ?\\)
|
||||||
|
","))
|
||||||
|
;; If a non-terminal argument ends on backslashes, make
|
||||||
|
;; sure to also escape them as they will be followed by
|
||||||
|
;; a comma.
|
||||||
|
(concat arg (and (not (equal s ""))
|
||||||
|
(string-match "\\\\+\\'" arg)
|
||||||
|
(match-string 0 arg)))
|
||||||
|
nil t)
|
||||||
|
s)))))
|
||||||
|
|
||||||
|
(defun org-macro-extract-arguments (s)
|
||||||
|
"Extract macro arguments from string S.
|
||||||
|
S is a string containing comma separated values properly escaped.
|
||||||
|
Return a list of arguments, as strings. This is the opposite of
|
||||||
|
`org-macro-escape-arguments'."
|
||||||
|
;; Do not use `org-split-string' since empty strings are
|
||||||
|
;; meaningful here.
|
||||||
|
(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" ","))))
|
||||||
|
s nil t)
|
||||||
|
"\000"))
|
||||||
|
|
||||||
|
|
||||||
(provide 'org-macro)
|
(provide 'org-macro)
|
||||||
;;; org-macro.el ends here
|
;;; org-macro.el ends here
|
||||||
|
|
|
@ -76,6 +76,30 @@
|
||||||
(org-macro-replace-all org-macro-templates)
|
(org-macro-replace-all org-macro-templates)
|
||||||
(buffer-string)))))
|
(buffer-string)))))
|
||||||
|
|
||||||
|
(ert-deftest test-org-macro/escape-arguments ()
|
||||||
|
"Test `org-macro-escape-arguments' specifications."
|
||||||
|
;; Regular tests.
|
||||||
|
(should (equal "a" (org-macro-escape-arguments "a")))
|
||||||
|
(should (equal "a,b" (org-macro-escape-arguments "a" "b")))
|
||||||
|
;; Handle empty arguments.
|
||||||
|
(should (equal "a,,b" (org-macro-escape-arguments "a" "" "b")))
|
||||||
|
;; Properly escape commas and backslashes preceding them.
|
||||||
|
(should (equal "a\\,b" (org-macro-escape-arguments "a,b")))
|
||||||
|
(should (equal "a\\\\,b" (org-macro-escape-arguments "a\\" "b")))
|
||||||
|
(should (equal "a\\\\\\,b" (org-macro-escape-arguments "a\\,b"))))
|
||||||
|
|
||||||
|
(ert-deftest test-org-macro/extract-arguments ()
|
||||||
|
"Test `org-macro-extract-arguments' specifications."
|
||||||
|
;; Regular tests.
|
||||||
|
(should (equal '("a") (org-macro-extract-arguments "a")))
|
||||||
|
(should (equal '("a" "b") (org-macro-extract-arguments "a,b")))
|
||||||
|
;; Handle empty arguments.
|
||||||
|
(should (equal '("a" "" "b") (org-macro-extract-arguments "a,,b")))
|
||||||
|
;; Handle escaped commas and backslashes.
|
||||||
|
(should (equal '("a,b") (org-macro-extract-arguments "a\\,b")))
|
||||||
|
(should (equal '("a\\" "b") (org-macro-extract-arguments "a\\\\,b")))
|
||||||
|
(should (equal '("a\\,b") (org-macro-extract-arguments "a\\\\\\,b"))))
|
||||||
|
|
||||||
|
|
||||||
(provide 'test-org-macro)
|
(provide 'test-org-macro)
|
||||||
;;; test-org-macro.el ends here
|
;;; test-org-macro.el ends here
|
||||||
|
|
Loading…
Reference in a new issue