فهرست منبع

org-exp: make lists more robust wrt macros expansion

* lisp/org-exp.el (org-export-preprocess-string): mark list end before
  expanding macros. Thus, a macro inside a list and containing blank
  lines cannot break the list structure.
  (org-export-preprocess-apply-macros): multi-lines macros get
  indented with the same indentation as the first line. Thus, we are
  sure that every line belongs to the same list as the first line, if
  such list exists. Also add comments in code.
Nicolas Goaziou 14 سال پیش
والد
کامیت
ae60048a81
1فایلهای تغییر یافته به همراه34 افزوده شده و 16 حذف شده
  1. 34 16
      lisp/org-exp.el

+ 34 - 16
lisp/org-exp.el

@@ -1103,6 +1103,10 @@ on this string to produce the exported version."
       (org-export-handle-include-files-recurse)
       (run-hooks 'org-export-preprocess-after-include-files-hook)
 
+      ;; Change lists ending. Other parts of export may insert blank
+      ;; lines and lists' structure could be altered.
+      (org-export-mark-list-end)
+
       ;; Process the macros
       (org-export-preprocess-apply-macros)
       (run-hooks 'org-export-preprocess-after-macros-hook)
@@ -1121,10 +1125,6 @@ on this string to produce the exported version."
       ;; Get rid of tasks, depending on configuration
       (org-export-remove-tasks (plist-get parameters :tasks))
 
-      ;; Change lists ending. Other parts of export may insert blank
-      ;; lines and lists' structure could be altered.
-      (org-export-mark-list-end)
-
       ;; Export code blocks
       (org-export-blocks-preprocess)
 
@@ -2219,26 +2219,35 @@ TYPE must be a string, any of:
 (defun org-export-preprocess-apply-macros ()
   "Replace macro references."
   (goto-char (point-min))
-  (let (sy val key args args2 s n)
+  (let (sy val key args args2 ind-str s n)
     (while (re-search-forward
 	    "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\(([ \t\n]*\\([^\000]*?\\))\\)?}}}"
 	    nil t)
-      (unless (save-match-data
-		(save-excursion
-		  (goto-char (point-at-bol))
-		  (looking-at "[ \t]*#\\+macro")))
+      (unless (save-match-data (save-excursion
+				 (goto-char (point-at-bol))
+				 (looking-at "[ \t]*#\\+macro")))
+	;; Get macro name (KEY), arguments (ARGS), and indentation of
+	;; current line (IND-STR) as strings.
 	(setq key (downcase (match-string 1))
-	      args (match-string 3))
+	      args (match-string 3)
+	      ind-str (save-match-data (save-excursion
+					 (beginning-of-line)
+					 (looking-at "^\\([ \t]*\\).*")
+					 (match-string 1))))
+	;; When macro is defined, retrieve replacement text in VAL,
+	;; and proceed with expansion.
 	(when (setq val (or (plist-get org-export-opt-plist
 				       (intern (concat ":macro-" key)))
 			    (plist-get org-export-opt-plist
 				       (intern (concat ":" key)))))
 	  (save-match-data
+	    ;; If arguments are provided, first retreive them properly
+	    ;; (in ARGS, as a list), then replace them in VAL.
 	    (when args
 	      (setq args (org-split-string args ",") args2 nil)
 	      (while args
 		(while (string-match "\\\\\\'" (car args))
-		  ;; repair bad splits
+		  ;; Repair bad splits.
 		  (setcar (cdr args) (concat (substring (car args) 0 -1)
 					     "," (nth 1 args)))
 		  (pop args))
@@ -2250,13 +2259,22 @@ TYPE must be a string, any of:
 		      n (string-to-number (match-string 1 val)))
 		(and (>= (length args) n)
 		     (setq val (replace-match (nth (1- n) args) t t val)))))
+	    ;; VAL starts with "(eval": it is a sexp, `eval' it.
 	    (when (string-match "\\`(eval\\>" val)
 	      (setq val (eval (read val))))
-	    (if (and val (not (stringp val)))
-		(setq val (format "%s" val))))
-	  (and (stringp val)
-	       (prog1 (replace-match val t t)
-		 (goto-char (match-beginning 0)))))))))
+	    ;; Ensure VAL is a string (or nil) and that each new line
+	    ;; is indented as the first one.
+	    (setq val (and val
+			   (mapconcat 'identity
+				      (org-split-string
+				       (if (stringp val) val (format "%s" val))
+				       "\n")
+				      (concat "\n" ind-str)))))
+	  ;; Eventually do the replacement, if VAL isn't nil. Move
+	  ;; point at beginning of macro for recursive expansions.
+	  (when val
+	    (replace-match val t t)
+	    (goto-char (match-beginning 0))))))))
 
 (defun org-export-apply-macros-in-string (s)
   "Apply the macros in string S."