summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2016-01-08 23:36:22 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2016-01-08 23:36:22 +0100
commite2fbaeedc19a92e63ec0a50a6e8fcccdc4b09cdd (patch)
tree95cdefc8b95025db886b29956362f0ceacf60586
parentda10c6ace68014c9400fcead8d0f194c0fec20f0 (diff)
downloadorg-mode-e2fbaeedc19a92e63ec0a50a6e8fcccdc4b09cdd.tar.gz
Fix handling escaped placeholders in templates
* lisp/org-capture.el (org-capture-fill-template): * lisp/org-feed.el (org-feed-format-entry): Fix handling escaped placeholders in templates. In particular, do not rely on match data when `org-capture-escaped-%' is used. Reported-by: Michael Brand <michael.ch.brand@gmail.com> <http://permalink.gmane.org/gmane.emacs.orgmode/104081>
-rw-r--r--lisp/org-capture.el65
-rw-r--r--lisp/org-feed.el59
2 files changed, 69 insertions, 55 deletions
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 2d119e6..cbae91c 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -1613,17 +1613,19 @@ The template may still contain \"%?\" for cursor positioning."
;; %[] insert contents of a file.
(save-excursion
(while (re-search-forward "%\\[\\(.+\\)\\]" nil t)
- (unless (org-capture-escaped-%)
- (let ((start (match-beginning 0))
- (end (match-end 0))
- (filename (expand-file-name (match-string 1))))
- (goto-char start)
- (delete-region start end)
+ (let ((filename (expand-file-name (match-string 1)))
+ (beg (copy-marker (match-beginning 0)))
+ (end (copy-marker (match-end 0))))
+ (unless (org-capture-escaped-%)
+ (delete-region beg end)
+ (set-marker beg nil)
+ (set-marker end nil)
(condition-case error
(insert-file-contents filename)
- (error (insert (format "%%![couldn not insert %s: %s]"
- filename
- error))))))))
+ (error
+ (insert (format "%%![couldn not insert %s: %s]"
+ filename
+ error))))))))
;; Mark %() embedded elisp for later evaluation.
(org-capture-expand-embedded-elisp 'mark)
@@ -1632,13 +1634,17 @@ The template may still contain \"%?\" for cursor positioning."
(let ((regexp "%\\(:[-a-za-z]+\\|<\\([^>\n]+\\)>\\|[aAcfFikKlntTuUx]\\)"))
(save-excursion
(while (re-search-forward regexp nil t)
+ ;; `org-capture-escaped-%' may modify buffer and cripple
+ ;; match-data. Use markers instead. Ditto for other
+ ;; templates.
(let ((pos (copy-marker (match-beginning 0)))
(end (copy-marker (match-end 0)))
(value (match-string 1))
(time-string (match-string 2)))
(unless (org-capture-escaped-%)
- (goto-char pos)
(delete-region pos end)
+ (set-marker pos nil)
+ (set-marker end nil)
(let ((replacement
(pcase (string-to-char value)
(?< (format-time-string time-string))
@@ -1646,7 +1652,7 @@ The template may still contain \"%?\" for cursor positioning."
(or (plist-get org-store-link-plist (intern value))
""))
(?i (let ((lead (buffer-substring-no-properties
- (line-beginning-position) pos)))
+ (line-beginning-position) (point))))
(mapconcat #'identity
(split-string v-i "\n")
(concat "\n" lead))))
@@ -1668,9 +1674,7 @@ The template may still contain \"%?\" for cursor positioning."
(if (org-capture-inside-embedded-elisp-p)
(replace-regexp-in-string
"\"" "\\\\\"" replacement nil t)
- replacement)))
- (set-marker pos nil)
- (set-marker end nil))))))
+ replacement))))))))
;; Expand %() embedded Elisp. Limit to Sexp originally marked.
(org-capture-expand-embedded-elisp)
@@ -1685,21 +1689,24 @@ The template may still contain \"%?\" for cursor positioning."
(save-excursion
(let ((regexp "%\\^\\(?:{\\([^}]*\\)}\\)?\\([CgGLptTuU]\\)?"))
(while (re-search-forward regexp nil t)
- (unless (org-capture-escaped-%)
- (let* ((items
- (and (match-end 1)
- (save-match-data
- (split-string (match-string-no-properties 1)
- "|"))))
- (prompt (nth 0 items))
- (default (nth 1 items))
- (completions (nthcdr 2 items))
- (histvar
- (intern
- (concat "org-capture-template-prompt-history::"
- (or prompt ""))))
- (key (match-string 2)))
- (delete-region (match-beginning 0) (match-end 0))
+ (let* ((items (and (match-end 1)
+ (save-match-data
+ (split-string (match-string-no-properties 1)
+ "|"))))
+ (key (match-string 2))
+ (beg (copy-marker (match-beginning 0)))
+ (end (copy-marker (match-end 0)))
+ (prompt (nth 0 items))
+ (default (nth 1 items))
+ (completions (nthcdr 2 items))
+ (histvar
+ (intern
+ (concat "org-capture-template-prompt-history::"
+ (or prompt "")))))
+ (unless (org-capture-escaped-%)
+ (delete-region beg end)
+ (set-marker beg nil)
+ (set-marker end nil)
(pcase key
((or "G" "g")
(let* ((org-last-tags-completion-table
diff --git a/lisp/org-feed.el b/lisp/org-feed.el
index 07db989..3c742be 100644
--- a/lisp/org-feed.el
+++ b/lisp/org-feed.el
@@ -534,33 +534,40 @@ If that property is already present, nothing changes."
;; Mark %() embedded elisp for later evaluation.
(org-capture-expand-embedded-elisp 'mark)
- ;; Simple %-escapes
+ ;; Simple %-escapes. `org-capture-escaped-%' may modify
+ ;; buffer and cripple match-data. Use markers instead.
(while (re-search-forward "%\\([a-zA-Z]+\\)" nil t)
- (unless (org-capture-escaped-%)
- (let ((replacement
- (pcase (match-string-no-properties 1)
- ("h" v-h)
- ("t" v-t)
- ("T" v-T)
- ("u" v-u)
- ("U" v-U)
- ("a" v-a)
- (name
- (let ((v (plist-get entry (intern (concat ":" name)))))
- (save-excursion
- (save-match-data
- (beginning-of-line)
- (if (looking-at
- (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
- (org-feed-make-indented-block
- v (org-get-indentation))
- v))))))))
- (when replacement
- (replace-match
- ;; Escape string delimiters within embedded lisp.
- (if (org-capture-inside-embedded-elisp-p)
- (replace-regexp-in-string "\"" "\\\\\"" replacement nil t)
- replacement))))))
+ (let ((key (match-string 1))
+ (beg (copy-marker (match-beginning 0)))
+ (end (copy-marker (match-end 0))))
+ (unless (org-capture-escaped-%)
+ (delete-region beg end)
+ (set-marker beg nil)
+ (set-marker end nil)
+ (let ((replacement
+ (pcase key
+ ("h" v-h)
+ ("t" v-t)
+ ("T" v-T)
+ ("u" v-u)
+ ("U" v-U)
+ ("a" v-a)
+ (name
+ (let ((v (plist-get entry (intern (concat ":" name)))))
+ (save-excursion
+ (save-match-data
+ (beginning-of-line)
+ (if (looking-at
+ (concat "^\\([ \t]*\\)%" name "[ \t]*$"))
+ (org-feed-make-indented-block
+ v (org-get-indentation))
+ v))))))))
+ (when replacement
+ (insert
+ ;; Escape string delimiters within embedded lisp.
+ (if (org-capture-inside-embedded-elisp-p)
+ (replace-regexp-in-string "\"" "\\\\\"" replacement nil t)
+ replacement)))))))
;; %() embedded elisp
(org-capture-expand-embedded-elisp)