Jelajahi Sumber

org-add-planning-info: Improve deletion handling

* lisp/org.el (org-add-planning-info): Reset point before each
  planning entry search.  Clean up extra spaces.

* testing/lisp/test-org.el (test-org/add-planning-info): Add tests.

- Reposition save-excursion call to reset point every dolist
  iteration.  Otherwise, the order of the entries to be removed
  matters, and a call like

      (org-add-planning-info nil nil 'scheduled 'deadline)

  on

      DEADLINE: <2015-06-26 Fri> SCHEDULED: <2015-06-26 Fri>

  will fail to remove the deadline entry.

- Delete leading white space even when at the beginning of the line so
  that, when org-adapt-indentation is nil, a space is not inserted
  when removing the leading planning info entry.

  This prevents headings with repeating entries like

      SCHEDULED: <2015-06-26 Fri +1w>

  from being closed and recycled with an extra space in front of
  SCHEDULED.

- Add leading white space to the planning info entry regexp to prevent
  leftover white space when removing entries other than the first
  entry.
Kyle Meyer 10 tahun lalu
induk
melakukan
5f3d8037a5
2 mengubah file dengan 179 tambahan dan 16 penghapusan
  1. 20 16
      lisp/org.el
  2. 159 0
      testing/lisp/test-org.el

+ 20 - 16
lisp/org.el

@@ -13478,23 +13478,27 @@ WHAT entry will also be removed."
 	      (skip-chars-forward " \t")
 	      (skip-chars-forward " \t")
 	      ;; Check if we have to remove something.
 	      ;; Check if we have to remove something.
 	      (dolist (type (if what (cons what remove) remove))
 	      (dolist (type (if what (cons what remove) remove))
-		(when (save-excursion
-			(re-search-forward
-			 (case type
-			   (closed org-closed-time-regexp)
-			   (deadline org-deadline-time-regexp)
-			   (scheduled org-scheduled-time-regexp)
-			   (otherwise (error "Invalid planning type: %s" type)))
-			 (line-end-position) t))
-		  (replace-match "")
-		  (when (looking-at "--+<[^>]+>") (replace-match ""))
-		  (when (and (not what) (eq type 'closed))
-		    (save-excursion
-		      (beginning-of-line)
-		      (if (looking-at "[ \t]*$")
-			  (delete-region (point) (1+ (point-at-eol)))))))
+		(save-excursion
+		  (when (re-search-forward
+			 (concat
+			  " *"
+			  (case type
+			    (closed org-closed-time-regexp)
+			    (deadline org-deadline-time-regexp)
+			    (scheduled org-scheduled-time-regexp)
+			    (otherwise
+			     (error "Invalid planning type: %s" type))))
+			 (line-end-position) t)
+		    (replace-match "")
+		    (when (looking-at "--+<[^>]+>") (replace-match ""))
+		    (when (and (not what) (eq type 'closed))
+		      (save-excursion
+			(beginning-of-line)
+			(when (looking-at "[ \t]*$")
+			  (delete-region (point)
+					 (line-beginning-position 2)))))))
 		;; Remove leading white spaces.
 		;; Remove leading white spaces.
-		(when (and (not (bolp)) (looking-at "[ \t]+")) (replace-match ""))))
+		(when (looking-at "[ \t]+") (replace-match ""))))
 	     ((not what) (throw 'exit nil)) ; Nothing to do.
 	     ((not what) (throw 'exit nil)) ; Nothing to do.
 	     (t (insert-before-markers "\n")
 	     (t (insert-before-markers "\n")
 		(backward-char 1)
 		(backward-char 1)

+ 159 - 0
testing/lisp/test-org.el

@@ -2858,6 +2858,165 @@ Text.
 	 "* Headline\n*** Inlinetask\n*** END\n<point>DEADLINE: <2014-03-04 tue.>"
 	 "* Headline\n*** Inlinetask\n*** END\n<point>DEADLINE: <2014-03-04 tue.>"
        (let ((org-inlinetask-min-level 3)) (org-at-planning-p))))))
        (let ((org-inlinetask-min-level 3)) (org-at-planning-p))))))
 
 
