Browse Source

Merge branch 'master' into next

Nicolas Goaziou 7 years ago
parent
commit
ea47ed0d76
2 changed files with 123 additions and 45 deletions
  1. 49 45
      lisp/org-capture.el
  2. 74 0
      testing/lisp/test-org-capture.el

+ 49 - 45
lisp/org-capture.el

@@ -1111,8 +1111,10 @@ may have been stored before."
 
 (defun org-capture-place-entry ()
   "Place the template as a new Org entry."
-  (let ((reversed? (org-capture-get :prepend))
+  (let ((template (org-capture-get :template))
+	(reversed? (org-capture-get :prepend))
 	(level 1))
+    (org-capture-verify-tree template)
     (when (org-capture-get :exact-position)
       (goto-char (org-capture-get :exact-position)))
     (cond
@@ -1131,11 +1133,9 @@ may have been stored before."
     (let ((origin (point)))
       (unless (bolp) (insert "\n"))
       (org-capture-empty-lines-before)
+      (org-capture-position-for-last-stored (point))
       (let ((beg (point)))
-	(org-capture-position-for-last-stored beg)
-	(let ((template (org-capture-get :template)))
-	  (org-capture-verify-tree template)
-	  (org-paste-subtree level template 'for-yank))
+	(org-paste-subtree level template 'for-yank)
 	(let ((end (if (org-at-heading-p) (line-end-position 0) (point))))
 	  (org-capture-empty-lines-after)
 	  (unless (org-at-heading-p) (outline-next-heading))
@@ -1271,18 +1271,21 @@ may have been stored before."
      (t
       (goto-char (org-table-end))))
     ;; Insert text and position point according to template.
-    (unless (bolp) (insert "\n"))
-    (let ((beg (point))
-	  (end (save-excursion
-		 (insert text)
-		 (point))))
-      (org-capture-position-for-last-stored 'table-line)
-      (org-capture-mark-kill-region beg end)
-      (org-capture-narrow beg end)
-      (when (or (re-search-backward "%\\?" beg t)
-		(re-search-forward "%\\?" end t))
-	(replace-match "")))
-    (org-table-align)))
+    (let ((origin (point)))
+      (unless (bolp) (insert "\n"))
+      (let ((beg (point))
+	    (end (save-excursion
+		   (insert text)
+		   (point))))
+	(org-capture-position-for-last-stored 'table-line)
+	(org-capture-mark-kill-region origin end)
+	;; TEXT is guaranteed to end with a newline character.  Ignore
+	;; it when narrowing so as to not alter data on the next line.
+	(org-capture-narrow beg (1- end))
+	(when (or (search-backward "%?" beg t)
+		  (search-forward "%?" end t))
+	  (replace-match "")))
+      (org-table-align))))
 
 (defun org-capture-place-plain-text ()
   "Place the template plainly.
@@ -1290,35 +1293,36 @@ 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)))
+   ((org-capture-get :target-entry-p)
+    ;; 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."

+ 74 - 0
testing/lisp/test-org-capture.el

@@ -161,6 +161,15 @@
 	(insert "Capture text")
 	(org-capture-kill))
       (buffer-string))))
+  (should
+   (equal "| a |\n| b |"
+	  (org-test-with-temp-text-in-file "| a |\n| b |"
+	    (let* ((file (buffer-file-name))
+		   (org-capture-templates
+		    `(("t" "Table" table-line (file ,file) "| x |"))))
+	      (org-capture nil "t")
+	      (org-capture-kill))
+	    (buffer-string))))
   ;; Test aborting a capture that split the line.
   (should
    (equal
@@ -364,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