aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorStephen Berman2018-08-01 14:42:57 +0200
committerStephen Berman2018-08-01 14:42:57 +0200
commit22d463ed5ca262e1d8893b115c3f1237485fc7e0 (patch)
tree4dfed30b619e33c73f054dcd0075035b8a3d30fe /lisp
parentcabe9e5126bfed05643d595589031cce8a404255 (diff)
downloademacs-22d463ed5ca262e1d8893b115c3f1237485fc7e0.tar.gz
emacs-22d463ed5ca262e1d8893b115c3f1237485fc7e0.zip
Fix todo-mode commands called on done items separator
The done items separator is not reachable by todo-mode navigation commands, but it is e.g. by C-n and C-p. Ensure that invoking todo-mode commands with point on the separator does not result in unexpected results, errors or file corruption (bug#32343). * lisp/calendar/todo-mode.el (todo-insert-item--basic): Make copying item and inserting item "here" noops when invoked on done items separator. Consolidate error handling of these cases. Also restrict "here" insertion to valid positions in the current category, since this is simpler than the previous behavior of inserting as the first item, which was moreover undocumented, counterintuitive and superfluous. (todo-set-item-priority, todo-move-item, todo-item-done) (todo-item-start, todo-item-end): Make noops when invoked on done items separator. * test/lisp/calendar/todo-mode-tests.el: Require ert-x. (todo-test--insert-item): Add formal parameters of todo-insert-item--basic. (todo-test--done-items-separator): New function. (todo-test-done-items-separator01-bol) (todo-test-done-items-separator01-eol) (todo-test-done-items-separator02-bol) (todo-test-done-items-separator02-eol) (todo-test-done-items-separator03-bol) (todo-test-done-items-separator03-eol) (todo-test-done-items-separator04-bol) (todo-test-done-items-separator04-eol) (todo-test-done-items-separator05-bol) (todo-test-done-items-separator05-eol) (todo-test-done-items-separator06-bol) (todo-test-done-items-separator06-eol) (todo-test-done-items-separator07): New tests.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/calendar/todo-mode.el81
1 files changed, 42 insertions, 39 deletions
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 5161ae8d668..80bea25acd8 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -1860,15 +1860,18 @@ their associated keys and their effects."
1860 (region (eq where 'region)) 1860 (region (eq where 'region))
1861 (here (eq where 'here)) 1861 (here (eq where 'here))
1862 diary-item) 1862 diary-item)
1863 (when copy 1863 (when (and arg here)
1864 (cond 1864 (user-error "Here insertion only valid in current category"))
1865 ((not (eq major-mode 'todo-mode)) 1865 (when (and (or copy here)
1866 (user-error "You must be in Todo mode to copy a todo item")) 1866 (or (not (eq major-mode 'todo-mode)) (todo-done-item-p)
1867 ((todo-done-item-p) 1867 (when copy (looking-at "^$"))
1868 (user-error "You cannot copy a done item as a new todo item")) 1868 (save-excursion
1869 ((looking-at "^$") 1869 (beginning-of-line)
1870 (user-error "Point must be on a todo item to copy it"))) 1870 ;; Point is on done items separator.
1871 (setq diary-item (todo-diary-item-p))) 1871 (looking-at todo-category-done))))
1872 (user-error (concat "Item " (if copy "copying" "insertion")
1873 " is not valid here")))
1874 (when copy (setq diary-item (todo-diary-item-p)))
1872 (when region 1875 (when region
1873 (let (use-empty-active-region) 1876 (let (use-empty-active-region)
1874 (unless (and todo-use-only-highlighted-region (use-region-p)) 1877 (unless (and todo-use-only-highlighted-region (use-region-p))
@@ -1876,7 +1879,6 @@ their associated keys and their effects."
1876 (let* ((obuf (current-buffer)) 1879 (let* ((obuf (current-buffer))
1877 (ocat (todo-current-category)) 1880 (ocat (todo-current-category))
1878 (opoint (point)) 1881 (opoint (point))
1879 (todo-mm (eq major-mode 'todo-mode))
1880 (cat+file (cond ((equal arg '(4)) 1882 (cat+file (cond ((equal arg '(4))
1881 (todo-read-category "Insert in category: ")) 1883 (todo-read-category "Insert in category: "))
1882 ((equal arg '(16)) 1884 ((equal arg '(16))
@@ -1931,7 +1933,6 @@ their associated keys and their effects."
1931 (unless todo-global-current-todo-file 1933 (unless todo-global-current-todo-file
1932 (setq todo-global-current-todo-file todo-current-todo-file)) 1934 (setq todo-global-current-todo-file todo-current-todo-file))
1933 (let ((buffer-read-only nil) 1935 (let ((buffer-read-only nil)
1934 (called-from-outside (not (and todo-mm (equal cat ocat))))
1935 done-only item-added) 1936 done-only item-added)
1936 (unless copy 1937 (unless copy
1937 (setq new-item 1938 (setq new-item
@@ -1955,14 +1956,8 @@ their associated keys and their effects."
1955 "\n\t" new-item nil nil 1))) 1956 "\n\t" new-item nil nil 1)))
1956 (unwind-protect 1957 (unwind-protect
1957 (progn 1958 (progn
1958 ;; Make sure the correct category is selected. There 1959 ;; If we just visited the file, no category is selected yet.
1959 ;; are two cases: (i) we just visited the file, so no 1960 (when (= (- (point-max) (point-min)) (buffer-size))
1960 ;; category is selected yet, or (ii) we invoked
1961 ;; insertion "here" from outside the category we want
1962 ;; to insert in (with priority insertion, category
1963 ;; selection is done by todo-set-item-priority).
1964 (when (or (= (- (point-max) (point-min)) (buffer-size))
1965 (and here called-from-outside))
1966 (todo-category-number cat) 1961 (todo-category-number cat)
1967 (todo-category-select)) 1962 (todo-category-select))
1968 ;; If only done items are displayed in category, 1963 ;; If only done items are displayed in category,
@@ -1973,16 +1968,7 @@ their associated keys and their effects."
1973 (setq done-only t) 1968 (setq done-only t)
1974 (todo-toggle-view-done-only)) 1969 (todo-toggle-view-done-only))
1975 (if here 1970 (if here
1976 (progn 1971 (todo-insert-with-overlays new-item)
1977 ;; If command was invoked with point in done
1978 ;; items section or outside of the current
1979 ;; category, can't insert "here", so to be
1980 ;; useful give new item top priority.
1981 (when (or (todo-done-item-section-p)
1982 called-from-outside
1983 done-only)
1984 (goto-char (point-min)))
1985 (todo-insert-with-overlays new-item))
1986 (todo-set-item-priority new-item cat t)) 1972 (todo-set-item-priority new-item cat t))
1987 (setq item-added t)) 1973 (setq item-added t))
1988 ;; If user cancels before setting priority, restore 1974 ;; If user cancels before setting priority, restore
@@ -2549,7 +2535,11 @@ whose value can be either of the symbols `raise' or `lower',
2549meaning to raise or lower the item's priority by one." 2535meaning to raise or lower the item's priority by one."
2550 (interactive) 2536 (interactive)
2551 (unless (and (or (called-interactively-p 'any) (memq arg '(raise lower))) 2537 (unless (and (or (called-interactively-p 'any) (memq arg '(raise lower)))
2552 (or (todo-done-item-p) (looking-at "^$"))) 2538 ;; Noop if point is not on a todo (i.e. not done) item.
2539 (or (todo-done-item-p) (looking-at "^$")
2540 ;; On done items separator.
2541 (save-excursion (beginning-of-line)
2542 (looking-at todo-category-done))))
2553 (let* ((item (or item (todo-item-string))) 2543 (let* ((item (or item (todo-item-string)))
2554 (marked (todo-marked-item-p)) 2544 (marked (todo-marked-item-p))
2555 (cat (or cat (cond ((eq major-mode 'todo-mode) 2545 (cat (or cat (cond ((eq major-mode 'todo-mode)
@@ -2697,9 +2687,13 @@ section in the category moved to."
2697 (interactive "P") 2687 (interactive "P")
2698 (let* ((cat1 (todo-current-category)) 2688 (let* ((cat1 (todo-current-category))
2699 (marked (assoc cat1 todo-categories-with-marks))) 2689 (marked (assoc cat1 todo-categories-with-marks)))
2700 ;; Noop if point is not on an item and there are no marked items. 2690 (unless
2701 (unless (and (looking-at "^$") 2691 ;; Noop if point is not on an item and there are no marked items.
2702 (not marked)) 2692 (and (or (looking-at "^$")
2693 ;; On done items separator.
2694 (save-excursion (beginning-of-line)
2695 (looking-at todo-category-done)))
2696 (not marked))
2703 (let* ((buffer-read-only) 2697 (let* ((buffer-read-only)
2704 (file1 todo-current-todo-file) 2698 (file1 todo-current-todo-file)
2705 (item (todo-item-string)) 2699 (item (todo-item-string))
@@ -2856,10 +2850,14 @@ visible."
2856 (let* ((cat (todo-current-category)) 2850 (let* ((cat (todo-current-category))
2857 (marked (assoc cat todo-categories-with-marks))) 2851 (marked (assoc cat todo-categories-with-marks)))
2858 (when marked (todo--user-error-if-marked-done-item)) 2852 (when marked (todo--user-error-if-marked-done-item))
2859 (unless (and (not marked) 2853 (unless
2860 (or (todo-done-item-p) 2854 ;; Noop if point is not on a todo (i.e. not done) item and
2861 ;; Point is between todo and done items. 2855 ;; there are no marked items.
2862 (looking-at "^$"))) 2856 (and (or (todo-done-item-p) (looking-at "^$")
2857 ;; On done items separator.
2858 (save-excursion (beginning-of-line)
2859 (looking-at todo-category-done)))
2860 (not marked))
2863 (let* ((date-string (calendar-date-string (calendar-current-date) t t)) 2861 (let* ((date-string (calendar-date-string (calendar-current-date) t t))
2864 (time-string (if todo-always-add-time-string 2862 (time-string (if todo-always-add-time-string
2865 (concat " " (substring (current-time-string) 2863 (concat " " (substring (current-time-string)
@@ -5132,6 +5130,8 @@ but the categories sexp differs from the current value of
5132 (forward-line) 5130 (forward-line)
5133 (looking-at (concat "^" 5131 (looking-at (concat "^"
5134 (regexp-quote todo-category-done)))))) 5132 (regexp-quote todo-category-done))))))
5133 ;; Point is on done items separator.
5134 (save-excursion (beginning-of-line) (looking-at todo-category-done))
5135 ;; Buffer is widened. 5135 ;; Buffer is widened.
5136 (looking-at (regexp-quote todo-category-beg))) 5136 (looking-at (regexp-quote todo-category-beg)))
5137 (goto-char (line-beginning-position)) 5137 (goto-char (line-beginning-position))
@@ -5141,8 +5141,11 @@ but the categories sexp differs from the current value of
5141 5141
5142(defun todo-item-end () 5142(defun todo-item-end ()
5143 "Move to end of current todo item and return its position." 5143 "Move to end of current todo item and return its position."
5144 ;; Items cannot end with a blank line. 5144 (unless (or
5145 (unless (looking-at "^$") 5145 ;; Items cannot end with a blank line.
5146 (looking-at "^$")
5147 ;; Point is on done items separator.
5148 (save-excursion (beginning-of-line) (looking-at todo-category-done)))
5146 (let* ((done (todo-done-item-p)) 5149 (let* ((done (todo-done-item-p))
5147 (to-lim nil) 5150 (to-lim nil)
5148 ;; For todo items, end is before the done items section, for done 5151 ;; For todo items, end is before the done items section, for done