From fa5f8c8f90440ce7e440148e2b7ee20a10d9f547 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sun, 10 May 2015 11:48:13 +0200 Subject: [PATCH] Allow optional argument to {{{property}}} for remote entries * lisp/org-macro.el (org-macro-initialize-templates): "property" template accepts an optional argument, as a search option to grab properties from other headlines. * doc/org.texi (Macro replacement): Document new feature. Improve documentation. (An example): Update documentation. * testing/lisp/test-org-macro.el (test-org/macro-replace-all): Add tests. --- doc/org.texi | 60 +++++++++++++++++++++++++++++------------- lisp/org-macro.el | 12 ++++++++- testing/lisp/test-org-macro.el | 35 +++++++++++++++++++++++- 3 files changed, 86 insertions(+), 21 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index d926de48a..b5159639e 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -10174,7 +10174,6 @@ an index} for more information. - @node Macro replacement @section Macro replacement @cindex macro replacement, during export @@ -10194,23 +10193,46 @@ escaped with another backslash character.}. These references, called macros, can be inserted anywhere Org markup is recognized: paragraphs, headlines, verse blocks, tables cells and lists. -They cannot be used within ordinary keywords (starting with @code{#+}) but -are allowed in @code{#+CAPTION}, @code{#+TITLE}, @code{#+AUTHOR} and -@code{#+EMAIL}. +They can also be used in keywords accepting Org syntax, e.g., +@code{#+CAPTION}, @code{#+TITLE}, @code{#+AUTHOR}, @code{#+DATE} and some +others, export back-end specific, ones. In addition to user-defined macros, a set of predefined macros can be used: -@code{@{@{@{title@}@}@}}, @code{@{@{@{author@}@}@}}, and -@code{@{@{@{email@}@}@}} are replaced with the information set by their -respective keywords. Further, @code{@{@{@{date(@var{FORMAT})@}@}@}}, -@code{@{@{@{time(@var{FORMAT})@}@}@}} and -@code{@{@{@{modification-time(@var{FORMAT})@}@}@}} refer to the @code{#+DATE} -keyword, the current date, and the modification time of the file being -exported, respectively. @var{FORMAT} should be a format string understood by -@code{format-time-string}. Note that @var{FORMAT} is an optional argument to -the @code{@{@{@{date@}@}@}} macro, and that it will only be used if -@code{#+DATE} is a single timestamp. Finally, the filename is available via -@code{@{@{@{input-file@}@}@}} and properties can be accessed using -@code{@{@{@{property(@var{PROPERTY-NAME})@}@}@}}. + +@table @code +@item @{@{@{title@}@}@} +@itemx @{@{@{author@}@}@} +@itemx @{@{@{email@}@}@} +@cindex title, macro +@cindex author, macro +@cindex email, macro +These macros are replaced with the information available at the time of +export. + +@item @{@{@{date@}@}@} +@itemx @{@{@{date(@var{FORMAT})@}@}@} +@itemx @{@{@{time(@var{FORMAT})@}@}@} +@itemx @{@{@{modification-time(@var{FORMAT})@}@}@} +@cindex date, macro +@cindex time, macro +@cindex modification time, macro +These macros refer to the @code{#+DATE} keyword, the current date, and the +modification time of the file being exported, respectively. @samp{FORMAT} +should be a format string understood by @code{format-time-string}. Note that +@var{FORMAT} is an optional argument to the @code{@{@{@{date@}@}@}} macro, +and that it will only be used if @code{#+DATE} is a single timestamp. + +@item @{@{@{input-file@}@}@} +@cindex input file, macro +This macro refers to the filename of the exported file, if any. + +@item @{@{@{property(@var{PROPERTY-NAME})@}@}@} +@itemx @{@{@{property(@var{PROPERTY-NAME},@var{SEARCH-OPTION})@}@}@} +@cindex property, macro +This macro returns the value of property @var{PROPERTY-NAME} in current +entry. If @var{SEARCH-OPTION} (@pxref(Search options}) refers to a remote +entry, it will be used instead. +@end table The surrounding brackets can be made invisible by setting @code{org-hide-macro-markers} non-@code{nil}. @@ -13637,7 +13659,7 @@ length, using @code{:columns} attribute. Here is a thorough example. @inforef{GNU Sample Texts,,texinfo} for an equivalent Texinfo code. -@smallexample +@example #+MACRO: version 2.0 #+MACRO: updated last updated 4 March 2014 @@ -13655,7 +13677,7 @@ equivalent Texinfo code. #+TEXINFO_DIR_DESC: Invoking sample #+TEXINFO_PRINTED_TITLE: GNU Sample -#+SUBTITLE: for version 2.0, last updated 4 March 2014 +#+SUBTITLE: for version @{@{@{version@}@}@}, @{@{@{updated@}@}@} * Copying :PROPERTIES: @@ -13697,7 +13719,7 @@ equivalent Texinfo code. :PROPERTIES: :INDEX: cp :END: -@end smallexample +@end example @node iCalendar export @section iCalendar export diff --git a/lisp/org-macro.el b/lisp/org-macro.el index 890f0cff9..a168ffb39 100644 --- a/lisp/org-macro.el +++ b/lisp/org-macro.el @@ -123,7 +123,17 @@ function installs the following ones: \"property\", (push cell templates)))))) ;; Install hard-coded macros. (mapc update-templates - (list (cons "property" "(eval (org-entry-get nil \"$1\" 'selective))") + (list (cons "property" + "(eval (save-excursion + (let ((l \"$2\")) + (when (org-string-nw-p l) + (condition-case _ + (let ((org-link-search-must-match-exact-headline t)) + (org-link-search l nil nil t)) + (error + (error \"Macro property failed: cannot find location %s\" + l))))) + (org-entry-get nil \"$1\" 'selective)))") (cons "time" "(eval (format-time-string \"$1\"))"))) (let ((visited-file (buffer-file-name (buffer-base-buffer)))) (when (and visited-file (file-exists-p visited-file)) diff --git a/testing/lisp/test-org-macro.el b/testing/lisp/test-org-macro.el index d28cb7f22..4934d93c1 100644 --- a/testing/lisp/test-org-macro.el +++ b/testing/lisp/test-org-macro.el @@ -74,7 +74,40 @@ org-test-dir) (org-macro-initialize-templates) (org-macro-replace-all org-macro-templates) - (buffer-string))))) + (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. + (should + (equal "1" + (org-test-with-temp-text + "* H\n:PROPERTIES:\n:A: 1\n:END:\n{{{property(A)}}}" + (org-macro-initialize-templates) + (org-macro-replace-all org-macro-templates) + (buffer-substring-no-properties + (line-beginning-position) (line-end-position))))) + (should + (equal "1" + (org-test-with-temp-text + "* H\n:PROPERTIES:\n:A: 1\n:END:\n{{{property(A,)}}}" + (org-macro-initialize-templates) + (org-macro-replace-all org-macro-templates) + (buffer-substring-no-properties + (line-beginning-position) (line-end-position))))) + (should + (equal + "1" + (org-test-with-temp-text + "* H1\n:PROPERTIES:\n:A: 1\n:END:\n* H2\n{{{property(A,*H1)}}}" + (org-macro-initialize-templates) + (org-macro-replace-all org-macro-templates) + (buffer-substring-no-properties + (line-beginning-position) (line-end-position))))) + (should-error + (org-test-with-temp-text + "* H1\n:PROPERTIES:\n:A: 1\n:END:\n* H2\n{{{property(A,*???)}}}" + (org-macro-initialize-templates) + (org-macro-replace-all org-macro-templates)))) (ert-deftest test-org-macro/escape-arguments () "Test `org-macro-escape-arguments' specifications." -- 2.11.4.GIT