瀏覽代碼

Fix quirks in `org-insert-structure-template'

* lisp/org.el (org-insert-structure-template): Fix some issues.
  Refactor code.
* testing/lisp/test-org.el (test-org/insert-structure-template):
  Update tests.

Reported-by: stardiviner <numbchild@gmail.com>
<http://lists.gnu.org/r/emacs-orgmode/2018-05/msg00553.html>
Nicolas Goaziou 7 年之前
父節點
當前提交
ed7d1dc6d7
共有 2 個文件被更改,包括 42 次插入67 次删除
  1. 28 54
      lisp/org.el
  2. 14 13
      testing/lisp/test-org.el

+ 28 - 54
lisp/org.el

@@ -11840,7 +11840,7 @@ If an element cannot be made unique, an error is raised."
 		     :key (lambda (elm) (cl-position (cdr elm) keys))))))
 		     :key (lambda (elm) (cl-position (cdr elm) keys))))))
 
 
 (defun org-insert-structure-template (type)
 (defun org-insert-structure-template (type)
-    "Insert a block structure of the type #+begin_foo/#+end_foo.
+  "Insert a block structure of the type #+begin_foo/#+end_foo.
 Select a block from `org-structure-template-alist' then type
 Select a block from `org-structure-template-alist' then type
 either RET, TAB or SPC to write the block type.  With an active
 either RET, TAB or SPC to write the block type.  With an active
 region, wrap the region in the block.  Otherwise, insert an empty
 region, wrap the region in the block.  Otherwise, insert an empty
@@ -11849,62 +11849,36 @@ block."
    (list (pcase (org--insert-structure-template-mks)
    (list (pcase (org--insert-structure-template-mks)
 	   (`("\t" . ,_) (read-string "Structure type: "))
 	   (`("\t" . ,_) (read-string "Structure type: "))
 	   (`(,_ ,choice . ,_) choice))))
 	   (`(,_ ,choice . ,_) choice))))
-  (let* ((region? (use-region-p))
-	 (col (current-indentation))
-	 (indent (make-string col ?\s))
-	 (special? (string-match-p "\\(src\\|export\\)\\'" type))
-	 (region-string (and region?
-			     (buffer-substring (region-beginning)
-					       (region-end))))
-	 (region-end-blank (and region?
-				(save-excursion
-				  (goto-char (region-end))
-				  (when (looking-at "[ \t]*$")
-				    (replace-match "")
-				    t))))
-	 s)
-    (when region? (delete-region (region-beginning) (region-end)))
-    (unless (save-excursion (skip-chars-backward "[ \t]") (bolp))
+  (let* ((column (current-indentation))
+	 (region? (use-region-p))
+	 (region-start (and region? (region-beginning)))
+	 (region-end (and region? (copy-marker (region-end))))
+	 (special? (string-match-p "\\`\\(src\\|export\\)\\'" type)))
+    (when region? (goto-char region-start))
+    (if (save-excursion (skip-chars-backward " \t") (bolp))
+	(beginning-of-line)
       (insert "\n"))
       (insert "\n"))
-    (beginning-of-line)
     (save-excursion
     (save-excursion
-      (insert
-       (with-temp-buffer
-	 (when region?
-	   (insert region-string "\n")
-	   (when (string-match-p
-		  (concat "\\`" (regexp-opt '("example" "export" "src")))
-		  type)
-	     (org-escape-code-in-region (point-min) (point-max))))
-	 (goto-char (point-min))
-	 ;; Delete trailing white-lines.
-	 (when region?
-	   (while (looking-at-p "^[ \t]*$")
-	     (delete-region (line-beginning-position)
-			    (line-beginning-position 2))))
-	 (save-excursion
-	   (while (not (eobp))
-	     (unless (looking-at-p indent)
-	       (insert indent))
-	     (forward-line)))
-	 (insert
-	  indent
-	  (format "#+begin_%s%s\n" type (if special? " " "")))
-	 (unless region? (indent-to col))
-	 (setq s (point))
-	 (goto-char (point-max))
-	 (skip-chars-backward "[ \t\n]" s)
-	 (delete-region (line-end-position) (point-max))
-	 (insert "\n" indent
-		 (format "#+end_%s" (car (split-string type)))
-		 (if region-end-blank "" "\n"))
-	 (buffer-substring (point-min) (point))))
+      (indent-to column)
+      (insert (format "#+begin_%s%s\n" type (if special? " " "")))
+      (when region?
+	(when (string-match-p (concat "\\`"
+				      (regexp-opt '("example" "export" "src")))
+			      type)
+	  (org-escape-code-in-region (point) region-end))
+	(goto-char region-end)
+	;; Ignore empty lines at the end of the region.
+	(skip-chars-backward " \r\t\n")
+	(end-of-line))
+      (unless (bolp) (insert "\n"))
+      (indent-to column)
+      (insert (format "#+end_%s" (car (split-string type))))
+      (if (looking-at "[ \t]*$") (replace-match "")
+	(insert "\n"))
       (when (and (eobp) (not (bolp))) (insert "\n")))
       (when (and (eobp) (not (bolp))) (insert "\n")))
-    (cond (special?
-	   (end-of-line))
-	  (t
-	   (forward-line)
-	   (skip-chars-forward "[ \t]*")))))
+    (if special? (end-of-line)
+      (forward-line)
+      (skip-chars-forward " \t"))))
 
 
 
 
 ;;;; TODO, DEADLINE, Comments
 ;;;; TODO, DEADLINE, Comments

