Fix several todo-mode.el editing bugs (bug#42976)
* 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.
This commit is contained in:
parent
3e10174fb6
commit
36bf4fa0b3
3 changed files with 98 additions and 27 deletions
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue