aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Berman2014-07-25 18:01:05 +0200
committerStephen Berman2014-07-25 18:01:05 +0200
commit6dd006a86d401a494efd48a31c5fe6e511e42b52 (patch)
tree643fc3b59f8b90fc7d8de4a766b10b1d842f8f19
parentc509a535a86acc8efc13df4d379ec09ef3659287 (diff)
downloademacs-6dd006a86d401a494efd48a31c5fe6e511e42b52.tar.gz
emacs-6dd006a86d401a494efd48a31c5fe6e511e42b52.zip
Fix code and doc involving marked items.
* todo-mode.texi (Marked Items): Correct omission of item deletion from commands applying to both todo and done items. * calendar/todo-mode.el: Fix handling of marked items and make minor code improvements. (todo-edit-item): If there are marked items, ensure user can only invoke editing commands that work with marked items. (todo-edit-item--text): When there are marked items, make it a noop if invoked with point not on an item; otherwise, ensure it applies only to item at point. (todo-item-undone): If there are marked not-done items, return point to its original position before signaling user error. (todo--user-error-if-marked-done-item): New function. (todo-edit-item--header, todo-edit-item--diary-inclusion) (todo-item-done): Use it.
-rw-r--r--doc/misc/ChangeLog5
-rw-r--r--doc/misc/todo-mode.texi9
-rw-r--r--lisp/ChangeLog15
-rw-r--r--lisp/calendar/todo-mode.el293
4 files changed, 182 insertions, 140 deletions
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog
index 84dea26ca32..0ad35d3803a 100644
--- a/doc/misc/ChangeLog
+++ b/doc/misc/ChangeLog
@@ -1,3 +1,8 @@
12014-07-25 Stephen Berman <stephen.berman@gmx.net>
2
3 * todo-mode.texi (Marked Items): Correct omission of item deletion
4 from commands applying to both todo and done items.
5
12014-07-04 Stephen Berman <stephen.berman@gmx.net> 62014-07-04 Stephen Berman <stephen.berman@gmx.net>
2 7
3 * todo-mode.texi (Levels of Organization): Comment out statement 8 * todo-mode.texi (Levels of Organization): Comment out statement
diff --git a/doc/misc/todo-mode.texi b/doc/misc/todo-mode.texi
index 092137268f7..9b0ec6e85a3 100644
--- a/doc/misc/todo-mode.texi
+++ b/doc/misc/todo-mode.texi
@@ -1323,10 +1323,11 @@ If you use @kbd{m}, @kbd{d}, @kbd{A d} or @kbd{u} on multiple
1323noncontiguous marked items, the relocated items retain their relative 1323noncontiguous marked items, the relocated items retain their relative
1324order but are now listed consecutively en bloc. 1324order but are now listed consecutively en bloc.
1325 1325
1326You can mark both todo and done items, but note that only @kbd{m} can apply 1326You can mark both todo and done items, but note that only @kbd{m} and
1327to both; other commands only affect either marked todo or marked done 1327@kbd{k} can apply to both; other commands only affect either marked
1328items, so if both types of items are marked, invoking these commands 1328todo or marked done items, so if both types of items are marked,
1329has no effect and informs you of your erroneous attempt. 1329invoking these commands has no effect and informs you of your
1330erroneous attempt.
1330 1331
1331@node Todo Categories Mode, Searching for Items, Marked Items, Top 1332@node Todo Categories Mode, Searching for Items, Marked Items, Top
1332@chapter Todo Categories Mode 1333@chapter Todo Categories Mode
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index c2bdbdebab6..7869bee211c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,18 @@
12014-07-25 Stephen Berman <stephen.berman@gmx.net>
2
3 * calendar/todo-mode.el: Fix handling of marked items and make
4 minor code improvements.
5 (todo-edit-item): If there are marked items, ensure user can only
6 invoke editing commands that work with marked items.
7 (todo-edit-item--text): When there are marked items, make it a
8 noop if invoked with point not on an item; otherwise, ensure it
9 applies only to item at point.
10 (todo-item-undone): If there are marked not-done items, return
11 point to its original position before signaling user error.
12 (todo--user-error-if-marked-done-item): New function.
13 (todo-edit-item--header, todo-edit-item--diary-inclusion)
14 (todo-item-done): Use it.
15
12014-07-25 Glenn Morris <rgm@gnu.org> 162014-07-25 Glenn Morris <rgm@gnu.org>
2 17
3 * files.el (toggle-read-only): Re-add basic doc-string. 18 * files.el (toggle-read-only): Re-add basic doc-string.
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index e5f486a2056..60f798792d1 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -2068,85 +2068,101 @@ the item at point."
2068(defun todo-edit-item (&optional arg) 2068(defun todo-edit-item (&optional arg)
2069 "Choose an editing operation for the current item and carry it out." 2069 "Choose an editing operation for the current item and carry it out."
2070 (interactive "P") 2070 (interactive "P")
2071 (cond ((todo-done-item-p) 2071 (let ((marked (assoc (todo-current-category) todo-categories-with-marks)))
2072 (todo-edit-item--next-key todo-edit-done-item--param-key-alist)) 2072 (cond ((and (todo-done-item-p) (not marked))
2073 ((todo-item-string) 2073 (todo-edit-item--next-key todo-edit-done-item--param-key-alist))
2074 (todo-edit-item--next-key todo-edit-item--param-key-alist arg)))) 2074 ((or marked (todo-item-string))
2075 (todo-edit-item--next-key todo-edit-item--param-key-alist arg)))))
2075 2076
2076(defun todo-edit-item--text (&optional arg) 2077(defun todo-edit-item--text (&optional arg)
2077 "Function providing the text editing facilities of `todo-edit-item'." 2078 "Function providing the text editing facilities of `todo-edit-item'."
2078 (let* ((opoint (point)) 2079 (let ((full-item (todo-item-string)))
2079 (start (todo-item-start)) 2080 ;; If there are marked items and user invokes a text-editing
2080 (end (save-excursion (todo-item-end))) 2081 ;; commands with point not on an item, todo-item-start is nil and
2081 (item-beg (progn 2082 ;; 1+ signals an error, so just make this a noop.
2082 (re-search-forward 2083 (when full-item
2083 (concat todo-date-string-start todo-date-pattern 2084 (let* ((opoint (point))
2084 "\\( " diary-time-regexp "\\)?" 2085 (start (todo-item-start))
2085 (regexp-quote todo-nondiary-end) "?") 2086 (end (save-excursion (todo-item-end)))
2086 (line-end-position) t) 2087 (item-beg (progn
2087 (1+ (- (point) start)))) 2088 (re-search-forward
2088 (include-header (eq arg 'include-header)) 2089 (concat todo-date-string-start todo-date-pattern
2089 (comment-edit (eq arg 'comment-edit)) 2090 "\\( " diary-time-regexp "\\)?"
2090 (comment-delete (eq arg 'comment-delete)) 2091 (regexp-quote todo-nondiary-end) "?")
2091 (header-string (substring (todo-item-string) 0 item-beg)) 2092 (line-end-position) t)
2092 (item (if (or include-header comment-edit comment-delete) 2093 (1+ (- (point) start))))
2093 (todo-item-string) 2094 (include-header (eq arg 'include-header))
2094 (substring (todo-item-string) item-beg))) 2095 (comment-edit (eq arg 'comment-edit))
2095 (multiline (> (length (split-string item "\n")) 1)) 2096 (comment-delete (eq arg 'comment-delete))
2096 (comment (save-excursion 2097 (header-string (substring full-item 0 item-beg))
2097 (todo-item-start) 2098 (item (if (or include-header comment-edit comment-delete)
2098 (re-search-forward 2099 full-item
2099 (concat " \\[" (regexp-quote todo-comment-string) 2100 (substring full-item item-beg)))
2100 ": \\([^]]+\\)\\]") end t))) 2101 (multiline (or (eq arg 'multiline)
2101 (prompt (if comment "Edit comment: " "Enter a comment: ")) 2102 (> (length (split-string item "\n")) 1)))
2102 (buffer-read-only nil)) 2103 (comment (save-excursion
2103 (cond 2104 (todo-item-start)
2104 ((or comment-edit comment-delete) 2105 (re-search-forward
2105 (save-excursion 2106 (concat " \\[" (regexp-quote todo-comment-string)
2106 (todo-item-start) 2107 ": \\([^]]+\\)\\]") end t)))
2107 (if (re-search-forward (concat " \\[" (regexp-quote todo-comment-string) 2108 (prompt (if comment "Edit comment: " "Enter a comment: "))
2108 ": \\([^]]+\\)\\]") end t) 2109 (buffer-read-only nil))
2109 (if comment-delete 2110 ;; When there are marked items, user can invoke todo-edit-item
2110 (when (todo-y-or-n-p "Delete comment? ") 2111 ;; even if point is not on an item, but text editing only
2111 (delete-region (match-beginning 0) (match-end 0))) 2112 ;; applies to the item at point.
2112 (replace-match (read-string prompt (cons (match-string 1) 1)) 2113 (when (or (and (todo-done-item-p)
2113 nil nil nil 1)) 2114 (or comment-edit comment-delete))
2114 (if comment-delete 2115 (and (not (todo-done-item-p))
2115 (user-error "There is no comment to delete") 2116 (or (not arg) include-header multiline)))
2116 (insert " [" todo-comment-string ": " 2117 (cond
2117 (prog1 (read-string prompt) 2118 ((or comment-edit comment-delete)
2118 ;; If user moved point during editing, 2119 (save-excursion
2119 ;; make sure it moves back. 2120 (todo-item-start)
2120 (goto-char opoint) 2121 (if (re-search-forward (concat " \\["
2121 (todo-item-end)) 2122 (regexp-quote todo-comment-string)
2122 "]"))))) 2123 ": \\([^]]+\\)\\]") end t)
2123 ((or multiline (eq arg 'multiline)) 2124 (if comment-delete
2124 (let ((buf todo-edit-buffer)) 2125 (when (todo-y-or-n-p "Delete comment? ")
2125 (set-window-buffer (selected-window) 2126 (delete-region (match-beginning 0) (match-end 0)))
2126 (set-buffer (make-indirect-buffer (buffer-name) buf))) 2127 (replace-match (read-string prompt (cons (match-string 1) 1))
2127 (narrow-to-region (todo-item-start) (todo-item-end)) 2128 nil nil nil 1))
2128 (todo-edit-mode) 2129 (if comment-delete
2129 (message "%s" (substitute-command-keys 2130 (user-error "There is no comment to delete")
2130 (concat "Type \\[todo-edit-quit] " 2131 (insert " [" todo-comment-string ": "
2131 "to return to Todo mode.\n"))))) 2132 (prog1 (read-string prompt)
2132 (t 2133 ;; If user moved point during editing,
2133 (let ((new (concat (if include-header "" header-string) 2134 ;; make sure it moves back.
2134 (read-string "Edit: " (if include-header 2135 (goto-char opoint)
2135 (cons item item-beg) 2136 (todo-item-end))
2136 (cons item 0)))))) 2137 "]")))))
2137 (when include-header 2138 (multiline
2138 (while (not (string-match (concat todo-date-string-start 2139 (let ((buf todo-edit-buffer))
2139 todo-date-pattern) new)) 2140 (set-window-buffer (selected-window)
2140 (setq new (read-from-minibuffer 2141 (set-buffer (make-indirect-buffer
2141 "Item must start with a date: " new)))) 2142 (buffer-name) buf)))
2142 ;; Ensure lines following hard newlines are indented. 2143 (narrow-to-region (todo-item-start) (todo-item-end))
2143 (setq new (replace-regexp-in-string "\\(\n\\)[^[:blank:]]" 2144 (todo-edit-mode)
2144 "\n\t" new nil nil 1)) 2145 (message "%s" (substitute-command-keys
2145 ;; If user moved point during editing, make sure it moves back. 2146 (concat "Type \\[todo-edit-quit] "
2146 (goto-char opoint) 2147 "to return to Todo mode.\n")))))
2147 (todo-remove-item) 2148 (t
2148 (todo-insert-with-overlays new) 2149 (let ((new (concat (if include-header "" header-string)
2149 (move-to-column item-beg)))))) 2150 (read-string "Edit: " (if include-header
2151 (cons item item-beg)
2152 (cons item 0))))))
2153 (when include-header
2154 (while (not (string-match (concat todo-date-string-start
2155 todo-date-pattern) new))
2156 (setq new (read-from-minibuffer
2157 "Item must start with a date: " new))))
2158 ;; Ensure lines following hard newlines are indented.
2159 (setq new (replace-regexp-in-string "\\(\n\\)[^[:blank:]]"
2160 "\n\t" new nil nil 1))
2161 ;; If user moved point during editing, make sure it moves back.
2162 (goto-char opoint)
2163 (todo-remove-item)
2164 (todo-insert-with-overlays new)
2165 (move-to-column item-beg)))))))))
2150 2166
2151(defun todo-edit-quit () 2167(defun todo-edit-quit ()
2152 "Return from Todo Edit mode to Todo mode. 2168 "Return from Todo Edit mode to Todo mode.
@@ -2201,16 +2217,16 @@ made in the number or names of categories."
2201 2217
2202(defun todo-edit-item--header (what &optional inc) 2218(defun todo-edit-item--header (what &optional inc)
2203 "Function providing header editing facilities of `todo-edit-item'." 2219 "Function providing header editing facilities of `todo-edit-item'."
2204 (let* ((cat (todo-current-category)) 2220 (let ((marked (assoc (todo-current-category) todo-categories-with-marks))
2205 (marked (assoc cat todo-categories-with-marks)) 2221 (first t)
2206 (first t) 2222 (todo-date-from-calendar t)
2207 (todo-date-from-calendar t) 2223 ;; INC must be an integer, but users could pass it via
2208 ;; INC must be an integer, but users could pass it via 2224 ;; `todo-edit-item' as e.g. `-' or `C-u'.
2209 ;; `todo-edit-item' as e.g. `-' or `C-u'. 2225 (inc (prefix-numeric-value inc))
2210 (inc (prefix-numeric-value inc)) 2226 (buffer-read-only nil)
2211 (buffer-read-only nil) 2227 ndate ntime year monthname month day
2212 ndate ntime year monthname month day 2228 dayname) ; Needed by calendar-date-display-form.
2213 dayname) ; Needed by calendar-date-display-form. 2229 (when marked (todo--user-error-if-marked-done-item))
2214 (save-excursion 2230 (save-excursion
2215 (or (and marked (goto-char (point-min))) (todo-item-start)) 2231 (or (and marked (goto-char (point-min))) (todo-item-start))
2216 (catch 'end 2232 (catch 'end
@@ -2372,47 +2388,45 @@ made in the number or names of categories."
2372(defun todo-edit-item--diary-inclusion (&optional nonmarking) 2388(defun todo-edit-item--diary-inclusion (&optional nonmarking)
2373 "Function providing diary marking facilities of `todo-edit-item'." 2389 "Function providing diary marking facilities of `todo-edit-item'."
2374 (let ((buffer-read-only) 2390 (let ((buffer-read-only)
2375 (marked (assoc (todo-current-category) 2391 (marked (assoc (todo-current-category) todo-categories-with-marks)))
2376 todo-categories-with-marks))) 2392 (when marked (todo--user-error-if-marked-done-item))
2377 (catch 'stop 2393 (catch 'stop
2378 (save-excursion 2394 (save-excursion
2379 (when marked (goto-char (point-min))) 2395 (when marked (goto-char (point-min)))
2380 (while (not (eobp)) 2396 (while (not (eobp))
2381 (if (todo-done-item-p) 2397 (unless (and marked (not (todo-marked-item-p)))
2382 (throw 'stop (message "Done items cannot be edited")) 2398 (let* ((beg (todo-item-start))
2383 (unless (and marked (not (todo-marked-item-p))) 2399 (lim (save-excursion (todo-item-end)))
2384 (let* ((beg (todo-item-start)) 2400 (end (save-excursion
2385 (lim (save-excursion (todo-item-end))) 2401 (or (todo-time-string-matcher lim)
2386 (end (save-excursion 2402 (todo-date-string-matcher lim)))))
2387 (or (todo-time-string-matcher lim) 2403 (if nonmarking
2388 (todo-date-string-matcher lim))))) 2404 (if (looking-at (regexp-quote diary-nonmarking-symbol))
2389 (if nonmarking 2405 (replace-match "")
2390 (if (looking-at (regexp-quote diary-nonmarking-symbol)) 2406 (when (looking-at (regexp-quote todo-nondiary-start))
2391 (replace-match "") 2407 (save-excursion
2392 (when (looking-at (regexp-quote todo-nondiary-start))
2393 (save-excursion
2394 (replace-match "")
2395 (search-forward todo-nondiary-end (1+ end) t)
2396 (replace-match "")
2397 (todo-update-count 'diary 1)))
2398 (insert diary-nonmarking-symbol))
2399 (if (looking-at (regexp-quote todo-nondiary-start))
2400 (progn
2401 (replace-match "") 2408 (replace-match "")
2402 (search-forward todo-nondiary-end (1+ end) t) 2409 (search-forward todo-nondiary-end (1+ end) t)
2403 (replace-match "") 2410 (replace-match "")
2404 (todo-update-count 'diary 1)) 2411 (todo-update-count 'diary 1)))
2405 (when end 2412 (insert diary-nonmarking-symbol))
2406 (when (looking-at (regexp-quote diary-nonmarking-symbol)) 2413 (if (looking-at (regexp-quote todo-nondiary-start))
2407 (replace-match "") 2414 (progn
2408 (setq end (1- end))) ; Since we deleted nonmarking symbol. 2415 (replace-match "")
2409 (insert todo-nondiary-start) 2416 (search-forward todo-nondiary-end (1+ end) t)
2410 (goto-char (1+ end)) 2417 (replace-match "")
2411 (insert todo-nondiary-end) 2418 (todo-update-count 'diary 1))
2412 (todo-update-count 'diary -1)))))) 2419 (when end
2413 (unless marked (throw 'stop nil)) 2420 (when (looking-at (regexp-quote diary-nonmarking-symbol))
2414 (todo-forward-item))))) 2421 (replace-match "")
2415 (todo-update-categories-sexp))) 2422 (setq end (1- end))) ; Since we deleted nonmarking symbol.
2423 (insert todo-nondiary-start)
2424 (goto-char (1+ end))
2425 (insert todo-nondiary-end)
2426 (todo-update-count 'diary -1))))))
2427 (unless marked (throw 'stop nil))
2428 (todo-forward-item)))))
2429 (todo-update-categories-sexp))
2416 2430
2417(defun todo-edit-category-diary-inclusion (arg) 2431(defun todo-edit-category-diary-inclusion (arg)
2418 "Make all items in this category diary items. 2432 "Make all items in this category diary items.
@@ -2783,21 +2797,7 @@ visible."
2783 (interactive "P") 2797 (interactive "P")
2784 (let* ((cat (todo-current-category)) 2798 (let* ((cat (todo-current-category))
2785 (marked (assoc cat todo-categories-with-marks))) 2799 (marked (assoc cat todo-categories-with-marks)))
2786 (when marked 2800 (when marked (todo--user-error-if-marked-done-item))
2787 (save-excursion
2788 (save-restriction
2789 (goto-char (point-max))
2790 (todo-backward-item)
2791 (unless (todo-done-item-p)
2792 (widen)
2793 (unless (re-search-forward
2794 (concat "^" (regexp-quote todo-category-beg)) nil t)
2795 (goto-char (point-max)))
2796 (forward-line -1))
2797 (while (todo-done-item-p)
2798 (when (todo-marked-item-p)
2799 (user-error "This command does not apply to done items"))
2800 (todo-backward-item)))))
2801 (unless (and (not marked) 2801 (unless (and (not marked)
2802 (or (todo-done-item-p) 2802 (or (todo-done-item-p)
2803 ;; Point is between todo and done items. 2803 ;; Point is between todo and done items.
@@ -2885,7 +2885,9 @@ comments without asking."
2885 (while (not (eobp)) 2885 (while (not (eobp))
2886 (when (or (not marked) (and marked (todo-marked-item-p))) 2886 (when (or (not marked) (and marked (todo-marked-item-p)))
2887 (if (not (todo-done-item-p)) 2887 (if (not (todo-done-item-p))
2888 (user-error "Only done items can be undone") 2888 (progn
2889 (goto-char opoint)
2890 (user-error "Only done items can be undone"))
2889 (todo-item-start) 2891 (todo-item-start)
2890 (unless marked 2892 (unless marked
2891 (setq ov (make-overlay (save-excursion (todo-item-start)) 2893 (setq ov (make-overlay (save-excursion (todo-item-start))
@@ -5222,6 +5224,25 @@ Overrides `diary-goto-entry'."
5222 (progn (goto-char (point-min)) 5224 (progn (goto-char (point-min))
5223 (looking-at todo-done-string-start))))) 5225 (looking-at todo-done-string-start)))))
5224 5226
5227(defun todo--user-error-if-marked-done-item ()
5228 "Signal user error on marked done items.
5229Helper funtion for editing commands that only apply to (possibly
5230marked) not done todo items."
5231 (save-excursion
5232 (save-restriction
5233 (goto-char (point-max))
5234 (todo-backward-item)
5235 (unless (todo-done-item-p)
5236 (widen)
5237 (unless (re-search-forward
5238 (concat "^" (regexp-quote todo-category-beg)) nil t)
5239 (goto-char (point-max)))
5240 (forward-line -1))
5241 (while (todo-done-item-p)
5242 (when (todo-marked-item-p)
5243 (user-error "This command does not apply to done items"))
5244 (todo-backward-item)))))
5245
5225(defun todo-reset-done-separator (sep) 5246(defun todo-reset-done-separator (sep)
5226 "Replace existing overlays of done items separator string SEP." 5247 "Replace existing overlays of done items separator string SEP."
5227 (save-excursion 5248 (save-excursion