org-capture: Fix escaping characters in template embedded S-exps

* lisp/org-capture.el (org-capture-fill-template): Escape backslash
  characters in %i contents when those are inserted within a S-exp.
  Also prevent adding any prefix to %i contents spanning over multiple
  lines when they are inserted within a S-exp.

* testing/lisp/test-org-capture.el (test-org-capture/fill-template):
  Add tests.

Reported-by: Samuel Wales <samologist@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/112232>
This commit is contained in:
Nicolas Goaziou 2017-03-13 22:45:54 +01:00
parent ad19484676
commit 92ee4d06a2
2 changed files with 46 additions and 26 deletions

View File

@ -1654,34 +1654,41 @@ The template may still contain \"%?\" for cursor positioning."
(delete-region pos end)
(set-marker pos nil)
(set-marker end nil)
(let ((replacement
(pcase (string-to-char value)
(?< (format-time-string time-string))
(?:
(or (plist-get org-store-link-plist (intern value))
""))
(?i (let ((lead (buffer-substring-no-properties
(let* ((inside-sexp? (org-capture-inside-embedded-elisp-p))
(replacement
(pcase (string-to-char value)
(?< (format-time-string time-string))
(?:
(or (plist-get org-store-link-plist (intern value))
""))
(?i
(if inside-sexp? v-i
;; Outside embedded Lisp, repeat leading
;; characters before initial place holder
;; every line.
(let ((lead (buffer-substring-no-properties
(line-beginning-position) (point))))
(mapconcat #'identity
(split-string v-i "\n")
(concat "\n" lead))))
(?a v-a)
(?A v-A)
(?c v-c)
(?f v-f)
(?F v-F)
(?k v-k)
(?K v-K)
(?l v-l)
(?n v-n)
(?t v-t)
(?T v-T)
(?u v-u)
(?U v-U)
(?x v-x))))
(replace-regexp-in-string "\n\\(.\\)"
(concat lead "\\1")
v-i nil nil 1))))
(?a v-a)
(?A v-A)
(?c v-c)
(?f v-f)
(?F v-F)
(?k v-k)
(?K v-K)
(?l v-l)
(?n v-n)
(?t v-t)
(?T v-T)
(?u v-u)
(?U v-U)
(?x v-x))))
(insert
(if (org-capture-inside-embedded-elisp-p)
(replace-regexp-in-string "\"" "\\\\\"" replacement)
(if inside-sexp?
;; Escape sensitive characters.
(replace-regexp-in-string "[\\\"]" "\\\\\\&" replacement)
replacement))))))))
;; Expand %() embedded Elisp. Limit to Sexp originally marked.

View File

@ -35,6 +35,13 @@
(should
(equal "success!\n"
(org-capture-fill-template "%(concat \"success\" \"!\")")))
;; It is possible to include other place holders in %(sexp). In
;; that case properly escape \ and " characters.
(should
(equal "Nested string \"\\\"\\\"\"\n"
(let ((org-store-link-plist nil))
(org-capture-fill-template "%(concat \"%i\")"
"Nested string \"\\\"\\\"\""))))
;; %<...> placeholder.
(should
(equal (concat (format-time-string "%Y") "\n")
@ -66,6 +73,12 @@
(let ((org-store-link-plist nil))
(org-capture-fill-template
"%i" "%(concat \"no \" \"evaluation\")"))))
;; When %i contents span over multiple line, repeat initial leading
;; characters over each line.
(should
(equal "> line 1\n> line 2\n"
(let ((org-store-link-plist nil))
(org-capture-fill-template "> %i" "line 1\nline 2"))))
;; Test %-escaping with \ character.
(should
(equal "%i\n"