summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2018-10-23 01:22:49 +0200
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2018-10-23 01:26:17 +0200
commit7a4a10dea036658633060f4a43dcc95e6b5b4423 (patch)
tree90698b98e2b9c90883113c6b7d7dd915ccc87c01
parentad0fce50ebe8864c365bfba4d4a8e0e6a767d266 (diff)
downloadorg-mode-7a4a10dea036658633060f4a43dcc95e6b5b4423.tar.gz
org-capture: Fix plain capture at the end of the buffer.
* lisp/org-capture.el (org-capture-place-plain-text): Fix plain capture at the end of the buffer. * testing/lisp/test-org-capture.el (test-org-capture/plain): New test.
-rw-r--r--lisp/org-capture.el59
-rw-r--r--testing/lisp/test-org-capture.el65
2 files changed, 96 insertions, 28 deletions
diff --git a/lisp/org-capture.el b/lisp/org-capture.el
index 462dbb1..f327bd0 100644
--- a/lisp/org-capture.el
+++ b/lisp/org-capture.el
@@ -1291,35 +1291,38 @@ If the target locator points at an Org node, place the template into
the text of the entry, before the first child. If not, place the
template at the beginning or end of the file.
Of course, if exact position has been required, just put it there."
- (let* ((txt (org-capture-get :template))
- beg end)
- (cond
- ((org-capture-get :exact-position)
- (goto-char (org-capture-get :exact-position)))
- ((and (org-capture-get :target-entry-p)
- (bolp)
- (looking-at org-outline-regexp))
- ;; we should place the text into this entry
- (if (org-capture-get :prepend)
- ;; Skip meta data and drawers
- (org-end-of-meta-data t)
- ;; go to ent of the entry text, before the next headline
- (outline-next-heading)))
- (t
- ;; beginning or end of file
- (goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
- (or (bolp) (newline))
+ (cond
+ ((org-capture-get :exact-position)
+ (goto-char (org-capture-get :exact-position)))
+ ((and (org-capture-get :target-entry-p)
+ (bolp)
+ (looking-at org-outline-regexp))
+ ;; Place the text into this entry.
+ (if (org-capture-get :prepend)
+ ;; Skip meta data and drawers.
+ (org-end-of-meta-data t)
+ ;; Go to end of the entry text, before the next headline
+ (outline-next-heading)))
+ (t
+ ;; Beginning or end of file.
+ (goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
+ (let ((origin (point)))
+ (unless (bolp) (insert "\n"))
(org-capture-empty-lines-before)
- (setq beg (point))
- (insert txt)
- (org-capture-empty-lines-after)
- (org-capture-position-for-last-stored beg)
- (setq end (point))
- (org-capture-mark-kill-region beg (1- end))
- (org-capture-narrow beg (1- end))
- (when (or (re-search-backward "%\\?" beg t)
- (re-search-forward "%\\?" end t))
- (replace-match ""))))
+ (org-capture-position-for-last-stored (point))
+ (let ((beg (point)))
+ (insert (org-capture-get :template))
+ (unless (bolp) (insert "\n"))
+ ;; Ignore the final newline character so as to not alter data
+ ;; after inserted text. Yet, if the template is empty, make
+ ;; sure END matches BEG instead of pointing before it.
+ (let ((end (max beg (1- (point)))))
+ (org-capture-empty-lines-after)
+ (org-capture-mark-kill-region origin (point))
+ (org-capture-narrow beg end)
+ (when (or (search-backward "%?" beg t)
+ (search-forward "%?" end t))
+ (replace-match ""))))))
(defun org-capture-mark-kill-region (beg end)
"Mark the region that will have to be killed when aborting capture."
diff --git a/testing/lisp/test-org-capture.el b/testing/lisp/test-org-capture.el
index 56f7783..f53c154 100644
--- a/testing/lisp/test-org-capture.el
+++ b/testing/lisp/test-org-capture.el
@@ -373,6 +373,71 @@
(org-capture nil "t")
(org-table-get-stored-formulas))))))
+(ert-deftest test-org-capture/plain ()
+ "Test `plain' type in capture template."
+ ;; Insert at end of the file, unless `:prepend' is non-nil.
+ (should
+ (equal "Some text.\nFoo\n"
+ (org-test-with-temp-text-in-file "Some text."
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file ,file) "Foo"
+ :immediate-finish t))))
+ (org-capture nil "t")
+ (buffer-string)))))
+ (should
+ (equal "Foo\nSome text."
+ (org-test-with-temp-text-in-file "Some text."
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file ,file) "Foo"
+ :immediate-finish t :prepend t))))
+ (org-capture nil "t")
+ (buffer-string)))))
+ ;; When a headline is specified, add it at the beginning of the
+ ;; entry, past any meta-data, or at its end, depending on
+ ;; `:prepend'.
+ (should
+ (equal "* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\nFoo\n* B"
+ (org-test-with-temp-text-in-file
+ "* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\n* B"
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file+headline ,file "A") "Foo"
+ :immediate-finish t))))
+ (org-capture nil "t")
+ (buffer-string)))))
+ (should
+ (equal "* A\nSCHEDULED: <2012-03-29 Thu>\nFoo\nSome text.\n* B"
+ (org-test-with-temp-text-in-file
+ "* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\n* B"
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file+headline ,file "A") "Foo"
+ :immediate-finish t :prepend t))))
+ (org-capture nil "t")
+ (buffer-string)))))
+ ;; At an exact position, in the middle of a line, make sure to
+ ;; insert text on a line on its own.
+ (should
+ (equal "A\nX\nB"
+ (org-test-with-temp-text-in-file "AB"
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file+function ,file forward-char) "X"
+ :immediate-finish t))))
+ (org-capture nil "t")
+ (buffer-string)))))
+ ;; Pathological case: insert an empty template in an empty file.
+ (should
+ (equal ""
+ (org-test-with-temp-text-in-file ""
+ (let* ((file (buffer-file-name))
+ (org-capture-templates
+ `(("t" "Text" plain (file ,file) ""
+ :immediate-finish t))))
+ (org-capture nil "t")
+ (buffer-string))))))
(provide 'test-org-capture)
;;; test-org-capture.el ends here