org-macro: Properly handle macros in setup files

* lisp/org-macro.el (org-macro--collect-macros): Fix a bug where
  reading a macro in a setup file would remove other macros read so
  far from template.  Change function signature.
(org-macro-initialize-templates): Apply signature change from function
above.
* testing/lisp/test-org-macro.el: Add test.
This commit is contained in:
Nicolas Goaziou 2013-04-01 15:44:15 +02:00
parent 55db57dc0a
commit a82b06ae4b
2 changed files with 43 additions and 35 deletions

View File

@ -61,37 +61,44 @@ directly, use instead:
;;; Functions
(defun org-macro--collect-macros (files)
(defun org-macro--collect-macros ()
"Collect macro definitions in current buffer and setup files.
FILES is a list of setup files names read so far, used to avoid
circular dependencies. Return an alist containing all macro
templates found."
(let ((case-fold-search t) templates)
;; Install buffer-local macros. Also enter SETUPFILE keywords.
(org-with-wide-buffer
(goto-char (point-min))
(while (re-search-forward "^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t)
(let ((element (org-element-at-point)))
(when (eq (org-element-type element) 'keyword)
(let ((val (org-element-property :value element)))
(if (equal (org-element-property :key element) "SETUPFILE")
;; Enter setup file.
(let ((file (expand-file-name (org-remove-double-quotes val))))
(unless (member file files)
(with-temp-buffer
(org-mode)
(insert (org-file-contents file 'noerror))
(setq templates
(org-macro--collect-macros (cons file files))))))
;; Install macro in TEMPLATES.
(when (string-match "^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" val)
(let* ((name (match-string 1 val))
(template (or (match-string 2 val) ""))
(old-cell (assoc name templates)))
(if old-cell (setcdr old-cell template)
(push (cons name template) templates))))))))))
;; Return value.
templates))
Return an alist containing all macro templates found."
(let* (collect-macros ; For byte-compiler.
(collect-macros
(lambda (files templates)
;; Return an alist of macro templates. FILES is a list of
;; setup files names read so far, used to avoid circular
;; dependencies. TEMPLATES is the alist collected so far.
(let ((case-fold-search t))
(org-with-wide-buffer
(goto-char (point-min))
(while (re-search-forward
"^[ \t]*#\\+\\(MACRO\\|SETUPFILE\\):" nil t)
(let ((element (org-element-at-point)))
(when (eq (org-element-type element) 'keyword)
(let ((val (org-element-property :value element)))
(if (equal (org-element-property :key element) "MACRO")
;; Install macro in TEMPLATES.
(when (string-match
"^\\(.*?\\)\\(?:\\s-+\\(.*\\)\\)?\\s-*$" val)
(let* ((name (match-string 1 val))
(template (or (match-string 2 val) ""))
(old-cell (assoc name templates)))
(if old-cell (setcdr old-cell template)
(push (cons name template) templates))))
;; Enter setup file.
(let ((file (expand-file-name
(org-remove-double-quotes val))))
(unless (member file files)
(with-temp-buffer
(org-mode)
(insert (org-file-contents file 'noerror))
(setq templates
(funcall collect-macros (cons file files)
templates)))))))))))
templates))))
(funcall collect-macros nil nil)))
(defun org-macro-initialize-templates ()
"Collect macro templates defined in current buffer.
@ -100,7 +107,7 @@ Templates are stored in buffer-local variable
function installs the following ones: \"property\",
\"time\". and, if the buffer is associated to a file,
\"input-file\" and \"modification-time\"."
(let* ((templates (org-macro--collect-macros nil))
(let* ((templates (org-macro--collect-macros))
(update-templates
(lambda (cell)
(let ((old-template (assoc (car cell) templates)))

View File

@ -66,11 +66,12 @@
;; Macros in setup file.
(should
(string-match
"success\\'"
"success success\\'"
(org-test-with-temp-text
(format
"#+SETUPFILE: \"%sexamples/macro-templates.org\"\n{{{included-macro}}}"
org-test-dir)
(format "#+MACRO: other-macro success
#+SETUPFILE: \"%sexamples/macro-templates.org\"
{{{included-macro}}} {{{other-macro}}}"
org-test-dir)
(org-macro-initialize-templates)
(org-macro-replace-all org-macro-templates)
(buffer-string)))))