diff options
| author | Stephen Berman | 2018-08-01 14:42:57 +0200 |
|---|---|---|
| committer | Stephen Berman | 2018-08-01 14:42:57 +0200 |
| commit | 22d463ed5ca262e1d8893b115c3f1237485fc7e0 (patch) | |
| tree | 4dfed30b619e33c73f054dcd0075035b8a3d30fe /lisp | |
| parent | cabe9e5126bfed05643d595589031cce8a404255 (diff) | |
| download | emacs-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.el | 81 |
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', | |||
| 2549 | meaning to raise or lower the item's priority by one." | 2535 | meaning 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 |