forked from mirrors/org-mode
org-macro: Implement the "n" macro
* lisp/org-macro.el (org-macro--counter-table): New variable. (org-macro--counter-initialize): (org-macro--counter-increment): New functions. (org-macro-initialize-templates): Use new functions. * doc/org.texi (Macro replacement): Document new macro. * testing/lisp/test-org-macro.el (test-org-macro/n): (test-org-macro/property): New tests.
This commit is contained in:
parent
6b6476b89c
commit
ad89390219
|
@ -197,6 +197,9 @@ contents, are now supported.
|
|||
This new function is meant to be used in back-ends supporting images
|
||||
as descriptions of links, a.k.a. image links. See its docstring for
|
||||
details.
|
||||
**** New macro : ~{{{n}}}~
|
||||
This macro creates and increment multiple counters in a document. See
|
||||
manual for details.
|
||||
**** Add global macros through ~org-export-global-macros~
|
||||
With this variable, one can define macros available for all documents.
|
||||
**** New keyword ~#+EXPORT_FILE_NAME~
|
||||
|
|
|
@ -36,8 +36,11 @@
|
|||
|
||||
;; Along with macros defined through #+MACRO: keyword, default
|
||||
;; templates include the following hard-coded macros:
|
||||
;; {{{time(format-string)}}}, {{{property(node-property)}}},
|
||||
;; {{{input-file}}} and {{{modification-time(format-string)}}}.
|
||||
;; {{{time(format-string)}}},
|
||||
;; {{{property(node-property)}}},
|
||||
;; {{{input-file}}},
|
||||
;; {{{modification-time(format-string)}}},
|
||||
;; {{{n(counter,reset}}}.
|
||||
|
||||
;; Upon exporting, "ox.el" will also provide {{{author}}}, {{{date}}},
|
||||
;; {{{email}}} and {{{title}}} macros.
|
||||
|
@ -129,7 +132,7 @@ function installs the following ones: \"property\",
|
|||
(let ((old-template (assoc (car cell) templates)))
|
||||
(if old-template (setcdr old-template (cdr cell))
|
||||
(push cell templates))))))
|
||||
;; Install hard-coded macros.
|
||||
;; Install "property", "time" macros.
|
||||
(mapc update-templates
|
||||
(list (cons "property"
|
||||
"(eval (save-excursion
|
||||
|
@ -143,6 +146,7 @@ function installs the following ones: \"property\",
|
|||
l)))))
|
||||
(org-entry-get nil \"$1\" 'selective)))")
|
||||
(cons "time" "(eval (format-time-string \"$1\"))")))
|
||||
;; Install "input-file", "modification-time" macros.
|
||||
(let ((visited-file (buffer-file-name (buffer-base-buffer))))
|
||||
(when (and visited-file (file-exists-p visited-file))
|
||||
(mapc update-templates
|
||||
|
@ -152,6 +156,10 @@ function installs the following ones: \"property\",
|
|||
(prin1-to-string visited-file)
|
||||
(prin1-to-string
|
||||
(nth 5 (file-attributes visited-file)))))))))
|
||||
;; Initialize and install "n" macro.
|
||||
(org-macro--counter-initialize)
|
||||
(funcall update-templates
|
||||
(cons "n" "(eval (org-macro--counter-increment \"$1\" \"$2\"))"))
|
||||
(setq org-macro-templates templates)))
|
||||
|
||||
(defun org-macro-expand (macro templates)
|
||||
|
@ -280,6 +288,9 @@ Return a list of arguments, as strings. This is the opposite of
|
|||
s nil t)
|
||||
"\000"))
|
||||
|
||||
|
||||
;;; Helper functions and variables for internal macros
|
||||
|
||||
(defun org-macro--vc-modified-time (file)
|
||||
(save-window-excursion
|
||||
(when (vc-backend file)
|
||||
|
@ -304,6 +315,27 @@ Return a list of arguments, as strings. This is the opposite of
|
|||
(kill-buffer buf))
|
||||
date))))
|
||||
|
||||
(defvar org-macro--counter-table nil
|
||||
"Hash table containing counter value per name.")
|
||||
|
||||
(defun org-macro--counter-initialize ()
|
||||
"Initialize `org-macro--counter-table'."
|
||||
(setq org-macro--counter-table (make-hash-table :test #'equal)))
|
||||
|
||||
(defun org-macro--counter-increment (name &optional reset)
|
||||
"Increment counter NAME.
|
||||
NAME is a string identifying the counter. If optional argument
|
||||
RESET is a non-empty string, reset the counter instead."
|
||||
(if (org-string-nw-p reset)
|
||||
(let ((new-value (if (string-match-p "\\`[ \t]*[0-9]+[ \t]*\\'" reset)
|
||||
(string-to-number reset)
|
||||
1)))
|
||||
(puthash name new-value org-macro--counter-table))
|
||||
(let ((value (gethash name org-macro--counter-table)))
|
||||
(puthash name
|
||||
(if (null value) 1 (1+ value))
|
||||
org-macro--counter-table))))
|
||||
|
||||
|
||||
(provide 'org-macro)
|
||||
;;; org-macro.el ends here
|
||||
|
|
|
@ -75,9 +75,22 @@
|
|||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-string))))
|
||||
;; Test special "property" macro. With only one argument, retrieve
|
||||
;; property from current headline. Otherwise, the second argument
|
||||
;; is a search option to get the property from another headline.
|
||||
;; Macro expansion ignores narrowing.
|
||||
(should
|
||||
(string-match
|
||||
"expansion"
|
||||
(org-test-with-temp-text
|
||||
"#+MACRO: macro expansion\n{{{macro}}}\n<point>Contents"
|
||||
(narrow-to-region (point) (point-max))
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(org-with-wide-buffer (buffer-string))))))
|
||||
|
||||
(ert-deftest test-org-macro/property ()
|
||||
"Test {{{property}}} macro."
|
||||
;; With only one argument, retrieve property from current headline.
|
||||
;; Otherwise, the second argument is a search option to get the
|
||||
;; property from another headline.
|
||||
(should
|
||||
(equal "1"
|
||||
(org-test-with-temp-text
|
||||
|
@ -107,17 +120,80 @@
|
|||
(org-test-with-temp-text
|
||||
"* H1\n:PROPERTIES:\n:A: 1\n:END:\n* H2\n{{{property(A,*???)}}}<point>"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)))
|
||||
;; Macro expansion ignores narrowing.
|
||||
(org-macro-replace-all org-macro-templates))))
|
||||
|
||||
(ert-deftest test-org-macro/n ()
|
||||
"Test {{{n}}} macro."
|
||||
;; Standard test with default counter.
|
||||
(should
|
||||
(string-match
|
||||
"expansion"
|
||||
(org-test-with-temp-text
|
||||
"#+MACRO: macro expansion\n{{{macro}}}\n<point>Contents"
|
||||
(narrow-to-region (point) (point-max))
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(org-with-wide-buffer (buffer-string))))))
|
||||
(equal "1 2"
|
||||
(org-test-with-temp-text "{{{n}}} {{{n}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
(should
|
||||
(equal "1 2"
|
||||
(org-test-with-temp-text "{{{n()}}} {{{n}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
;; Test alternative counters.
|
||||
(should
|
||||
(equal "1 1 1 2"
|
||||
(org-test-with-temp-text "{{{n}}} {{{n(c1)}}} {{{n(c2)}}} {{{n(c1)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
;; Second argument set a counter to a given value. A non-numeric
|
||||
;; value resets the counter to 1.
|
||||
(should
|
||||
(equal "9 10"
|
||||
(org-test-with-temp-text "{{{n(c,9)}}} {{{n(c)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
(should
|
||||
(equal "9 1"
|
||||
(org-test-with-temp-text "{{{n(c,9)}}} {{{n(c,reset)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
;; Tolerate spaces in second argument.
|
||||
(should
|
||||
(equal "9 10"
|
||||
(org-test-with-temp-text "{{{n(c, 9)}}} {{{n(c)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
(should
|
||||
(equal "9 1"
|
||||
(org-test-with-temp-text "{{{n(c,9)}}} {{{n(c, reset)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
;; Second argument also applies to default counter.
|
||||
(should
|
||||
(equal "9 10 1"
|
||||
(org-test-with-temp-text "{{{n(,9)}}} {{{n}}} {{{n(,reset)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position)))))
|
||||
;; An empty second argument is equivalent to no argument.
|
||||
(should
|
||||
(equal "2 3"
|
||||
(org-test-with-temp-text "{{{n(c,2)}}} {{{n(c,)}}}"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(buffer-substring-no-properties
|
||||
(line-beginning-position) (line-end-position))))))
|
||||
|
||||
(ert-deftest test-org-macro/escape-arguments ()
|
||||
"Test `org-macro-escape-arguments' specifications."
|
||||
|
|
Loading…
Reference in New Issue