Jelajahi Sumber

Remove second pass for macro expansion

* lisp/org-macro.el (org-macro-initialize-templates): Initialize all
  macros, including {{{title}}} and al.
(org-macro-replace-all): Change signature.
(org-macro--find-keyword-value): New function.
* lisp/ox.el (org-export-as): Remove second macro expansion
Nicolas Goaziou 7 tahun lalu
induk
melakukan
5f5d82ed51
2 mengubah file dengan 49 tambahan dan 33 penghapusan
  1. 46 7
      lisp/org-macro.el
  2. 3 26
      lisp/ox.el

+ 46 - 7
lisp/org-macro.el

@@ -136,6 +136,25 @@ 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 "author, "date, "email", "title" and "results" macros.
+    (mapc update-templates
+	  (list
+	   (cons "author" (org-macro--find-keyword-value "AUTHOR"))
+	   (cons "date"
+		 (let* ((value (org-macro--find-keyword-value "DATE"))
+			(date (org-element-parse-secondary-string
+			       value (org-element-restriction 'keyword))))
+		   (if (and (consp date)
+			    (not (cdr date))
+			    (eq (org-element-type (car date)) 'timestamp))
+		       (format "(eval (if (org-string-nw-p \"$1\") %s %S))"
+			       (format "(org-timestamp-format '%S \"$1\")"
+				       (org-element-copy (car date)))
+			       value)
+		     value)))
+	   (cons "email" (org-macro--find-keyword-value "EMAIL"))
+	   (cons "results" "$1")
+	   (cons "title" (org-macro--find-keyword-value "TITLE"))))
     ;; Install "property", "time" macros.
     (mapc update-templates
 	  (list (cons "property"
@@ -156,7 +175,11 @@ function installs the following ones: \"property\",
 	(mapc update-templates
 	      (list (cons "input-file" (file-name-nondirectory visited-file))
 		    (cons "modification-time"
-			  (format "(eval (format-time-string \"$1\" (or (and (org-string-nw-p \"$2\") (org-macro--vc-modified-time %s)) '%s)))"
+			  (format "(eval
+\(format-time-string \"$1\"
+                     (or (and (org-string-nw-p \"$2\")
+                              (org-macro--vc-modified-time %s))
+                     '%s)))"
 				  (prin1-to-string visited-file)
 				  (prin1-to-string
 				   (nth 5 (file-attributes visited-file)))))))))
@@ -190,17 +213,17 @@ default value.  Return nil if no template was found."
         ;; Return string.
         (format "%s" (or value ""))))))
 
-(defun org-macro-replace-all (templates &optional finalize keywords)
+(defun org-macro-replace-all (templates &optional keywords)
   "Replace all macros in current buffer by their expansion.
 
 TEMPLATES is an alist of templates used for expansion.  See
 `org-macro-templates' for a buffer-local default value.
 
-If optional arg FINALIZE is non-nil, raise an error if a macro is
-found in the buffer with no definition in TEMPLATES.
-
 Optional argument KEYWORDS, when non-nil is a list of keywords,
-as strings, where macro expansion is allowed."
+as strings, where macro expansion is allowed.
+
+Return an error if a macro in the buffer cannot be associated to
+a definition in TEMPLATES."
   (org-with-wide-buffer
    (goto-char (point-min))
    (let ((properties-regexp (format "\\`EXPORT_%s\\+?\\'"
@@ -246,7 +269,7 @@ as strings, where macro expansion is allowed."
 		      ;; Leave point before replacement in case of
 		      ;; recursive expansions.
 		      (save-excursion (insert value)))
-		     (finalize
+		     (t
 		      (error "Undefined Org macro: %s; aborting"
 			     (org-element-property :key macro))))))))))))
 
@@ -294,6 +317,22 @@ Return a list of arguments, as strings.  This is the opposite of
 
 ;;; Helper functions and variables for internal macros
 
+(defun org-macro--find-keyword-value (name)
+  "Find value for keyword NAME in current buffer.
+KEYWORD is a string.  Return value associated to the keywords
+named after NAME, as a string, or nil."
+  (org-with-point-at 1
+    (let ((regexp (format "^[ \t]*#\\+%s:" (regexp-quote name)))
+	  (case-fold-search t)
+	  (result nil))
+      (while (re-search-forward regexp nil t)
+	(let ((element (org-element-at-point)))
+	  (when (eq 'keyword (org-element-type element))
+	    (setq result (concat result
+				 " "
+				 (org-element-property :value element))))))
+      (and result (org-trim result)))))
+
 (defun org-macro--vc-modified-time (file)
   (save-window-excursion
     (when (vc-backend file)

+ 3 - 26
lisp/ox.el

@@ -3038,9 +3038,9 @@ Return code as a string."
 	 (org-export-expand-include-keyword)
 	 (org-export--delete-comment-trees)
 	 (org-macro-initialize-templates)
-	 (org-macro-replace-all
-	  (append org-macro-templates org-export-global-macros)
-	  nil parsed-keywords)
+	 (org-macro-replace-all (append org-macro-templates
+					org-export-global-macros)
+				parsed-keywords)
 	 ;; Refresh buffer properties and radio targets after
 	 ;; potentially invasive previous changes.  Likewise, do it
 	 ;; again after executing Babel code.
@@ -3082,29 +3082,6 @@ Return code as a string."
 	   (dolist (filter (plist-get info :filter-options))
 	     (let ((result (funcall filter info backend-name)))
 	       (when result (setq info result)))))
-	 ;; Expand export-specific set of macros: {{{author}}},
-	 ;; {{{date(FORMAT)}}}, {{{email}}} and {{{title}}}.  It must
-	 ;; be done once regular macros have been expanded, since
-	 ;; parsed keywords may contain one of them.
-	 (org-macro-replace-all
-	  (list
-	   (cons "author" (org-element-interpret-data (plist-get info :author)))
-	   (cons "date"
-		 (let* ((date (plist-get info :date))
-			(value (or (org-element-interpret-data date) "")))
-		   (if (and (consp date)
-			    (not (cdr date))
-			    (eq (org-element-type (car date)) 'timestamp))
-		       (format "(eval (if (org-string-nw-p \"$1\") %s %S))"
-			       (format "(org-timestamp-format '%S \"$1\")"
-				       (org-element-copy (car date)))
-			       value)
-		     value)))
-	   (cons "email" (org-element-interpret-data (plist-get info :email)))
-	   (cons "title" (org-element-interpret-data (plist-get info :title)))
-	   (cons "results" "$1"))
-	  'finalize
-	  parsed-keywords)
 	 ;; Parse buffer.
 	 (setq tree (org-element-parse-buffer nil visible-only))
 	 ;; Prune tree from non-exported elements and transform