+ 14 - 13
testing/lisp/test-org.el

@@ -4060,18 +4060,19 @@ Text.
        (org-next-block 1 nil "^[ \t]*#\\+BEGIN_QUOTE")
        (org-next-block 1 nil "^[ \t]*#\\+BEGIN_QUOTE")
        (looking-at "#\\+begin_quote")))))
        (looking-at "#\\+begin_quote")))))
 
 
-(ert-deftest test-org/insert-template ()
+(ert-deftest test-org/insert-structure-template ()
   "Test `org-insert-structure-template'."
   "Test `org-insert-structure-template'."
   ;; Test in empty buffer.
   ;; Test in empty buffer.
   (should
   (should
-   (string= "#+begin_foo\n\n#+end_foo\n"
+   (string= "#+begin_foo\n#+end_foo\n"
 	    (org-test-with-temp-text ""
 	    (org-test-with-temp-text ""
 	      (org-insert-structure-template "foo")
 	      (org-insert-structure-template "foo")
 	      (buffer-string))))
 	      (buffer-string))))
   ;; Test with multiple lines in buffer.
   ;; Test with multiple lines in buffer.
   (should
   (should
-   (string= "#+begin_foo\nI'm a paragraph\n#+end_foo\nI'm a second paragraph"
+   (string= "#+begin_foo\nI'm a paragraph\n#+end_foo\n\nI'm a second paragraph"
 	    (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragraph"
 	    (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragraph"
+	      (transient-mark-mode 1)
 	      (org-mark-element)
 	      (org-mark-element)
 	      (org-insert-structure-template "foo")
 	      (org-insert-structure-template "foo")
 	      (buffer-string))))
 	      (buffer-string))))
@@ -4079,12 +4080,12 @@ Text.
   (should
   (should
    (string= "#+begin_foo\nI'm a paragraph\n#+end_foo\n\nI'm a second paragraph"
    (string= "#+begin_foo\nI'm a paragraph\n#+end_foo\n\nI'm a second paragraph"
 	    (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragraph"
 	    (org-test-with-temp-text "I'm a paragraph\n\nI'm a second paragraph"
+	      (transient-mark-mode 1)
 	      (set-mark (point-min))
 	      (set-mark (point-min))
 	      (end-of-line)
 	      (end-of-line)
-	      (activate-mark)
 	      (org-insert-structure-template "foo")
 	      (org-insert-structure-template "foo")
 	      (buffer-string))))
 	      (buffer-string))))
-  ;; Middle of paragraph
+  ;; Middle of paragraph.
   (should
   (should
    (string= "p1\n#+begin_foo\np2\n#+end_foo\np3"
    (string= "p1\n#+begin_foo\np2\n#+end_foo\np3"
 	    (org-test-with-temp-text "p1\n<point>p2\np3"
 	    (org-test-with-temp-text "p1\n<point>p2\np3"
@@ -4124,15 +4125,15 @@ Text.
 	      (buffer-string))))
 	      (buffer-string))))
   ;; Test point location.
   ;; Test point location.
   (should
   (should
-   (eq (length "#\\+begin_foo\n")
-       (org-test-with-temp-text ""
-	 (org-insert-structure-template "foo")
-	 (point))))
+   (string= "#+begin_foo\n"
+	    (org-test-with-temp-text ""
+	      (org-insert-structure-template "foo")
+	      (buffer-substring (point-min) (point)))))
   (should
   (should
-   (eq (length "#\\+begin_src ")
-       (org-test-with-temp-text ""
-	 (org-insert-structure-template "src")
-	 (point)))))
+   (string= "#+begin_src "
+	    (org-test-with-temp-text ""
+	      (org-insert-structure-template "src")
+	      (buffer-substring (point-min) (point))))))
 
 
 (ert-deftest test-org/previous-block ()
 (ert-deftest test-org/previous-block ()
   "Test `org-previous-block' specifications."
   "Test `org-previous-block' specifications."