Browse Source

Fix `org-read-date-prefer-future' when rescheduling

* lisp/org.el (org-read-date-analyze): When
  `org-read-date-prefer-future', offer a date in the future even if
  default date is different from now.

* testing/lisp/test-org.el (test-org/org-read-date): Add tests.

Reported-by: Rasmus <rasmus@gmx.us>
<http://permalink.gmane.org/gmane.emacs.orgmode/93805>
Nicolas Goaziou 10 năm trước cách đây
mục cha
commit
85c55d453b
2 tập tin đã thay đổi với 110 bổ sung11 xóa
  1. 29 10
      lisp/org.el
  2. 81 1
      testing/lisp/test-org.el

+ 29 - 10
lisp/org.el

@@ -16936,16 +16936,35 @@ user."
 
     (setq tl (parse-time-string ans)
 	  day (or (nth 3 tl) (nth 3 org-defdecode))
-	  month (or (nth 4 tl)
-		    (if (and org-read-date-prefer-future
-			     (nth 3 tl) (< (nth 3 tl) (nth 3 nowdecode)))
-			(prog1 (1+ (nth 4 nowdecode)) (setq futurep t))
-		      (nth 4 org-defdecode)))
-	  year (or (and (not kill-year) (nth 5 tl))
-		   (if (and org-read-date-prefer-future
-			    (nth 4 tl) (< (nth 4 tl) (nth 4 nowdecode)))
-		       (prog1 (1+ (nth 5 nowdecode)) (setq futurep t))
-		     (nth 5 org-defdecode)))
+	  month
+	  (cond ((nth 4 tl))
+		((not org-read-date-prefer-future) (nth 4 org-defdecode))
+		;; Day was specified.  Make sure DAY+MONTH
+		;; combination happens in the future.
+		((nth 3 tl)
+		 (setq futurep t)
+		 (if (< day (nth 3 nowdecode)) (1+ (nth 4 nowdecode))
+		   (nth 4 nowdecode)))
+		(t (nth 4 org-defdecode)))
+	  year
+	  (cond ((and (not kill-year) (nth 5 tl)))
+		((not org-read-date-prefer-future) (nth 5 org-defdecode))
+		;; Month was guessed in the future and is at least
+		;; equal to NOWDECODE's.  Fix year accordingly.
+		(futurep
+		 (if (or (> month (nth 4 nowdecode))
+			 (>= day (nth 3 nowdecode)))
+		     (nth 5 nowdecode)
+		   (1+ (nth 5 nowdecode))))
+		;; Month was specified.  Make sure MONTH+YEAR
+		;; combination happens in the future.
+		((nth 4 tl)
+		 (setq futurep t)
+		 (cond ((> month (nth 4 nowdecode)) (nth 5 nowdecode))
+		       ((< month (nth 5 nowdecode)) (1+ (nth 5 nowdecode)))
+		       ((< day (nth 3 nowdecode)) (1+ (nth 5 nowdecode)))
+		       (t (nth 5 nowdecode))))
+		(t (nth 5 org-defdecode)))
 	  hour (or (nth 2 tl) (nth 2 org-defdecode))
 	  minute (or (nth 1 tl) (nth 1 org-defdecode))
 	  second (or (nth 0 tl) 0)

+ 81 - 1
testing/lisp/test-org.el

@@ -191,7 +191,87 @@
   ;; Parse Europeans dates without year.
   (should (string-match "2[0-9]\\{3\\}-03-29 16:40"
 			(let ((org-time-was-given t))
-			  (org-read-date t nil "29.03. 16:40")))))
+			  (org-read-date t nil "29.03. 16:40"))))
+  ;; Relative date applied to current time if there is single
+  ;; plus/minus, or to default date when there are two of them.
+  (should
+   (equal
+    "2015-03-04"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2014-03-04"))))
+      (org-read-date
+       t nil "+1y" nil
+       (apply #'encode-time (org-parse-time-string "2012-03-29"))))))
+  (should
+   (equal
+    "2013-03-29"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2014-03-04"))))
+      (org-read-date
+       t nil "++1y" nil
+       (apply #'encode-time (org-parse-time-string "2012-03-29"))))))
+  ;; When `org-read-date-prefer-future' is non-nil, prefer future
+  ;; dates (relatively to now) when incomplete.  Otherwise, use
+  ;; default date.
+  (should
+   (equal
+    "2014-04-01"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2014-03-04"))))
+      (let ((org-read-date-prefer-future t))
+	(org-read-date t nil "1")))))
+  (should
+   (equal
+    "2013-03-04"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2012-03-29"))))
+      (let ((org-read-date-prefer-future t))
+	(org-read-date t nil "3-4")))))
+  (should
+   (equal
+    "2012-03-04"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2012-03-29"))))
+      (let ((org-read-date-prefer-future nil))
+	(org-read-date t nil "3-4")))))
+  ;; When set to `org-read-date-prefer-future' is set to `time', read
+  ;; day is moved to tomorrow if specified hour is before current
+  ;; time.  However, it only happens in no other part of the date is
+  ;; specified.
+  (should
+   (equal
+    "2012-03-30"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2012-03-29 16:40"))))
+      (let ((org-read-date-prefer-future 'time))
+	(org-read-date t nil "00:40" nil)))))
+  (should-not
+   (equal
+    "2012-03-30"
+    (flet ((current-time () (apply #'encode-time
+				   (org-parse-time-string "2012-03-29 16:40"))))
+      (let ((org-read-date-prefer-future 'time))
+	(org-read-date t nil "29 00:40" nil)))))
+  ;; Caveat: `org-read-date-prefer-future' always refers to current
+  ;; time, not default time, when they differ.
+  (should
+   (equal
+    "2014-04-01"
+    (flet ((current-time
+	    () (apply #'encode-time (org-parse-time-string "2014-03-04"))))
+      (let ((org-read-date-prefer-future t))
+	(org-read-date
+	 t nil "1" nil
+	 (apply #'encode-time (org-parse-time-string "2012-03-29")))))))
+  (should
+   (equal
+    "2014-03-25"
+    (flet ((current-time
+	    () (apply #'encode-time (org-parse-time-string "2014-03-04"))))
+      (let ((org-read-date-prefer-future t))
+	(org-read-date
+	 t nil "25" nil
+	 (apply #'encode-time (org-parse-time-string "2012-03-29"))))))))
 
 (ert-deftest test-org/org-parse-time-string ()
   "Test `org-parse-time-string'."