+(ert-deftest test-org/add-planning-info ()
+  "Test `org-add-planning-info'."
+  ;; Create deadline when `org-adapt-indentation' is non-nil.
+  (should
+   (equal "* H\n  DEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "* H\nParagraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Create deadline when `org-adapt-indentation' is nil.
+  (should
+   (equal "* H\nDEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "* H\nParagraph<point>"
+	    (let ((org-adapt-indentation nil))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Update deadline when `org-adapt-indentation' is non-nil.
+  (should
+   (equal "* H\n  DEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "\
+* H
+  DEADLINE: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Update deadline when `org-adapt-indentation' is nil.
+  (should
+   (equal "* H\nDEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "\
+* H
+DEADLINE: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation nil))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Schedule when `org-adapt-indentation' is non-nil.
+  (should
+   (equal "* H\n  SCHEDULED: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "* H\nParagraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info 'scheduled "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Schedule when `org-adapt-indentation' is nil.
+  (should
+   (equal "* H\nSCHEDULED: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "* H\nParagraph<point>"
+	    (let ((org-adapt-indentation nil))
+	      (org-add-planning-info 'scheduled "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Add deadline when scheduled.
+  (should
+   (equal "\
+* H
+  DEADLINE: <2015-06-25> SCHEDULED: <2015-06-24>
+Paragraph"
+	  (org-test-with-temp-text "\
+* H
+  SCHEDULED: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>"))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove middle entry.
+  (should
+   (equal "\
+* H
+  CLOSED: [2015-06-24] SCHEDULED: <2015-06-24>
+Paragraph"
+	  (org-test-with-temp-text "\
+* H
+  CLOSED: [2015-06-24 Wed] DEADLINE: <2015-06-25 Thu> SCHEDULED: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info nil nil 'deadline))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)[]>]" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove last entry and then middle entry (order should not
+  ;; matter).
+  (should
+   (equal "\
+* H
+  CLOSED: [2015-06-24]
+Paragraph"
+	  (org-test-with-temp-text "\
+* H
+  CLOSED: [2015-06-24 Wed] DEADLINE: <2015-06-25 Thu> SCHEDULED: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info nil nil 'scheduled 'deadline))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)[]>]" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove closed when `org-adapt-indentation' is non-nil.
+  (should
+   (equal "* H\n  DEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "\
+* H
+  CLOSED: [2015-06-25 Thu] DEADLINE: <2015-06-25 Thu>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info nil nil 'closed))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove closed when `org-adapt-indentation' is nil.
+  (should
+   (equal "* H\nDEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "\
+* H
+CLOSED: [2015-06-25 Thu] DEADLINE: <2015-06-25 Thu>
+Paragraph<point>"
+	    (let ((org-adapt-indentation nil))
+	      (org-add-planning-info nil nil 'closed))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove closed entry and delete empty line.
+  (should
+   (equal "\
+* H
+Paragraph"
+	  (org-test-with-temp-text "\
+* H
+  CLOSED: [2015-06-24 Wed]
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info nil nil 'closed))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1))))
+  ;; Remove one entry and update another.
+  (should
+   (equal "* H\n  DEADLINE: <2015-06-25>\nParagraph"
+	  (org-test-with-temp-text "\
+* H
+  SCHEDULED: <2015-06-23 Tue> DEADLINE: <2015-06-24 Wed>
+Paragraph<point>"
+	    (let ((org-adapt-indentation t))
+	      (org-add-planning-info 'deadline "<2015-06-25 Thu>" 'scheduled))
+	    (replace-regexp-in-string
+	     "\\( [.A-Za-z]+\\)>" "" (buffer-string)
+	     nil nil 1)))))
+
 
 
 ;;; Property API
 ;;; Property API