aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Berman2013-02-08 00:38:36 +0100
committerStephen Berman2013-02-08 00:38:36 +0100
commit0ad8680abcd1007c2306e32bf729346cfb15440e (patch)
tree9b5b71c07b8404e01adcec8b011ce8749883a536
parent82a9ac454a9361edd0a1a6ce4aea9db16b51fc61 (diff)
downloademacs-0ad8680abcd1007c2306e32bf729346cfb15440e.tar.gz
emacs-0ad8680abcd1007c2306e32bf729346cfb15440e.zip
* calendar/todos.el: Bug fixes and improvements to item editing
and insertion. (todos-check-format): Compare current value of todos-categories with actual categories sexp. (todos-repair-categories-sexp): Add warning to doc string about category order getting restored to list element order. (todos-mode-external-set): When todos-categories is nil, as in Todos Edit mode, set it by reading actual categories sexp. (todos-edit-mode): Make buffer writeable. (todos-done-item-section-p): New function. (todos-insert-item): Use it as part of preventing insertion here in done items section. Move check for display of done items only to just before setting new item's priority, and if cancelled after toggling to todo items, restore display of done items. (todos-edit-multiline-item): Don't base on todos-edit-multiline but just narrow and change mode. (todos-edit-multiline): Don't make indirect buffer but just widen and change mode; also remove overlays. (todos-edit-quit): Restore Todos mode and category display; when quitting multiline item editing, ensure items above edited item are visible in window if possible. (todos-done-item-add-edit-or-delete-comment): If user moved point during editing, make sure it moves back to edited item before returning.
-rw-r--r--lisp/ChangeLog27
-rw-r--r--lisp/calendar/todos.el193
2 files changed, 166 insertions, 54 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index ea640f11510..5c4f707d81f 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,30 @@
12013-02-07 Stephen Berman <stephen.berman@gmx.net>
2
3 * calendar/todos.el: Bug fixes and improvements to item editing
4 and insertion.
5 (todos-check-format): Compare current value of todos-categories
6 with actual categories sexp.
7 (todos-repair-categories-sexp): Add warning to doc string about
8 category order getting restored to list element order.
9 (todos-mode-external-set): When todos-categories is nil, as in
10 Todos Edit mode, set it by reading actual categories sexp.
11 (todos-edit-mode): Make buffer writeable.
12 (todos-done-item-section-p): New function.
13 (todos-insert-item): Use it as part of preventing insertion here
14 in done items section. Move check for display of done items only
15 to just before setting new item's priority, and if cancelled after
16 toggling to todo items, restore display of done items.
17 (todos-edit-multiline-item): Don't base on todos-edit-multiline
18 but just narrow and change mode.
19 (todos-edit-multiline): Don't make indirect buffer but just widen
20 and change mode; also remove overlays.
21 (todos-edit-quit): Restore Todos mode and category display; when
22 quitting multiline item editing, ensure items above edited item
23 are visible in window if possible.
24 (todos-done-item-add-edit-or-delete-comment): If user moved point
25 during editing, make sure it moves back to edited item before
26 returning.
27
12013-02-05 Stephen Berman <stephen.berman@gmx.net> 282013-02-05 Stephen Berman <stephen.berman@gmx.net>
2 29
3 * calendar/todos.el (todos-reset-done-separator-string): 30 * calendar/todos.el (todos-reset-done-separator-string):
diff --git a/lisp/calendar/todos.el b/lisp/calendar/todos.el
index 479d4c49377..ef05521937f 100644
--- a/lisp/calendar/todos.el
+++ b/lisp/calendar/todos.el
@@ -1094,9 +1094,11 @@ where the invalid formatting was found."
1094 (save-restriction 1094 (save-restriction
1095 (widen) 1095 (widen)
1096 (goto-char (point-min)) 1096 (goto-char (point-min))
1097 ;; Check for `todos-categories' sexp as the first line 1097 (let ((cats (prin1-to-string todos-categories))
1098 (let ((cats (prin1-to-string todos-categories))) 1098 (sexp (buffer-substring-no-properties (line-beginning-position)
1099 (unless (looking-at (regexp-quote cats)) 1099 (line-end-position))))
1100 ;; Check for `todos-categories' sexp as the first line
1101 (unless (string= sexp cats)
1100 (error "Invalid or missing todos-categories sexp"))) 1102 (error "Invalid or missing todos-categories sexp")))
1101 (forward-line) 1103 (forward-line)
1102 (let ((legit (concat "\\(^" (regexp-quote todos-category-beg) "\\)" 1104 (let ((legit (concat "\\(^" (regexp-quote todos-category-beg) "\\)"
@@ -1400,7 +1402,11 @@ the file."
1400(defun todos-repair-categories-sexp () 1402(defun todos-repair-categories-sexp ()
1401 "Repair corrupt Todos categories sexp. 1403 "Repair corrupt Todos categories sexp.
1402This should only be needed as a consequence of careless manual 1404This should only be needed as a consequence of careless manual
1403editing or a bug in todos.el." 1405editing or a bug in todos.el.
1406
1407*Warning*: Calling this command restores the category order to
1408the list element order in the Todos categories sexp, so any order
1409changes made in Todos Categories mode will have to be made again."
1404 (interactive) 1410 (interactive)
1405 (let ((todos-categories (todos-make-categories-list t))) 1411 (let ((todos-categories (todos-make-categories-list t)))
1406 (todos-update-categories-sexp))) 1412 (todos-update-categories-sexp)))
@@ -1531,13 +1537,13 @@ The final element is \"*\", indicating an unspecified month.")
1531 (todos-item-start) 1537 (todos-item-start)
1532 (looking-at todos-done-string-start))) 1538 (looking-at todos-done-string-start)))
1533 1539
1534;; (defun todos-done-item-section-p () 1540(defun todos-done-item-section-p ()
1535;; "Return non-nil if point is in category's done items section." 1541 "Return non-nil if point is in category's done items section."
1536;; (save-excursion 1542 (save-excursion
1537;; (or (re-search-backward (concat "^" (regexp-quote todos-category-done)) 1543 (or (re-search-backward (concat "^" (regexp-quote todos-category-done))
1538;; nil t) 1544 nil t)
1539;; (progn (goto-char (point-min)) 1545 (progn (goto-char (point-min))
1540;; (looking-at todos-done-string-start))))) 1546 (looking-at todos-done-string-start)))))
1541 1547
1542(defun todos-prefix-overlay () 1548(defun todos-prefix-overlay ()
1543 "Return this item's prefix overlay." 1549 "Return this item's prefix overlay."
@@ -2970,7 +2976,15 @@ which is the value of the user option
2970 ;; invocation of `todos-show', since there is then 2976 ;; invocation of `todos-show', since there is then
2971 ;; no buffer visiting the current file. 2977 ;; no buffer visiting the current file.
2972 (find-file-noselect todos-current-todos-file 'nowarn) 2978 (find-file-noselect todos-current-todos-file 'nowarn)
2973 todos-categories))) 2979 (or todos-categories
2980 ;; In Todos Edit mode todos-categories is now nil
2981 ;; since it uses same buffer as Todos mode but
2982 ;; doesn't have the latter's local variables.
2983 (save-excursion
2984 (goto-char (point-min))
2985 (read (buffer-substring-no-properties
2986 (line-beginning-position)
2987 (line-end-position))))))))
2974 (set (make-local-variable 'todos-categories) cats))) 2988 (set (make-local-variable 'todos-categories) cats)))
2975 2989
2976(define-derived-mode todos-edit-mode text-mode "Todos-Ed" 2990(define-derived-mode todos-edit-mode text-mode "Todos-Ed"
@@ -2978,7 +2992,8 @@ which is the value of the user option
2978 2992
2979\\{todos-edit-mode-map}" 2993\\{todos-edit-mode-map}"
2980 (todos-modes-set-1) 2994 (todos-modes-set-1)
2981 (todos-mode-external-set)) 2995 (todos-mode-external-set)
2996 (setq buffer-read-only nil))
2982 2997
2983(put 'todos-categories-mode 'mode-class 'special) 2998(put 'todos-categories-mode 'mode-class 'special)
2984 2999
@@ -4602,19 +4617,14 @@ the priority is not given by HERE but by prompting."
4602 ;; file's first category. 4617 ;; file's first category.
4603 (set-buffer (find-buffer-visiting file))) 4618 (set-buffer (find-buffer-visiting file)))
4604 (setq todos-current-todos-file file) 4619 (setq todos-current-todos-file file)
4605 ;; If only done items are displayed in category, toggle to
4606 ;; todo items.
4607 (save-excursion
4608 (when (and (goto-char (point-min))
4609 (looking-at todos-done-string-start))
4610 (todos-show-done-only)))
4611 (unless todos-global-current-todos-file 4620 (unless todos-global-current-todos-file
4612 (setq todos-global-current-todos-file todos-current-todos-file)) 4621 (setq todos-global-current-todos-file todos-current-todos-file))
4613 ;; These are not needed here, since they are called in 4622 ;; These are not needed here, since they are called in
4614 ;; todos-set-item-priority. 4623 ;; todos-set-item-priority.
4615 ;; (todos-category-number cat) 4624 ;; (todos-category-number cat)
4616 ;; (todos-category-select) 4625 ;; (todos-category-select)
4617 (let (buffer-read-only) 4626 (let ((buffer-read-only nil)
4627 done-only item-added)
4618 (setq new-item 4628 (setq new-item
4619 ;; Add date, time and diary marking as required. 4629 ;; Add date, time and diary marking as required.
4620 (concat (if (not (and diary (not todos-include-in-diary))) 4630 (concat (if (not (and diary (not todos-include-in-diary)))
@@ -4633,23 +4643,36 @@ the priority is not given by HERE but by prompting."
4633 (concat "\n" (make-string todos-indent-to-here 32)) 4643 (concat "\n" (make-string todos-indent-to-here 32))
4634 new-item nil nil 1)) 4644 new-item nil nil 1))
4635 (if here 4645 (if here
4636 (progn 4646 (if (or (todos-done-item-p) (todos-done-item-section-p))
4647 (error "Cannot insert item in done items section")
4637 (unless (and todos-mm (equal cat ocat)) 4648 (unless (and todos-mm (equal cat ocat))
4638 (todos-category-number cat) 4649 (todos-category-number cat)
4639 (todos-category-select) 4650 (todos-category-select)
4640 (goto-char (point-min))) 4651 (goto-char (point-min)))
4641 (todos-insert-with-overlays new-item)) 4652 (todos-insert-with-overlays new-item))
4642 (unwind-protect 4653 (unwind-protect
4643 (todos-set-item-priority new-item cat t) 4654 (progn
4644 ;; In (at least) two circumstances, point may be at eob 4655 ;; If only done items are displayed in category,
4645 ;; and eob at window-start, so that that the todo items 4656 ;; toggle to todo items.
4646 ;; are out of view: (i) if item is inserted at end of 4657 (when (and (goto-char (point-min))
4647 ;; category, (ii) if only done items are shown, this is 4658 (looking-at todos-done-string-start))
4648 ;; (above) programmatically toggled to show todo items, 4659 (setq done-only t)
4649 ;; and user cancels before setting new item's 4660 (todos-show-done-only))
4650 ;; priority. To make sure the todo items are displayed 4661 (todos-set-item-priority new-item cat t)
4651 ;; in the window, force recentering. 4662 (setq item-added t))
4652 (recenter))) 4663 ;; If user cancels before setting priority, restore
4664 ;; display.
4665 (unless item-added
4666 (and done-only (todos-show-done-only)))
4667 ;; If todos section is not visible when insertion
4668 ;; command is called (either because only done items
4669 ;; were shown or because category was not in current
4670 ;; buffer), then if item is inserted at end of category,
4671 ;; point is at eob and eob at window-start, so that that
4672 ;; higher priority todo items are out of view. So we
4673 ;; recenter to make sure the todo items are displayed in
4674 ;; the window.
4675 (when item-added (recenter))))
4653 (todos-update-count 'todo 1) 4676 (todos-update-count 'todo 1)
4654 (if (or diary todos-include-in-diary) (todos-update-count 'diary 1)) 4677 (if (or diary todos-include-in-diary) (todos-update-count 'diary 1))
4655 (todos-update-categories-sexp)))))) 4678 (todos-update-categories-sexp))))))
@@ -4790,29 +4813,77 @@ minibuffer; otherwise, edit it in Todos Edit mode."
4790 (todos-insert-with-overlays new) 4813 (todos-insert-with-overlays new)
4791 (move-to-column item-beg)))))) 4814 (move-to-column item-beg))))))
4792 4815
4816;; (defun todos-edit-multiline-item ()
4817;; "Edit current Todo item in Todos Edit mode.
4818;; Use of newlines invokes `todos-indent' to insure compliance with
4819;; the format of Diary entries."
4820;; (interactive)
4821;; (todos-edit-multiline t))
4822
4823;; (defun todos-edit-multiline (&optional item) ;FIXME: not item editing command
4824;; "" ;FIXME
4825;; (interactive)
4826;; (let ((buffer-name todos-edit-buffer))
4827;; (set-window-buffer
4828;; (selected-window)
4829;; (set-buffer (make-indirect-buffer
4830;; (file-name-nondirectory todos-current-todos-file)
4831;; buffer-name)))
4832;; (if item
4833;; (narrow-to-region (todos-item-start) (todos-item-end))
4834;; (widen))
4835;; (todos-edit-mode)
4836;; (message "%s" (substitute-command-keys
4837;; (concat "Type \\[todos-edit-quit] to check file format "
4838;; "validity and return to Todos mode.\n")))))
4839
4840;; (defun todos-edit-quit ()
4841;; "Return from Todos Edit mode to Todos mode.
4842;; If the item contains hard line breaks, make sure the following
4843;; lines are indented by `todos-indent-to-here' to conform to diary
4844;; format.
4845
4846;; If the whole file was in Todos Edit mode, check before returning
4847;; whether the file is still a valid Todos file and if so, also
4848;; recalculate the Todos categories sexp, in case changes were made
4849;; in the number or names of categories."
4850;; (interactive)
4851;; (if (eq (buffer-size) (- (point-max) (point-min)))
4852;; (when (todos-check-format)
4853;; (todos-repair-categories-sexp))
4854;; ;; Ensure lines following hard newlines are indented.
4855;; (let ((item (replace-regexp-in-string
4856;; "\\(\n\\)[^[:blank:]]"
4857;; (concat "\n" (make-string todos-indent-to-here 32))
4858;; (buffer-string) nil nil 1)))
4859;; (delete-region (point-min) (point-max))
4860;; (insert item)))
4861;; (kill-buffer)
4862;; ;; In case next buffer is not the one holding todos-current-todos-file.
4863;; (todos-show))
4864
4793(defun todos-edit-multiline-item () 4865(defun todos-edit-multiline-item ()
4794 "Edit current Todo item in Todos Edit mode. 4866 "Edit current Todo item in Todos Edit mode.
4795Use of newlines invokes `todos-indent' to insure compliance with 4867Use of newlines invokes `todos-indent' to insure compliance with
4796the format of Diary entries." 4868the format of Diary entries."
4797 (interactive) 4869 (interactive)
4798 (todos-edit-multiline t)) 4870 (narrow-to-region (todos-item-start) (todos-item-end))
4799 4871 (rename-buffer todos-edit-buffer)
4800(defun todos-edit-multiline (&optional item) 4872 (todos-edit-mode)
4801 "" 4873 (message "%s" (substitute-command-keys
4874 (concat "Type \\[todos-edit-quit] "
4875 "to return to Todos mode.\n"))))
4876
4877(defun todos-edit-multiline (&optional item) ;FIXME: not item editing command
4878 "" ;FIXME
4802 (interactive) 4879 (interactive)
4803 (let ((buffer-name todos-edit-buffer)) 4880 (widen)
4804 (set-window-buffer 4881 (rename-buffer todos-edit-buffer)
4805 (selected-window) 4882 (todos-edit-mode)
4806 (set-buffer (make-indirect-buffer 4883 (remove-overlays) ; nil nil 'before-string)
4807 (file-name-nondirectory todos-current-todos-file) 4884 (message "%s" (substitute-command-keys
4808 buffer-name))) 4885 (concat "Type \\[todos-edit-quit] to check file format "
4809 (if item 4886 "validity and return to Todos mode.\n"))))
4810 (narrow-to-region (todos-item-start) (todos-item-end))
4811 (widen))
4812 (todos-edit-mode)
4813 (message "%s" (substitute-command-keys
4814 (concat "Type \\[todos-edit-quit] to check file format "
4815 "validity and return to Todos mode.\n")))))
4816 4887
4817(defun todos-edit-quit () 4888(defun todos-edit-quit ()
4818 "Return from Todos Edit mode to Todos mode. 4889 "Return from Todos Edit mode to Todos mode.
@@ -4827,17 +4898,28 @@ in the number or names of categories."
4827 (interactive) 4898 (interactive)
4828 (if (eq (buffer-size) (- (point-max) (point-min))) 4899 (if (eq (buffer-size) (- (point-max) (point-min)))
4829 (when (todos-check-format) 4900 (when (todos-check-format)
4830 (todos-repair-categories-sexp)) 4901 ;; FIXME: separate out sexp check?
4902 ;; If manual editing makes e.g. item counts change, have to
4903 ;; call this to update todos-categories, but it restores
4904 ;; category order to list order.
4905 ;; (todos-repair-categories-sexp)
4906 ;; Compare (todos-make-categories-list t) with sexp and if
4907 ;; different ask (todos-update-categories-sexp) ?
4908 (todos-mode)
4909 (todos-category-select))
4831 ;; Ensure lines following hard newlines are indented. 4910 ;; Ensure lines following hard newlines are indented.
4832 (let ((item (replace-regexp-in-string 4911 (let ((beg (save-excursion (todos-item-start)))
4912 (item (replace-regexp-in-string
4833 "\\(\n\\)[^[:blank:]]" 4913 "\\(\n\\)[^[:blank:]]"
4834 (concat "\n" (make-string todos-indent-to-here 32)) 4914 (concat "\n" (make-string todos-indent-to-here 32))
4835 (buffer-string) nil nil 1))) 4915 (buffer-string) nil nil 1)))
4836 (delete-region (point-min) (point-max)) 4916 (delete-region (point-min) (point-max))
4837 (insert item))) 4917 (insert item)
4838 (kill-buffer) 4918 (todos-mode)
4839 ;; In case next buffer is not the one holding todos-current-todos-file. 4919 (todos-category-select)
4840 (todos-show)) 4920 (goto-char (point-min))
4921 (goto-char beg)
4922 (recenter))))
4841 4923
4842(defun todos-edit-item-header-1 (what &optional inc) 4924(defun todos-edit-item-header-1 (what &optional inc)
4843 "Function underlying commands to edit item date/time header. 4925 "Function underlying commands to edit item date/time header.
@@ -5565,6 +5647,7 @@ With prefix ARG delete an existing comment."
5565 (interactive "P") 5647 (interactive "P")
5566 (when (todos-done-item-p) 5648 (when (todos-done-item-p)
5567 (let ((item (todos-item-string)) 5649 (let ((item (todos-item-string))
5650 (opoint (point))
5568 (end (save-excursion (todos-item-end))) 5651 (end (save-excursion (todos-item-end)))
5569 comment buffer-read-only) 5652 comment buffer-read-only)
5570 (save-excursion 5653 (save-excursion
@@ -5579,6 +5662,8 @@ With prefix ARG delete an existing comment."
5579 (cons (match-string 1) 1))) 5662 (cons (match-string 1) 1)))
5580 (replace-match comment nil nil nil 1)) 5663 (replace-match comment nil nil nil 1))
5581 (setq comment (read-string "Enter a comment: ")) 5664 (setq comment (read-string "Enter a comment: "))
5665 ;; If user moved point during editing, make sure it moves back.
5666 (goto-char opoint)
5582 (todos-item-end) 5667 (todos-item-end)
5583 (insert " [" todos-comment-string ": " comment "]")))))) 5668 (insert " [" todos-comment-string ": " comment "]"))))))
5584 5669