]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix several todo-mode.el editing bugs (bug#42976)
authorStephen Berman <stephen.berman@gmx.net>
Fri, 21 Aug 2020 20:41:48 +0000 (22:41 +0200)
committerStephen Berman <stephen.berman@gmx.net>
Fri, 21 Aug 2020 20:41:48 +0000 (22:41 +0200)
* lisp/calendar/todo-mode.el (todo-insert-item--basic): Ensure the
target todo file is in todo-mode.
(todo-edit-item--text): When editing a done item comment, prevent
clobbering match data on finishing the edit.
(todo-edit-item--header): Ensure that decrementing the month of
the date header works for intervals greater than a year, and when
incrementing or decrementing the month crosses one or more years,
adjust the year as needed.
(todo-read-category): If we're outside of todo-mode and there is a
current todo file, use it; otherwise, use the default todo file.

* test/lisp/calendar/todo-mode-tests.el
(todo-test-edit-item-date-month): New test.

* test/lisp/calendar/todo-mode-resources/todo-test-1.todo: Modify
to accommodate new test.

lisp/calendar/todo-mode.el
test/lisp/calendar/todo-mode-resources/todo-test-1.todo
test/lisp/calendar/todo-mode-tests.el

index a49f428a3c8d4acf9951bfbd6a9b493116914d6a..4f513d3386576333c67e037f6550ada8e6f50327 100644 (file)
@@ -1937,11 +1937,13 @@ their associated keys and their effects."
        (find-file-noselect file 'nowarn)
        (set-window-buffer (selected-window)
                           (set-buffer (find-buffer-visiting file)))
-       ;; If this command was invoked outside of a Todo mode buffer,
-       ;; the call to todo-current-category above returned nil.  If
-       ;; we just entered Todo mode now, then cat was set to the
-       ;; file's first category, but if todo-mode was already
-       ;; enabled, cat did not get set, so we have to do that.
+        ;; If FILE is not in Todo mode, set it now, which also sets
+       ;; CAT to the file's first category.
+       (unless (derived-mode-p 'todo-mode) (todo-mode))
+        ;; But if FILE was already in todo-mode and the item insertion
+       ;; command was invoked outside of a Todo mode buffer, the
+       ;; above calls to todo-current-category returned nil, so we
+       ;; have to explicitly set CAT to the current category.
        (unless cat
          (setq cat (todo-current-category)))
        (setq todo-current-todo-file file)
@@ -2169,7 +2171,9 @@ the item at point."
                  (if comment-delete
                      (when (todo-y-or-n-p "Delete comment? ")
                        (delete-region (match-beginning 0) (match-end 0)))
-                   (replace-match (read-string prompt (cons (match-string 1) 1))
+                   (replace-match (save-match-data
+                                     (read-string prompt
+                                                  (cons (match-string 1) 1)))
                                   nil nil nil 1))
                (if comment-delete
                    (user-error "There is no comment to delete")
@@ -2348,25 +2352,35 @@ made in the number or names of categories."
                            ((or (string= omonth "*") (= mm 13))
                             (user-error "Cannot increment *"))
                            (t
-                            (let ((mminc (+ mm inc (if (< inc 0) 12 0))))
-                              ;; Increment or decrement month by INC
-                              ;; modulo 12.
-                              (setq mm (% mminc 12))
-                              ;; If result is 0, make month December.
-                              (setq mm (if (= mm 0) 12 (abs mm)))
+                            (let* ((mmo mm)
+                                    ;; Change by 12 or more months?
+                                    (bigincp (>= (abs inc) 12))
+                                    ;; Month number is in range 1..12.
+                                    (mminc (+ mm (% inc 12)))
+                                   (mm (% (+ mminc 12) 12))
+                                   ;; 12n mod 12 = 0, so 0 is December.
+                                   (mm (if (= mm 0) 12 mm))
+                                    ;; Does change in month cross year?
+                                    (mmcmp (cond ((< inc 0) (> mm mmo))
+                                                 ((> inc 0) (< mm mmo))))
+                                    (yyadjust (if bigincp
+                                                  (+ (abs (/ inc 12))
+                                                     (if mmcmp 1 0))
+                                                1)))
                               ;; Adjust year if necessary.
-                              (setq year (or (and (cond ((> mminc 12)
-                                                         (+ yy (/ mminc 12)))
-                                                        ((< mminc 1)
-                                                         (- yy (/ mminc 12) 1))
-                                                        (t yy))
-                                                  (number-to-string yy))
-                                             oyear)))
-                            ;; Return the changed numerical month as
-                            ;; a string or the corresponding month name.
-                            (if omonth
-                                (number-to-string mm)
-                              (aref tma-array (1- mm))))))
+                               (setq yy (cond ((and (< inc 0)
+                                                    (or mmcmp bigincp))
+                                               (- yy yyadjust))
+                                              ((and (> inc 0)
+                                                    (or mmcmp bigincp))
+                                               (+ yy yyadjust))
+                                              (t yy)))
+                               (setq year (number-to-string yy))
+                              ;; Return the changed numerical month as
+                              ;; a string or the corresponding month name.
+                              (if omonth
+                                  (number-to-string mm)
+                                (aref tma-array (1- mm)))))))
                 ;; Since the number corresponding to the arbitrary
                 ;; month name "*" is out of the range of
                 ;; calendar-last-day-of-month, set it to 1
@@ -5923,8 +5937,15 @@ categories from `todo-category-completions-files'."
                       (todo-absolute-file-name
                        (let ((files (mapcar #'todo-short-file-name catfil)))
                          (completing-read (format str cat) files)))))))
-      ;; Default to the current file.
-      (unless file0 (setq file0 todo-current-todo-file))
+      ;; When called without arg FILE, use fallback todo file.
+      (unless file0 (setq file0 (or todo-current-todo-file
+                                    ;; If we're outside of todo-mode
+                                    ;; but there is a current todo
+                                    ;; file, use it.
+                                    todo-global-current-todo-file
+                                    ;; Else, use the default todo file.
+                                    (todo-absolute-file-name
+                                    todo-default-todo-file))))
       ;; First validate only a name passed interactively from
       ;; todo-add-category, which must be of a nonexistent category.
       (unless (and (assoc cat categories) (not add))
index 598d487cad9f122de0f87a4c623aa73b8450b6ab..557134fd4542d3e71df4582c70359f91d0cbdd52 100644 (file)
@@ -1,4 +1,4 @@
-(("testcat1" . [2 0 2 1]) ("testcat2" . [3 0 1 1]) ("testcat3" . [0 0 0 0]))
+(("testcat1" . [2 0 2 1]) ("testcat2" . [3 0 1 1]) ("testcat3" . [0 0 0 0]) ("testcat4" . [1 0 0 0]))
 --==-- testcat1
 [May 29, 2017] testcat1 item3
                has more than one line
@@ -18,3 +18,7 @@
 --==-- testcat3
 
 ==--== DONE 
+--==-- testcat4
+[Jan 1, 2020] testcat4 item1
+
+==--== DONE 
index d65f94d4f31a7ba48a902ba0e55432e17f20ca62..a19612ee562a64aa422a5154f6f603acf14c0c50 100644 (file)
@@ -848,6 +848,52 @@ should display the previously current (or default) todo file."
      (should (equal todo-current-todo-file todo-test-file-1))
      (delete-file (concat file "~")))))
 
+(ert-deftest todo-test-edit-item-date-month ()
+  "Test incrementing and decrementing the month of an item's date.
+If the change in month crosses a year boundary, the year of the
+item's date should be adjusted accordingly."
+  (with-todo-test
+   (todo-test--show 4)
+   (let ((current-prefix-arg t)         ; For todo-edit-item--header.
+         (get-date (lambda ()
+                     (save-excursion
+                       (todo-date-string-matcher (line-end-position))
+                       (buffer-substring-no-properties (match-beginning 1)
+                                                       (match-end 0))))))
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 0)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 1)
+     (should (equal (funcall get-date) "Feb 1, 2020"))
+     (todo-edit-item--header 'month -1)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month -1)
+     (should (equal (funcall get-date) "Dec 1, 2019"))
+     (todo-edit-item--header 'month 1)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 12)
+     (should (equal (funcall get-date) "Jan 1, 2021"))
+     (todo-edit-item--header 'month -12)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month -13)
+     (should (equal (funcall get-date) "Dec 1, 2018"))
+     (todo-edit-item--header 'month 7)
+     (should (equal (funcall get-date) "Jul 1, 2019"))
+     (todo-edit-item--header 'month 6)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 23)
+     (should (equal (funcall get-date) "Dec 1, 2021"))
+     (todo-edit-item--header 'month -23)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 24)
+     (should (equal (funcall get-date) "Jan 1, 2022"))
+     (todo-edit-item--header 'month -24)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     (todo-edit-item--header 'month 25)
+     (should (equal (funcall get-date) "Feb 1, 2022"))
+     (todo-edit-item--header 'month -25)
+     (should (equal (funcall get-date) "Jan 1, 2020"))
+     )))
 
 (provide 'todo-mode-tests)
 ;;; todo-mode-tests.el ends here