From ea77b2ccb269a0fa4fc61cdc49ce2cd30112be7b Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 1 Sep 2012 00:03:04 +0200 Subject: [PATCH] org-export: Use new API for macro expansion * contrib/lisp/org-export.el (org-export-define-backend): Update docstring. (org-export-special-keywords): Remove "MACRO". (org-export--get-inbuffer-options, org-export--get-buffer-attributes): Remove internal macro handling. (org-export-as): Use external tool instead. (org-export-expand-macro): Remove function. * contrib/lisp/org-e-ascii.el (org-e-ascii-macro): Remove function. * contrib/lisp/org-e-groff.el (org-e-groff-macro): Remove function. * contrib/lisp/org-e-html.el (org-e-html-macro): Remove function. * contrib/lisp/org-e-latex.el (org-e-latex-macro): Remove function. * contrib/lisp/org-e-man.el (org-e-man-macro): Remove function. * contrib/lisp/org-e-odt.el (org-e-odt-macro): Remove function. * contrib/lisp/org-e-texinfo.el (org-e-texinfo-macro): Remove function. * testing/lisp/test-org-export.el: Remove tests. Since macros are now expanded before parsing (and produce Org syntax), back-ends will never see them (unless NO-EXPAND argument from `org-export-as' is non-nil, which isn't the case for any back-end so far). --- contrib/lisp/org-e-ascii.el | 10 ---- contrib/lisp/org-e-groff.el | 8 --- contrib/lisp/org-e-html.el | 15 ----- contrib/lisp/org-e-latex.el | 10 ---- contrib/lisp/org-e-man.el | 10 ---- contrib/lisp/org-e-odt.el | 15 ----- contrib/lisp/org-e-texinfo.el | 12 +--- contrib/lisp/org-export.el | 98 ++++----------------------------- testing/lisp/test-org-export.el | 72 ------------------------ 9 files changed, 11 insertions(+), 239 deletions(-) diff --git a/contrib/lisp/org-e-ascii.el b/contrib/lisp/org-e-ascii.el index ad93ad955..588a57c0c 100644 --- a/contrib/lisp/org-e-ascii.el +++ b/contrib/lisp/org-e-ascii.el @@ -76,7 +76,6 @@ (latex-fragment . org-e-ascii-latex-fragment) (line-break . org-e-ascii-line-break) (link . org-e-ascii-link) - (macro . org-e-ascii-macro) (paragraph . org-e-ascii-paragraph) (plain-list . org-e-ascii-plain-list) (plain-text . org-e-ascii-plain-text) @@ -1328,15 +1327,6 @@ INFO is a plist holding contextual information." (unless org-e-ascii-links-to-notes (format " (%s)" raw-link)))))))) -;;;; Macro - -(defun org-e-ascii-macro (macro contents info) - "Transcode a MACRO element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (org-export-expand-macro macro info)) - - ;;;; Paragraph (defun org-e-ascii-paragraph (paragraph contents info) diff --git a/contrib/lisp/org-e-groff.el b/contrib/lisp/org-e-groff.el index c1860e8f6..5c1d94e49 100644 --- a/contrib/lisp/org-e-groff.el +++ b/contrib/lisp/org-e-groff.el @@ -76,7 +76,6 @@ (groff-fragment . org-e-groff-groff-fragment) (line-break . org-e-groff-line-break) (link . org-e-groff-link) - (macro . org-e-groff-macro) (paragraph . org-e-groff-paragraph) (plain-list . org-e-groff-plain-list) (plain-text . org-e-groff-plain-text) @@ -1399,13 +1398,6 @@ INFO is a plist holding contextual information. See ;; No path, only description. Try to do something useful. (t (format org-e-groff-link-with-unknown-path-format desc))))) -;;; Macro - -(defun org-e-groff-macro (macro contents info) - "Transcode a MACRO element from Org to Groff. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) ;;; Paragraph diff --git a/contrib/lisp/org-e-html.el b/contrib/lisp/org-e-html.el index 2d3d3c4f1..960694529 100644 --- a/contrib/lisp/org-e-html.el +++ b/contrib/lisp/org-e-html.el @@ -76,7 +76,6 @@ (latex-fragment . org-e-html-latex-fragment) (line-break . org-e-html-line-break) (link . org-e-html-link) - (macro . org-e-html-macro) (paragraph . org-e-html-paragraph) (plain-list . org-e-html-plain-list) (plain-text . org-e-html-plain-text) @@ -2408,20 +2407,6 @@ INFO is a plist holding contextual information. See (t (format "%s" desc))))) -;;;; Babel Call - -;; Babel Calls are ignored. - - -;;;; Macro - -(defun org-e-html-macro (macro contents info) - "Transcode a MACRO element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - ;;;; Paragraph (defun org-e-html-paragraph (paragraph contents info) diff --git a/contrib/lisp/org-e-latex.el b/contrib/lisp/org-e-latex.el index 88ffe54e2..395830d7b 100644 --- a/contrib/lisp/org-e-latex.el +++ b/contrib/lisp/org-e-latex.el @@ -71,7 +71,6 @@ (latex-fragment . org-e-latex-latex-fragment) (line-break . org-e-latex-line-break) (link . org-e-latex-link) - (macro . org-e-latex-macro) (paragraph . org-e-latex-paragraph) (plain-list . org-e-latex-plain-list) (plain-text . org-e-latex-plain-text) @@ -1820,15 +1819,6 @@ INFO is a plist holding contextual information. See (t (format org-e-latex-link-with-unknown-path-format desc))))) -;;;; Macro - -(defun org-e-latex-macro (macro contents info) - "Transcode a MACRO element from Org to LaTeX. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - ;;;; Paragraph (defun org-e-latex-paragraph (paragraph contents info) diff --git a/contrib/lisp/org-e-man.el b/contrib/lisp/org-e-man.el index 264fdef02..9c641ae50 100644 --- a/contrib/lisp/org-e-man.el +++ b/contrib/lisp/org-e-man.el @@ -80,7 +80,6 @@ (man-fragment . org-e-man-man-fragment) (line-break . org-e-man-line-break) (link . org-e-man-link) - (macro . org-e-man-macro) (paragraph . org-e-man-paragraph) (plain-list . org-e-man-plain-list) (plain-text . org-e-man-plain-text) @@ -745,15 +744,6 @@ INFO is a plist holding contextual information. See (t (format "\\fI%s\\fP" desc))))) -;;;; Macro - -(defun org-e-man-macro (macro contents info) - "Transcode a MACRO element from Org to Man. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - ;;;; Paragraph (defun org-e-man-paragraph (paragraph contents info) diff --git a/contrib/lisp/org-e-odt.el b/contrib/lisp/org-e-odt.el index 8bb009125..a9e2e56d5 100644 --- a/contrib/lisp/org-e-odt.el +++ b/contrib/lisp/org-e-odt.el @@ -58,7 +58,6 @@ (latex-fragment . org-e-odt-latex-fragment) (line-break . org-e-odt-line-break) (link . org-e-odt-link) - (macro . org-e-odt-macro) (paragraph . org-e-odt-paragraph) (plain-list . org-e-odt-plain-list) (plain-text . org-e-odt-plain-text) @@ -2606,20 +2605,6 @@ INFO is a plist holding contextual information. See "Emphasis" desc))))) -;;;; Babel Call - -;; Babel Calls are ignored. - - -;;;; Macro - -(defun org-e-odt-macro (macro contents info) - "Transcode a MACRO element from Org to ODT. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - ;;;; Paragraph (defun org-e-odt-paragraph (paragraph contents info) diff --git a/contrib/lisp/org-e-texinfo.el b/contrib/lisp/org-e-texinfo.el index 739fd01e9..15a8877b1 100644 --- a/contrib/lisp/org-e-texinfo.el +++ b/contrib/lisp/org-e-texinfo.el @@ -65,8 +65,7 @@ ;;; Define Back-End (defvar org-e-texinfo-translate-alist - '((babel-call . org-e-texinfo-babel-call) - (bold . org-e-texinfo-bold) + '((bold . org-e-texinfo-bold) (center-block . org-e-texinfo-center-block) (clock . org-e-texinfo-clock) (code . org-e-texinfo-code) @@ -83,7 +82,6 @@ (footnote-reference . org-e-texinfo-footnote-reference) (headline . org-e-texinfo-headline) (horizontal-rule . org-e-texinfo-horizontal-rule) - (inline-babel-call . org-e-texinfo-inline-babel-call) (inline-src-block . org-e-texinfo-inline-src-block) (inlinetask . org-e-texinfo-inlinetask) (italic . org-e-texinfo-italic) @@ -93,7 +91,6 @@ (latex-fragment . org-e-texinfo-latex-fragment) (line-break . org-e-texinfo-line-break) (link . org-e-texinfo-link) - (macro . org-e-texinfo-macro) (paragraph . org-e-texinfo-paragraph) (plain-list . org-e-texinfo-plain-list) (plain-text . org-e-texinfo-plain-text) @@ -1277,13 +1274,6 @@ INFO is a plist holding contextual information. See ;; No path, only description. Try to do something useful. (t (format org-e-texinfo-link-with-unknown-path-format desc))))) -;;; Macro - -(defun org-e-texinfo-macro (macro contents info) - "Transcode a MACRO element from Org to Texinfo. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) ;;; Menu diff --git a/contrib/lisp/org-export.el b/contrib/lisp/org-export.el index 23389fed9..e3a371660 100644 --- a/contrib/lisp/org-export.el +++ b/contrib/lisp/org-export.el @@ -178,8 +178,7 @@ All these properties should be back-end agnostic. Back-end specific properties are set through `org-export-define-backend'. Properties redefined there have precedence over these.") -(defconst org-export-special-keywords - '("SETUP_FILE" "OPTIONS" "MACRO") +(defconst org-export-special-keywords '("SETUP_FILE" "OPTIONS") "List of in-buffer keywords that require special treatment. These keywords are not directly associated to a property. The way they are handled must be hard-coded into @@ -791,7 +790,6 @@ As an example, here is how the `e-ascii' back-end is defined: \(latex-fragment . org-e-ascii-latex-fragment) \(line-break . org-e-ascii-line-break) \(link . org-e-ascii-link) - \(macro . org-e-ascii-macro) \(paragraph . org-e-ascii-paragraph) \(plain-list . org-e-ascii-plain-list) \(plain-text . org-e-ascii-plain-text) @@ -1395,41 +1393,7 @@ Assume buffer is in Org mode. Narrowing, if any, is ignored." (org-export--get-inbuffer-options backend (cons file files)))))) ((string= key "OPTIONS") - (org-export--parse-option-keyword val backend)) - ((string= key "MACRO") - (when (string-match - "^\\([-a-zA-Z0-9_]+\\)\\(?:[ \t]+\\(.*?\\)[ \t]*$\\)?" - val) - (let ((key - (intern - (concat ":macro-" - (downcase (match-string 1 val))))) - (value (org-match-string-no-properties 2 val))) - (cond - ((not value) nil) - ;; Value will be evaled: do not parse it. - ((string-match "\\`(eval\\>" value) - (list key (list value))) - ;; Value has to be parsed for nested - ;; macros. - (t - (list - key - (let ((restr (org-element-restriction 'macro))) - (org-element-parse-secondary-string - ;; If user explicitly asks for - ;; a newline, be sure to preserve it - ;; from further filling with - ;; `hard-newline'. Also replace - ;; "\\n" with "\n", "\\\n" with "\\n" - ;; and so on... - (replace-regexp-in-string - "\\(\\\\\\\\\\)n" "\\\\" - (replace-regexp-in-string - "\\(?:^\\|[^\\\\]\\)\\(\\\\n\\)" - hard-newline value nil nil 1) - nil nil 1) - restr))))))))))) + (org-export--parse-option-keyword val backend))))) (setq plist (org-combine-plists plist prop))))))) ;; 2. Standard options, as in `org-export-options-alist'. (let* ((all (append org-export-options-alist @@ -1530,22 +1494,7 @@ Assume buffer is in Org mode. Narrowing, if any, is ignored." (let* ((id (org-match-string-no-properties 1)) (file (org-id-find-id-file id))) (when file (push (cons id (file-relative-name file)) alist))))) - alist) - :macro-modification-time - (and visited-file - (file-exists-p visited-file) - (concat "(eval (format-time-string \"$1\" '" - (prin1-to-string (nth 5 (file-attributes visited-file))) - "))")) - ;; Store input file name as a macro. - :macro-input-file (and visited-file (file-name-nondirectory visited-file)) - ;; `:macro-date', `:macro-time' and `:macro-property' could as - ;; well be initialized as tree properties, since they don't - ;; depend on buffer properties. Though, it may be more logical - ;; to keep them close to other ":macro-" properties. - :macro-date "(eval (format-time-string \"$1\"))" - :macro-time "(eval (format-time-string \"$1\"))" - :macro-property "(eval (org-entry-get nil \"$1\" 'selective))"))) + alist)))) (defun org-export--get-global-options (&optional backend) "Return global export options as a plist. @@ -2497,8 +2446,8 @@ Return the updated communication channel." ;; ;; Note that `org-export-as' doesn't really parse the current buffer, ;; but a copy of it (with the same buffer-local variables and -;; visibility), where include keywords are expanded and Babel blocks -;; are executed, if appropriate. +;; visibility), where macros and include keywords are expanded and +;; Babel blocks are executed, if appropriate. ;; `org-export-with-current-buffer-copy' macro prepares that copy. ;; ;; File inclusion is taken care of by @@ -2554,12 +2503,14 @@ Return code as a string." (let ((info (org-export-install-filters (org-export-get-environment backend subtreep ext-plist))) ;; 2. Get parse tree. Buffer isn't parsed directly. - ;; Instead, a temporary copy is created, where include - ;; keywords are expanded and code blocks are evaluated. + ;; Instead, a temporary copy is created, where macros + ;; and include keywords are expanded and code blocks + ;; are evaluated. (tree (let ((buf (or (buffer-file-name (buffer-base-buffer)) (current-buffer)))) (org-export-with-current-buffer-copy (unless noexpand + (org-macro-replace-all) (org-export-expand-include-keyword) ;; TODO: Setting `org-current-export-file' is ;; required by Org Babel to properly resolve @@ -2891,7 +2842,7 @@ file should have." ;; should be added here. ;; ;; As of now, functions operating on footnotes, headlines, links, -;; macros, references, src-blocks, tables and tables of contents are +;; references, src-blocks, tables and tables of contents are ;; implemented. ;;;; For Affiliated Keywords @@ -3360,35 +3311,6 @@ has type \"radio\"." info 'first-match))) -;;;; For Macros -;; -;; `org-export-expand-macro' simply takes care of expanding macros. - -(defun org-export-expand-macro (macro info) - "Expand MACRO and return it as a string. -INFO is a plist holding export options." - (let* ((key (org-element-property :key macro)) - (args (org-element-property :args macro)) - ;; User's macros are stored in the communication channel with - ;; a ":macro-" prefix. Replace arguments in VALUE. Also - ;; expand recursively macros within. - (value (org-export-data - (mapcar - (lambda (obj) - (if (not (stringp obj)) (org-export-data obj info) - (replace-regexp-in-string - "\\$[0-9]+" - (lambda (arg) - (nth (1- (string-to-number (substring arg 1))) args)) - obj))) - (plist-get info (intern (format ":macro-%s" key)))) - info))) - ;; VALUE starts with "(eval": it is a s-exp, `eval' it. - (when (string-match "\\`(eval\\>" value) (setq value (eval (read value)))) - ;; Return string. - (format "%s" (or value "")))) - - ;;;; For References ;; ;; `org-export-get-ordinal' associates a sequence number to any object diff --git a/testing/lisp/test-org-export.el b/testing/lisp/test-org-export.el index 5bc2086a0..6163f60ba 100644 --- a/testing/lisp/test-org-export.el +++ b/testing/lisp/test-org-export.el @@ -974,78 +974,6 @@ Another text. (ref:text) info))))) - -;;; Macro - -(ert-deftest test-org-export/define-macro () - "Try defining various Org macro using in-buffer #+MACRO: keyword." - ;; Parsed macro. - (should (equal (org-test-with-temp-text "#+MACRO: one 1" - (org-export--get-inbuffer-options)) - '(:macro-one ("1")))) - ;; Evaled macro. - (should (equal (org-test-with-temp-text "#+MACRO: two (eval (+ 1 1))" - (org-export--get-inbuffer-options)) - '(:macro-two ("(eval (+ 1 1))")))) - ;; Incomplete macro. - (should-not (org-test-with-temp-text "#+MACRO: three" - (org-export--get-inbuffer-options))) - ;; Macro with newline character. - (should (equal (org-test-with-temp-text "#+MACRO: four a\\nb" - (org-export--get-inbuffer-options)) - '(:macro-four ("a\nb")))) - ;; Macro with protected newline character. - (should (equal (org-test-with-temp-text "#+MACRO: five a\\\\nb" - (org-export--get-inbuffer-options)) - '(:macro-five ("a\\nb")))) - ;; Recursive macro. - (org-test-with-temp-text "#+MACRO: six 6\n#+MACRO: seven 1 + {{{six}}}" - (should - (equal - (org-export--get-inbuffer-options) - '(:macro-six - ("6") - :macro-seven - ("1 + " (macro (:key "six" :value "{{{six}}}" :args nil :begin 5 :end 14 - :post-blank 0 :parent nil)))))))) - -(ert-deftest test-org-export/expand-macro () - "Test `org-export-expand-macro' specifications." - ;; Standard test. - (should - (equal - "some text" - (org-test-with-parsed-data "#+MACRO: macro some text\n{{{macro}}}" - (org-export-expand-macro - (org-element-map tree 'macro 'identity info t) info)))) - ;; Macro with arguments. - (should - (equal - "some text" - (org-test-with-parsed-data "#+MACRO: macro $1 $2\n{{{macro(some,text)}}}" - (org-export-expand-macro - (org-element-map tree 'macro 'identity info t) info)))) - ;; Macro with "eval" - (should - (equal - "3" - (org-test-with-parsed-data "#+MACRO: add (eval (+ $1 $2))\n{{{add(1,2)}}}" - (org-export-expand-macro - (org-element-map tree 'macro 'identity info t) info)))) - ;; Nested macros. - (should - (equal - "inner outer" - (org-test-with-parsed-data - "#+MACRO: in inner\n#+MACRO: out {{{in}}} outer\n{{{out}}}" - (flet ((translate-macro (macro contents info) - (org-export-expand-macro macro info))) - (org-export-expand-macro - (org-element-map tree 'macro 'identity info t) - (org-combine-plists - info `(:translate-alist ((macro . translate-macro)))))))))) - - ;;; Src-block and example-block