aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/ChangeLog65
-rw-r--r--lisp/calendar/todos.el654
2 files changed, 367 insertions, 352 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 0bcb61c3712..fc8bbbac000 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,68 @@
12012-09-14 Stephen Berman <stephen.berman@gmx.net>
2
3 * calendar/todos.el Remove lots of commented out code; add various
4 comments; further code rearrangement.
5 (todos-insert-item-here-ask-date-time)
6 (todos-insert-item-ask-date-time)
7 (todos-insert-item-ask-dayname-time)
8 (todos-insert-item-for-diary)
9 (todos-insert-item-for-diary-ask-date-time)
10 (todos-make-categories-alist, todos-categories-alist): Remove.
11 (todos-categories-list): Comment out.
12 (todos-make-categories-list): New function replacing
13 todos-make-categories-alist, using category plists to get item
14 counts and taking archive into account.
15 (todos-current-todos-file): New variable.
16 (todos-mode-map): Update key bindings.
17 (todos-save): Add as comment code to make sure todos-categories
18 sexp is current on saving.
19 (todos-quit): Call todos-show on quitting Todos archive buffer.
20 (todos-show): If todos-current-todos-file is not set to Todos
21 file, set it as a new file; set todos-categories from
22 todos-make-categories-alist.
23 (todos-display-categories): Use a different display format for
24 archive file; put point initially on the first button.
25 (todos-toggle-view-done-items): Check the category's `done'
26 property to determine if there are done items.
27 (todos-view-archive): Set todos-current-todos-file to the archive
28 file; jump from the Todos file to the same category in the
29 archive, if it exists, else jump to the first category; use
30 message instead of error.
31 (todos-add-category): Intern a special symbol for the new category
32 and set its property list to holds counts of the numbers of todo,
33 done and archived items in the category; assign the new category
34 the current highest category number.
35 (todos-rename-category): Don't use todos-categories-alist.
36 (todos-delete-category): Check the category's `todo' and `done'
37 properties to determine if it is empty; ensure that the end of the
38 last category is found; after deleting the category, empty its
39 plist and unintern its special symbol.
40 (todos-insert-item-here): Fix argument list of todos-insert-item.
41 (todos-delete-item, todos-raise-item, todos-lower-item):
42 Use message instead of error.
43 (todos-move-item): If the category to be moved to does not exist,
44 add it as a new category.
45 (todos-item-done, todos-reset-separator):
46 Use todos-category-select instead of todos-show.
47 (todos-archive-done-items): Make buffer writeable; conditionalize
48 search for end of category; save after adding to archive in case
49 the file is new, so it can be found.
50 (todos-category-select): Wrap search in if instead of or+and;
51 don't hide done items in an archive.
52 (todos-set-item-priority): Check the category's `todo'
53 property to determine if there are not done todo items.
54 (todos-jump-to-category-noninteractively): Just switch to buffer
55 visiting todos-current-todos-file, since this can be either a
56 Todos file or an archive.
57 (todos-item-counts): Use category's plist instead of an alist.
58 (todos-longest-category-name-length): Argument is now a list of
59 category names, not an alist, so just test each element, not each
60 element's the car.
61 (todos-padded-string): Use todos-categories instead of
62 todos-categories-alist.
63 (todos-insert-category-name): Use category plist to get item
64 counts; take archived items into account.
65
12012-09-13 Stephen Berman <stephen.berman@gmx.net> 662012-09-13 Stephen Berman <stephen.berman@gmx.net>
2 67
3 * calendar/todos.el: Numerous spelling and comment fixes, doc 68 * calendar/todos.el: Numerous spelling and comment fixes, doc
diff --git a/lisp/calendar/todos.el b/lisp/calendar/todos.el
index 7ec54e0f2e9..427056e6e26 100644
--- a/lisp/calendar/todos.el
+++ b/lisp/calendar/todos.el
@@ -481,6 +481,9 @@ Automatically generated when `todos-save-top-priorities' is non-nil."
481;; --------------------------------------------------------------------------- 481;; ---------------------------------------------------------------------------
482;;; Mode setup 482;;; Mode setup
483 483
484(defvar todos-current-todos-file nil
485 "")
486
484(defvar todos-categories nil 487(defvar todos-categories nil
485 "TODO categories.") 488 "TODO categories.")
486 489
@@ -496,12 +499,14 @@ Automatically generated when `todos-save-top-priorities' is non-nil."
496 (define-key map "S" 'todos-search) 499 (define-key map "S" 'todos-search)
497 ;; display commands 500 ;; display commands
498 (define-key map "C" 'todos-display-categories) 501 (define-key map "C" 'todos-display-categories)
502 ;; (define-key map "" 'todos-display-categories-alphabetically)
499 (define-key map "h" 'todos-highlight-item) 503 (define-key map "h" 'todos-highlight-item)
500 (define-key map "N" 'todos-toggle-item-numbering) 504 (define-key map "N" 'todos-toggle-item-numbering)
501 ;; (define-key map "" 'todos-toggle-display-date-time) 505 ;; (define-key map "" 'todos-toggle-display-date-time)
502 (define-key map "P" 'todos-print) 506 (define-key map "P" 'todos-print)
503 (define-key map "q" 'todos-quit) 507 (define-key map "q" 'todos-quit)
504 (define-key map "s" 'todos-save) 508 (define-key map "s" 'todos-save)
509 (define-key map "V" 'todos-view-archive)
505 (define-key map "v" 'todos-toggle-view-done-items) 510 (define-key map "v" 'todos-toggle-view-done-items)
506 (define-key map "Y" 'todos-diary-items) 511 (define-key map "Y" 'todos-diary-items)
507 ;; (define-key map "S" 'todos-save-top-priorities) 512 ;; (define-key map "S" 'todos-save-top-priorities)
@@ -514,7 +519,6 @@ Automatically generated when `todos-save-top-priorities' is non-nil."
514 (define-key map "e" 'todos-edit-item) 519 (define-key map "e" 'todos-edit-item)
515 (define-key map "E" 'todos-edit-multiline) 520 (define-key map "E" 'todos-edit-multiline)
516 ;; (define-key map "" 'todos-change-date) 521 ;; (define-key map "" 'todos-change-date)
517 ;; (define-key map "f" 'todos-file-item)
518 (define-key map "ii" 'todos-insert-item) 522 (define-key map "ii" 'todos-insert-item)
519 (define-key map "ih" 'todos-insert-item-here) 523 (define-key map "ih" 'todos-insert-item-here)
520 (define-key map "ia" 'todos-insert-item-ask-date-time) 524 (define-key map "ia" 'todos-insert-item-ask-date-time)
@@ -684,19 +688,27 @@ Automatically generated when `todos-save-top-priorities' is non-nil."
684(defun todos-save () 688(defun todos-save ()
685 "Save the TODO list." 689 "Save the TODO list."
686 (interactive) 690 (interactive)
687 (save-excursion 691 (let (buffer-read-only)
688 (save-restriction 692 (save-excursion
689 (save-buffer))) 693 (save-restriction
690 ;; (if todos-save-top-priorities-too (todos-save-top-priorities))) 694 ;; (widen)
691 ) 695 ;; (goto-char (point-min))
696 ;; (unless (looking-at (concat "^" (regexp-quote todos-category-beg)))
697 ;; (kill-line))
698 ;; (prin1 todos-categories (current-buffer))
699 (save-buffer)))
700 ;; (if todos-save-top-priorities-too (todos-save-top-priorities)))
701 ))
692 702
693(defun todos-quit () 703(defun todos-quit ()
694 "Done with TODO list for now." 704 "Done with TODO list for now."
695 (interactive) 705 (interactive)
696 (widen) 706 (widen)
697 (todos-save) 707 (todos-save)
698 (message "") 708 ;; (message "")
699 (bury-buffer)) 709 (if (eq major-mode 'todos-archive-mode)
710 (todos-show)
711 (bury-buffer)))
700 712
701;; --------------------------------------------------------------------------- 713;; ---------------------------------------------------------------------------
702;;; Commands 714;;; Commands
@@ -722,14 +734,14 @@ Automatically generated when `todos-save-top-priorities' is non-nil."
722 (find-file todos-file-do) 734 (find-file todos-file-do)
723 (todos-initial-setup)) 735 (todos-initial-setup))
724 (unless (eq major-mode 'todos-mode) (todos-mode)) 736 (unless (eq major-mode 'todos-mode) (todos-mode))
725 (unless todos-categories-alist 737 (unless (string= todos-current-todos-file todos-file-do)
726 (setq todos-categories-alist (todos-make-categories-alist))) 738 (setq todos-current-todos-file todos-file-do)
739 (setq todos-category-number 0)
740 (setq todos-categories nil))
727 (unless todos-categories 741 (unless todos-categories
728 (setq todos-categories (mapcar 'car todos-categories-alist))) 742 (setq todos-categories (todos-make-categories-list)))
729 (save-excursion 743 (save-excursion
730 (todos-category-select) 744 (todos-category-select))))
731 ;; (todos-show-paren-hack)
732 )))
733 745
734(defun todos-display-categories (&optional alpha) 746(defun todos-display-categories (&optional alpha)
735 "Display a numbered list of the Todos category names. 747 "Display a numbered list of the Todos category names.
@@ -755,9 +767,15 @@ the category in Todos mode."
755 (insert "Press a button to display the corresponding category.\n\n") 767 (insert "Press a button to display the corresponding category.\n\n")
756 ;; FIXME: abstract format from here and todos-insert-category-name 768 ;; FIXME: abstract format from here and todos-insert-category-name
757 (insert (make-string 4 32) (todos-padded-string "Category") 769 (insert (make-string 4 32) (todos-padded-string "Category")
758 (make-string 7 32) "Todos Done\n\n") 770 (if (string= todos-current-todos-file todos-archive-file)
771 (concat (make-string 6 32)
772 (format "%s" "Archived"))
773 (concat (make-string 7 32)
774 (format "%-7s%-7s%s" "Todo" "Done" "Archived")))
775 "\n\n")
759 (save-excursion 776 (save-excursion
760 (mapc '(lambda (cat) (todos-insert-category-name cat alpha)) categories))) 777 (mapc '(lambda (cat) (todos-insert-category-name cat alpha)) categories)))
778 (goto-char (next-single-char-property-change (point) 'button))
761 (todos-categories-mode)))) 779 (todos-categories-mode))))
762 780
763(defun todos-display-categories-alphabetically () 781(defun todos-display-categories-alphabetically ()
@@ -775,25 +793,41 @@ the category in Todos mode."
775 (interactive) 793 (interactive)
776 (save-excursion 794 (save-excursion
777 (goto-char (point-min)) 795 (goto-char (point-min))
778 (let ((todos-show-with-done 796 (let* ((todos-show-with-done
779 (if (re-search-forward (concat "\n\\(\\[" (regexp-quote todos-done-string) 797 (if (re-search-forward (concat "\n\\(\\["
780 "\\)") nil t) 798 (regexp-quote todos-done-string)
781 nil 799 "\\)") nil t)
782 t))) 800 nil
783 (todos-category-select)))) 801 t))
802 (cat (todos-current-category))
803 (catsym (intern-soft (concat "todos-" cat))))
804 (todos-category-select)
805 (when (zerop (get catsym 'done))
806 (message "There are no done items in this category.")))))
784 807
785(defun todos-view-archive (&optional cat) 808(defun todos-view-archive (&optional cat)
786 "" 809 ""
787 (interactive) 810 (interactive)
788 (if (file-exists-p todos-archive-file) 811 (if (file-exists-p todos-archive-file)
789 (progn 812 (progn ;let ((todos-show-with-done t))
790 (find-file todos-archive-file) 813 (find-file todos-archive-file)
814 (todos-archive-mode)
815 (unless (string= todos-current-todos-file todos-archive-file)
816 (setq todos-current-todos-file todos-archive-file)
817 (setq todos-categories nil))
818 (unless todos-categories
819 (setq todos-categories (todos-make-categories-list)))
791 (if cat 820 (if cat
792 (if (member cat (todos-categories-list (current-buffer))) 821 (if (member cat (todos-categories))
793 (todos-jump-to-category-noninteractively cat) 822 (progn
794 (error "No archived items from this category")) 823 (setq todos-category-number
824 (- (length todos-categories)
825 (length (member cat todos-categories))))
826 (todos-jump-to-category-noninteractively cat))
827 (message "No archived items from this category"))
828 (setq todos-category-number 0)
795 (todos-category-select))) 829 (todos-category-select)))
796 (error "There is currently no Todos archive"))) 830 (message "There is currently no Todos archive")))
797 831
798;; FIXME: slow 832;; FIXME: slow
799(defun todos-diary-items () 833(defun todos-diary-items ()
@@ -806,7 +840,6 @@ the category in Todos mode."
806 (widen) 840 (widen)
807 (copy-to-buffer bufname (point-min) (point-max)))) 841 (copy-to-buffer bufname (point-min) (point-max))))
808 (with-current-buffer bufname 842 (with-current-buffer bufname
809 ;; (todos-mode)
810 (goto-char (point-min)) 843 (goto-char (point-min))
811 (while (not (eobp)) 844 (while (not (eobp))
812 (setq opoint (point)) 845 (setq opoint (point))
@@ -866,12 +899,10 @@ the category in Todos mode."
866 "\\( " diary-time-regexp "\\)?\\]? ") 899 "\\( " diary-time-regexp "\\)?\\]? ")
867 ; FIXME: this space in header? ^ 900 ; FIXME: this space in header? ^
868 nil t) 901 nil t)
902 ;; FIXME: wrong match data if search fails
869 (setq ov (make-overlay (match-beginning 0) (match-end 0) nil t)) 903 (setq ov (make-overlay (match-beginning 0) (match-end 0) nil t))
870 (overlay-put ov 'display "") 904 (overlay-put ov 'display "")
871 (forward-line))) 905 (forward-line))))))
872 ;; FIXME: need this?
873 ;; (todos-update-numbered-prefix)
874 )))
875 906
876;;;###autoload 907;;;###autoload
877(defun todos-top-priorities (&optional nof-priorities category-pr-page show-done) 908(defun todos-top-priorities (&optional nof-priorities category-pr-page show-done)
@@ -972,7 +1003,6 @@ With non-nil SHOW-DONE, include done items in the listing."
972 (- (length todos-categories) 1003 (- (length todos-categories)
973 (length (member category todos-categories))) 1004 (length (member category todos-categories)))
974 (todos-add-category category))) 1005 (todos-add-category category)))
975 ;; (todos-show)))
976 (todos-category-select))) 1006 (todos-category-select)))
977 1007
978;; FIXME ? todos-{backward,forward}-item skip over empty line between done and 1008;; FIXME ? todos-{backward,forward}-item skip over empty line between done and
@@ -1013,7 +1043,7 @@ With non-nil SHOW-DONE, include done items in the listing."
1013 (forward-line)) 1043 (forward-line))
1014 (if found 1044 (if found
1015 (progn 1045 (progn
1016 (setq found (match-beginning 0)) 1046 (setq found (match-beginning 0)) ;FIXME: ok if looking-at returns nil?
1017 (todos-item-start) 1047 (todos-item-start)
1018 (when (looking-at (concat "^\\[" (regexp-quote todos-done-string))) 1048 (when (looking-at (concat "^\\[" (regexp-quote todos-done-string)))
1019 (setq in-done t)) 1049 (setq in-done t))
@@ -1035,7 +1065,8 @@ With non-nil SHOW-DONE, include done items in the listing."
1035 "Add new category CAT to the TODO list." 1065 "Add new category CAT to the TODO list."
1036 (interactive) 1066 (interactive)
1037 (let ((buffer-read-only) 1067 (let ((buffer-read-only)
1038 (buf (find-file-noselect todos-file-do t))) 1068 (buf (find-file-noselect todos-file-do t))
1069 catsym)
1039 (unless (zerop (buffer-size buf)) 1070 (unless (zerop (buffer-size buf))
1040 (and (null todos-categories) 1071 (and (null todos-categories)
1041 (error "Error in %s: File is non-empty but contains no category" 1072 (error "Error in %s: File is non-empty but contains no category"
@@ -1045,9 +1076,11 @@ With non-nil SHOW-DONE, include done items in the listing."
1045 (setq cat (todos-check-category-name cat)) 1076 (setq cat (todos-check-category-name cat))
1046 ;; initialize a newly created Todo buffer for Todo mode 1077 ;; initialize a newly created Todo buffer for Todo mode
1047 (unless (file-exists-p todos-file-do) (todos-mode)) 1078 (unless (file-exists-p todos-file-do) (todos-mode))
1048 (push cat todos-categories) 1079 (setq catsym (intern (concat "todos-" cat)))
1049 (push (list cat (cons 0 0)) todos-categories-alist) 1080 (setplist catsym (list 'todo 0 'done 0 'archived 0))
1081 (nconc todos-categories (list cat)) ;FIXME: is this TRTD?
1050 (widen) 1082 (widen)
1083 ;; FIXME: make this (point-max)
1051 (goto-char (point-min)) 1084 (goto-char (point-min))
1052 ;; make sure file does not begin with empty lines (shouldn't, but may be 1085 ;; make sure file does not begin with empty lines (shouldn't, but may be
1053 ;; added by mistake), otherwise new categories will contain them, so 1086 ;; added by mistake), otherwise new categories will contain them, so
@@ -1056,8 +1089,9 @@ With non-nil SHOW-DONE, include done items in the listing."
1056 (insert todos-category-beg cat "\n") 1089 (insert todos-category-beg cat "\n")
1057 (if (interactive-p) 1090 (if (interactive-p)
1058 ;; properly display the newly added category 1091 ;; properly display the newly added category
1059 (progn (setq todos-category-number 0) (todos-show)) 1092 (progn (setq todos-category-number (1- (length todos-categories)))
1060 0)))) 1093 (todos-category-select))
1094 (1- (length todos-categories))))))
1061 1095
1062(defun todos-rename-category () 1096(defun todos-rename-category ()
1063 "Rename current Todos category." 1097 "Rename current Todos category."
@@ -1069,7 +1103,6 @@ With non-nil SHOW-DONE, include done items in the listing."
1069 (setq new (todos-check-category-name new)) 1103 (setq new (todos-check-category-name new))
1070 (aset vec todos-category-number new) 1104 (aset vec todos-category-number new)
1071 (setq todos-categories (append vec nil)) 1105 (setq todos-categories (append vec nil))
1072 (setcar (assoc cat todos-categories-alist) new)
1073 (save-excursion 1106 (save-excursion
1074 (widen) 1107 (widen)
1075 (re-search-backward (concat (regexp-quote todos-category-beg) "\\(" 1108 (re-search-backward (concat (regexp-quote todos-category-beg) "\\("
@@ -1085,28 +1118,31 @@ With ARG non-nil delete the category unconditionally,
1085i.e. including all existing entries." 1118i.e. including all existing entries."
1086 (interactive "P") 1119 (interactive "P")
1087 (let* ((cat (todos-current-category)) 1120 (let* ((cat (todos-current-category))
1088 (not-done (car (todos-item-counts cat))) 1121 (catsym (intern-soft (concat "todos-" cat)))
1089 (done (cdr (todos-item-counts cat))) 1122 (todo (get catsym 'todo))
1123 (done (get catsym 'done))
1090 beg end) 1124 beg end)
1091 (if (and (null arg) 1125 (if (and (null arg)
1092 (or (> not-done 0) (> done 0))) 1126 (or (> todo 0) (> done 0)))
1093 (message "To delete a non-empty category, type C-u D.") 1127 (message "To delete a non-empty category, type C-u D.")
1094 (when (y-or-n-p (concat "Permanently remove category \"" cat 1128 (when (y-or-n-p (concat "Permanently remove category \"" cat
1095 "\"" (and arg " and all its entries") "? ")) 1129 "\"" (and arg " and all its entries") "? "))
1096 (let ((buffer-read-only)) 1130 (let ((buffer-read-only))
1097 (widen) 1131 (widen)
1098 (setq beg (re-search-backward (concat "^" (regexp-quote todos-category-beg) 1132 (setq beg (re-search-backward (concat "^" (regexp-quote todos-category-beg)
1099 cat "\n") nil t) 1133 cat "\n") nil t))
1100 end (progn 1134 (setq end (if (re-search-forward (concat "\n\\("
1101 (re-search-forward (concat "\n\\(" 1135 (regexp-quote todos-category-beg)
1102 (regexp-quote todos-category-beg) 1136 ".*\n\\)") nil t)
1103 ".*\n\\)") nil t) 1137 (match-beginning 1)
1104 (match-beginning 1))) 1138 (point-max)))
1105 (remove-overlays beg end) 1139 (remove-overlays beg end)
1106 (kill-region beg end) 1140 (kill-region beg end)
1107 (setq todos-categories (delete cat todos-categories)) 1141 (setq todos-categories (delete cat todos-categories))
1108 (setq todos-categories-alist 1142 (setplist catsym nil)
1109 (delete (assoc cat todos-categories-alist) todos-categories-alist)) 1143 (unintern catsym)
1144 (setq todos-category-number
1145 (mod todos-category-number (length todos-categories)))
1110 (todos-category-select) 1146 (todos-category-select)
1111 (message "Deleted category %s" cat)))))) 1147 (message "Deleted category %s" cat))))))
1112 1148
@@ -1180,7 +1216,7 @@ there."
1180 (interactive "P") 1216 (interactive "P")
1181 (unless (or (todos-done-item-p) 1217 (unless (or (todos-done-item-p)
1182 (save-excursion (forward-line -1) (todos-done-item-p))) 1218 (save-excursion (forward-line -1) (todos-done-item-p)))
1183 (if (not (derived-mode-p 'todos-mode)) (todos-show)) 1219 (when (not (derived-mode-p 'todos-mode)) (todos-show))
1184 (let* ((buffer-read-only) 1220 (let* ((buffer-read-only)
1185 (date-string (cond 1221 (date-string (cond
1186 ((eq date-type 'ask-date) 1222 ((eq date-type 'ask-date)
@@ -1192,7 +1228,7 @@ there."
1192 (with-current-buffer "*Calendar*" 1228 (with-current-buffer "*Calendar*"
1193 (calendar-date-string (calendar-cursor-to-date t) t t))) 1229 (calendar-date-string (calendar-cursor-to-date t) t t)))
1194 (t (calendar-date-string (calendar-current-date) t t)))) 1230 (t (calendar-date-string (calendar-current-date) t t))))
1195 (time-string (cond ((eq time 'omit) nil) 1231 (time-string (cond ((eq time 'omit) nil) ;FIXME: delete
1196 ((eq time 'ask-time) 1232 ((eq time 'ask-time)
1197 (todos-read-time)) 1233 (todos-read-time))
1198 (todos-always-add-time-string 1234 (todos-always-add-time-string
@@ -1208,88 +1244,55 @@ there."
1208 "\\(\n\\)[^[:blank:]]" 1244 "\\(\n\\)[^[:blank:]]"
1209 (concat "\n" (make-string todos-indent-to-here 32)) new-item 1245 (concat "\n" (make-string todos-indent-to-here 32)) new-item
1210 nil nil 1)) 1246 nil nil 1))
1211 ;; (if here
1212 ;; (todos-insert-with-overlays new-item)
1213 ;; (todos-add-item-non-interactively new-item cat))
1214 (unless here (todos-set-item-priority new-item cat)) 1247 (unless here (todos-set-item-priority new-item cat))
1215 (todos-insert-with-overlays new-item) 1248 (todos-insert-with-overlays new-item)
1216 (todos-item-counts cat 'insert)))) 1249 (todos-item-counts cat 'insert))))
1217 1250
1218;; FIXME: make insertion options customizable per category 1251;; FIXME: make insertion options customizable per category
1219;; date-type: d n (c) - time - diary - here
1220;; idd inn itt iyy ih
1221;; idtt idyy idh intt inyy inh ityy iyh
1222;; idtyy idyh intyy inyh ityh
1223;; idtyh intyh
1224;; idth inth
1225
1226;; todos-insert-item
1227;; todos-insert-item-ask-date
1228;; todos-insert-item-ask-date-time
1229;; todos-insert-item-ask-dayname
1230;; todos-insert-item-ask-dayname-time
1231;; todos-insert-item-ask-time
1232;; todos-insert-item-for-diary
1233;; todos-insert-item-for-diary-ask-date
1234;; todos-insert-item-for-diary-ask-date-time
1235;; todos-insert-item-for-diary-ask-dayname
1236;; todos-insert-item-for-diary-ask-dayname-time
1237;; todos-insert-item-for-diary-ask-time
1238;; todos-insert-item-here
1239;; todos-insert-item-here-ask-date
1240;; todos-insert-item-here-ask-date-time
1241;; todos-insert-item-here-ask-dayname
1242;; todos-insert-item-here-ask-dayname-time
1243;; todos-insert-item-here-ask-time
1244;; todos-insert-item-here-ask-time-diary
1245;; todos-insert-item-here-for-diary
1246;; todos-insert-item-here-for-diary-ask-date-time
1247;; todos-insert-item-here-for-diary-ask-time
1248;; todos-insert-item-here-for-diary-ask-dayname-time
1249 1252
1250(defun todos-insert-item-here () 1253;; current date ~ current day ~ ask date ~ ask day
1251 "" 1254;; current time ~ ask time ~ no time
1252 (interactive) 1255;; for diary ~ not for diary
1253 (todos-insert-item nil nil nil t)) 1256;; here ~ ask priority
1254
1255(defun todos-insert-item-here-ask-date-time ()
1256 ""
1257 (interactive)
1258 (todos-insert-item nil 'ask-date 'ask-time t))
1259 1257
1260;; (defun todos-insert-item-no-time () 1258;; date-type: d n (c) - time - diary - here
1261;; ""
1262;; (interactive)
1263;; (todos-insert-item nil nil 'omit t))
1264 1259
1265(defun todos-insert-item-ask-date-time (&optional arg) 1260;; ii todos-insert-item
1266 "" 1261;; idd todos-insert-item-ask-date
1267 (interactive "P") 1262;; idtt todos-insert-item-ask-date-time
1268 (todos-insert-item arg 'ask-date 'ask-time)) 1263;; idtyy todos-insert-item-ask-date-time-for-diary
1264;; idtyh todos-insert-item-ask-date-time-for-diary-here
1265;; idth todos-insert-item-ask-date-time-here
1266;; idyy todos-insert-item-ask-date-for-diary
1267;; idyh todos-insert-item-ask-date-for-diary-here
1268;; idh todos-insert-item-ask-date-here
1269;; inn todos-insert-item-ask-dayname
1270;; intt todos-insert-item-ask-dayname-time
1271;; intyy todos-insert-item-ask-dayname-time-for-diary
1272;; intyh todos-insert-item-ask-dayname-time-for-diary-here
1273;; inth todos-insert-item-ask-dayname-time-here
1274;; inyy todos-insert-item-ask-dayname-for-diary
1275;; inyh todos-insert-item-ask-dayname-for-diary-here
1276;; inh todos-insert-item-ask-dayname-here
1277;; itt todos-insert-item-time
1278;; ityy todos-insert-item-time-for-diary
1279;; ityh todos-insert-item-time-for-diary-here
1280;; ith todos-insert-item-time-here
1281;; iyy todos-insert-item-for-diary
1282;; iyh todos-insert-item-for-diary-here
1283;; ih todos-insert-item-here
1269 1284
1270(defun todos-insert-item-ask-dayname-time (&optional arg) 1285(defun todos-insert-item-here ()
1271 "" 1286 ""
1272 (interactive) 1287 (interactive)
1273 (todos-insert-item arg 'ask-dayname 'ask-time)) 1288 (todos-insert-item nil nil nil nil t))
1274
1275(defun todos-insert-item-for-diary (&optional arg)
1276 ""
1277 (interactive "P")
1278 (let ((todos-include-in-diary t))
1279 (todos-insert-item arg)))
1280
1281(defun todos-insert-item-for-diary-ask-date-time (&optional arg)
1282 ""
1283 (interactive "P")
1284 (let ((todos-include-in-diary t))
1285 (todos-insert-item arg 'ask-dayname 'ask-time)))
1286 1289
1287;; FIXME: autoload when key-binding is defined in calendar.el 1290;; FIXME: autoload when key-binding is defined in calendar.el
1288(defun todos-insert-item-from-calendar () 1291(defun todos-insert-item-from-calendar ()
1289 "" 1292 ""
1290 (interactive) 1293 (interactive)
1291 (pop-to-buffer (file-name-nondirectory todos-file-do)) 1294 (pop-to-buffer (file-name-nondirectory todos-file-do))
1292 (todos-show) 1295 (todos-show) ;FIXME: todos-category-select ?
1293 (todos-insert-item t 'calendar)) 1296 (todos-insert-item t 'calendar))
1294 1297
1295;; FIXME: calendar is loaded before todos 1298;; FIXME: calendar is loaded before todos
@@ -1312,12 +1315,8 @@ there."
1312 (< (point-min) (point-max))) 1315 (< (point-min) (point-max)))
1313 (todos-backward-item)) 1316 (todos-backward-item))
1314 (todos-item-counts (todos-current-category) 'delete) 1317 (todos-item-counts (todos-current-category) 'delete)
1315 ;; FIXME: is todos-prefix-overlays part of if-sexp, and is it needed 1318 (todos-prefix-overlays)))
1316 ;; at all? 1319 (message "No TODO list entry to delete"))) ;FIXME: better message
1317 ;; (if todos-number-prefix
1318 ;; (todos-update-numbered-prefix)
1319 (todos-prefix-overlays)));)
1320 (error "No TODO list entry to delete")))
1321 1320
1322(defun todos-edit-item () 1321(defun todos-edit-item ()
1323 "Edit current TODO list entry." 1322 "Edit current TODO list entry."
@@ -1382,23 +1381,14 @@ there."
1382 (todos-remove-item) 1381 (todos-remove-item)
1383 (todos-backward-item) 1382 (todos-backward-item)
1384 (todos-insert-with-overlays item)) 1383 (todos-insert-with-overlays item))
1385 (error "No TODO list entry to raise"))))) 1384 (message "No TODO list entry to raise"))))) ;FIXME: better message
1386 1385
1387(defun todos-lower-item () 1386(defun todos-lower-item ()
1388 "Lower priority of current entry." 1387 "Lower priority of current entry."
1389 (interactive) 1388 (interactive)
1390 (unless (or (todos-done-item-p) 1389 (unless (or (todos-done-item-p)
1391 (looking-at "^$")) ; between done and not done items 1390 (looking-at "^$")) ; between done and not done items
1392 (let* ((buffer-read-only) 1391 (let* ((buffer-read-only))
1393 ;; (end (save-excursion (todos-forward-item) (point)))
1394 ;; (done (save-excursion
1395 ;; (if (re-search-forward (concat "\n\n\\\["
1396 ;; (regexp-quote todos-done-string))
1397 ;; nil t)
1398 ;; (match-beginning 0)
1399 ;; (point-max))))
1400 )
1401 ;; (if (> (count-lines (point) done) 1)
1402 (if (save-excursion 1392 (if (save-excursion
1403 ;; can only lower non-final unfinished item 1393 ;; can only lower non-final unfinished item
1404 (todos-forward-item) 1394 (todos-forward-item)
@@ -1410,7 +1400,7 @@ there."
1410 (todos-forward-item) 1400 (todos-forward-item)
1411 (when (todos-done-item-p) (forward-line -1)) 1401 (when (todos-done-item-p) (forward-line -1))
1412 (todos-insert-with-overlays item)) 1402 (todos-insert-with-overlays item))
1413 (error "No TODO list entry to lower"))))) ;FIXME: better message 1403 (message "No TODO list entry to lower"))))) ;FIXME: better message
1414 1404
1415(defun todos-move-item () 1405(defun todos-move-item ()
1416 "Move the current todo item to another, interactively named, category. 1406 "Move the current todo item to another, interactively named, category.
@@ -1429,12 +1419,10 @@ it is created and the item becomes the first entry in that category."
1429 (orig-mrk (progn (todos-item-start) (point-marker))) 1419 (orig-mrk (progn (todos-item-start) (point-marker)))
1430 moved) 1420 moved)
1431 (todos-remove-item) 1421 (todos-remove-item)
1432 ;; numbered prefix isn't cached (see todos-remove-item) so have to update
1433 ;; (if todos-number-prefix (todos-update-numbered-prefix))
1434 (unwind-protect 1422 (unwind-protect
1435 (progn 1423 (progn
1436 ;; (todos-add-item-non-interactively item newcat) 1424 (unless (member newcat todos-categories) (todos-add-category newcat))
1437 (todos-set-item-priority item newcat) 1425 (todos-set-item-priority item newcat)
1438 (todos-insert-with-overlays item) 1426 (todos-insert-with-overlays item)
1439 (setq moved t) 1427 (setq moved t)
1440 (todos-item-counts oldcat 'delete) 1428 (todos-item-counts oldcat 'delete)
@@ -1444,8 +1432,6 @@ it is created and the item becomes the first entry in that category."
1444 (goto-char orig-mrk) 1432 (goto-char orig-mrk)
1445 (todos-insert-with-overlays item) 1433 (todos-insert-with-overlays item)
1446 (setq todos-category-number oldnum) 1434 (setq todos-category-number oldnum)
1447 ;; (todos-item-counts oldcat 'move-failed)
1448 ;; (todos-item-counts newcat 'move-failed)
1449 (todos-category-select) 1435 (todos-category-select)
1450 ;; FIXME: does this work? 1436 ;; FIXME: does this work?
1451 (goto-char opoint)) 1437 (goto-char opoint))
@@ -1484,19 +1470,22 @@ it is created and the item becomes the first entry in that category."
1484 (newline)) 1470 (newline))
1485 (todos-insert-with-overlays done-item))) 1471 (todos-insert-with-overlays done-item)))
1486 (todos-item-counts (todos-current-category) 'done) 1472 (todos-item-counts (todos-current-category) 'done)
1487 (todos-show))) 1473 (todos-category-select)))
1488 1474
1489(defun todos-archive-done-items () 1475(defun todos-archive-done-items ()
1490 "Archive the done items in the current category." 1476 "Archive the done items in the current category."
1491 (interactive) 1477 (interactive)
1492 (let ((archive (find-file-noselect todos-archive-file t)) 1478 (let ((archive (find-file-noselect todos-archive-file t))
1493 (cat (todos-current-category)) 1479 (cat (todos-current-category))
1480 (buffer-read-only)
1494 beg end) 1481 beg end)
1495 (save-excursion 1482 (save-excursion
1496 (save-restriction 1483 (save-restriction
1497 (widen) 1484 (widen)
1498 (re-search-forward (concat "^" (regexp-quote todos-category-beg)) nil t) 1485 (setq end (if (re-search-forward
1499 (setq end (or (match-beginning 0) (point-max))) 1486 (concat "^" (regexp-quote todos-category-beg)) nil t)
1487 (match-beginning 0)
1488 (point-max)))
1500 (re-search-backward (concat "^" (regexp-quote todos-category-beg) 1489 (re-search-backward (concat "^" (regexp-quote todos-category-beg)
1501 (regexp-quote cat)) 1490 (regexp-quote cat))
1502 nil t) 1491 nil t)
@@ -1512,7 +1501,8 @@ it is created and the item becomes the first entry in that category."
1512 nil t) 1501 nil t)
1513 (forward-char) 1502 (forward-char)
1514 (insert todos-category-beg cat "\n")) 1503 (insert todos-category-beg cat "\n"))
1515 (insert done)) 1504 (insert done)
1505 (save-buffer))
1516 (delete-region beg end) 1506 (delete-region beg end)
1517 (remove-overlays beg end) 1507 (remove-overlays beg end)
1518 (kill-line -1) 1508 (kill-line -1)
@@ -1532,10 +1522,8 @@ it is created and the item becomes the first entry in that category."
1532 (item (buffer-substring start (todos-item-end))) 1522 (item (buffer-substring start (todos-item-end)))
1533 undone) 1523 undone)
1534 (todos-remove-item) 1524 (todos-remove-item)
1535 ;; (if todos-number-prefix (todos-update-numbered-prefix))
1536 (unwind-protect 1525 (unwind-protect
1537 (progn 1526 (progn
1538 ;; (todos-add-item-non-interactively item cat)
1539 (todos-set-item-priority item cat) 1527 (todos-set-item-priority item cat)
1540 (todos-insert-with-overlays item) 1528 (todos-insert-with-overlays item)
1541 (setq undone t) 1529 (setq undone t)
@@ -1544,7 +1532,6 @@ it is created and the item becomes the first entry in that category."
1544 (widen) 1532 (widen)
1545 (goto-char orig-mrk) 1533 (goto-char orig-mrk)
1546 (todos-insert-with-overlays done-item) 1534 (todos-insert-with-overlays done-item)
1547 ;; (todos-item-counts cat 'done)
1548 (let ((todos-show-with-done t)) 1535 (let ((todos-show-with-done t))
1549 (todos-category-select) 1536 (todos-category-select)
1550 (goto-char opoint))) 1537 (goto-char opoint)))
@@ -1679,7 +1666,6 @@ Number of entries for each category is given by `todos-print-priorities'."
1679 (make-local-variable 'word-wrap) 1666 (make-local-variable 'word-wrap)
1680 (setq word-wrap t) 1667 (setq word-wrap t)
1681 (make-local-variable 'wrap-prefix) 1668 (make-local-variable 'wrap-prefix)
1682 ;; (setq wrap-prefix (make-string (+ 5 (length todos-prefix)) 32))
1683 (setq wrap-prefix (make-string todos-indent-to-here 32)) 1669 (setq wrap-prefix (make-string todos-indent-to-here 32))
1684 (unless (member '(continuation) fringe-indicator-alist) 1670 (unless (member '(continuation) fringe-indicator-alist)
1685 (push '(continuation) fringe-indicator-alist))) 1671 (push '(continuation) fringe-indicator-alist)))
@@ -1688,53 +1674,6 @@ Number of entries for each category is given by `todos-print-priorities'."
1688 "" 1674 ""
1689 (indent-to todos-indent-to-here todos-indent-to-here)) 1675 (indent-to todos-indent-to-here todos-indent-to-here))
1690 1676
1691(defun todos-reset-prefix (symbol value)
1692 "Set SYMBOL's value to VALUE, and ." ; FIXME
1693 (let ((oldvalue (symbol-value symbol)))
1694 (custom-set-default symbol value)
1695 (when (not (equal value oldvalue))
1696 (save-window-excursion
1697 (todos-show)
1698 (save-excursion
1699 (widen)
1700 (goto-char (point-min))
1701 (while (not (eobp))
1702 (remove-overlays (point) (point)); 'before-string prefix)
1703 (forward-line)))
1704 ;; activate the prefix setting (save-restriction does not help)
1705 ;; (todos-show)
1706 (todos-category-select)
1707 ))))
1708
1709;; FIXME: ??? with todos-lower-item leaves overlay of lower item if this is
1710;; the third or greater item number -- but not in edebug
1711;; (defun todos-update-numbered-prefix ()
1712;; "Update consecutive item numbering in the current category."
1713;; (save-excursion
1714;; (goto-char (point-min))
1715;; (while (not (eobp))
1716;; (let ((ov (car (overlays-in (point) (point))))
1717;; val)
1718;; (when ov
1719;; (setq val (overlay-get ov 'before-string))
1720;; (remove-overlays (point) (point) 'before-string val)))
1721;; (todos-forward-item))
1722;; (todos-show)))
1723
1724;; (defun todos-update-numbered-prefix ()
1725;; "Update consecutive item numbering in the current category."
1726;; (save-excursion
1727;; (goto-char (point-min))
1728;; (while (not (eobp))
1729;; (remove-overlays (point) (point))
1730;; (todos-forward-item))
1731;; ;; FIXME: is todos-prefix-overlays enough?
1732;; (todos-show)))
1733
1734;; (defvar todos-item-start-overlays nil "")
1735
1736;; (defvar todos-done-overlays nil "")
1737
1738(defun todos-prefix-overlays () 1677(defun todos-prefix-overlays ()
1739 "" 1678 ""
1740 (when (or todos-number-prefix 1679 (when (or todos-number-prefix
@@ -1750,31 +1689,16 @@ Number of entries for each category is given by `todos-print-priorities'."
1750 (when todos-number-prefix 1689 (when todos-number-prefix
1751 (setq num (1+ num)) 1690 (setq num (1+ num))
1752 ;; reset number for done items 1691 ;; reset number for done items
1753 (when ;; (or 1692 (when
1754 ;; ;; FIXME: really need this? 1693 ;; FIXME: really need this?
1755 ;; (looking-at (concat "\n\\[" (regexp-quote todos-done-string)))
1756 ;; if last not done item is multiline, then 1694 ;; if last not done item is multiline, then
1757 ;; todos-done-string-match skips empty line, so have 1695 ;; todos-done-string-match skips empty line, so have
1758 ;; to look back. 1696 ;; to look back.
1759 (and (looking-at (concat "^\\[" (regexp-quote todos-done-string))) 1697 (and (looking-at (concat "^\\[" (regexp-quote todos-done-string)))
1760 (looking-back "\n\n"));) 1698 (looking-back "\n\n"))
1761 (setq num 1)) 1699 (setq num 1))
1762 (setq prefix (propertize (concat (number-to-string num) " ") 1700 (setq prefix (propertize (concat (number-to-string num) " ")
1763 'face 'todos-prefix-string))) 1701 'face 'todos-prefix-string)))
1764 ;; (let ((ovs (overlays-in (point) (point))))
1765 ;; (or (and (setq ov-pref (car ovs))
1766 ;; ;; when done-separator overlay is in front of prefix overlay
1767 ;; (if (and (> (length ovs) 1)
1768 ;; (not (equal (overlay-get ov-pref 'before-string)
1769 ;; prefix)))
1770 ;; (setq ov-pref (cadr ovs))
1771 ;; t)
1772 ;; (equal (overlay-get ov-pref 'before-string) prefix))
1773 ;; ;; non-numerical prefix
1774 ;; (and (setq ov-pref (pop todos-item-start-overlays))
1775 ;; (move-overlay ov-pref (point) (point)))
1776 ;; (and (setq ov-pref (make-overlay (point) (point)))
1777 ;; (overlay-put ov-pref 'before-string prefix))))
1778 (let* ((ovs (overlays-in (point) (point))) 1702 (let* ((ovs (overlays-in (point) (point)))
1779 (ov-pref (car ovs)) 1703 (ov-pref (car ovs))
1780 (val (when ov-pref (overlay-get ov-pref 'before-string)))) 1704 (val (when ov-pref (overlay-get ov-pref 'before-string))))
@@ -1782,17 +1706,32 @@ Number of entries for each category is given by `todos-print-priorities'."
1782 (not (equal val prefix))) 1706 (not (equal val prefix)))
1783 (setq ov-pref (cadr ovs))) 1707 (setq ov-pref (cadr ovs)))
1784 (when (not (equal val prefix)) 1708 (when (not (equal val prefix))
1785 ;; (delete-overlay ov-pref) 1709 ;; (delete-overlay ov-pref) ; why doesn't this work ???
1786 (remove-overlays (point) (point)); 'before-string val) 1710 (remove-overlays (point) (point)); 'before-string val) ; or this ???
1787 (setq ov-pref (make-overlay (point) (point))) 1711 (setq ov-pref (make-overlay (point) (point)))
1788 (overlay-put ov-pref 'before-string prefix)))) 1712 (overlay-put ov-pref 'before-string prefix))))
1789 (forward-line)))))) 1713 (forward-line))))))
1790 1714
1715(defun todos-reset-prefix (symbol value)
1716 "Set SYMBOL's value to VALUE, and ." ; FIXME
1717 (let ((oldvalue (symbol-value symbol)))
1718 (custom-set-default symbol value)
1719 (when (not (equal value oldvalue))
1720 (save-window-excursion
1721 (todos-show)
1722 (save-excursion
1723 (widen)
1724 (goto-char (point-min))
1725 (while (not (eobp))
1726 (remove-overlays (point) (point)); 'before-string prefix)
1727 (forward-line)))
1728 ;; activate the prefix setting (save-restriction does not help)
1729 (todos-category-select)))))
1730
1791(defun todos-reset-separator (symbol value) 1731(defun todos-reset-separator (symbol value)
1792 "Set SYMBOL's value to VALUE, and ." ; FIXME 1732 "Set SYMBOL's value to VALUE, and ." ; FIXME
1793 (let ((oldvalue (symbol-value symbol))) 1733 (let ((oldvalue (symbol-value symbol)))
1794 (custom-set-default symbol value) 1734 (custom-set-default symbol value)
1795 ;; (setq todos-done-overlays nil)
1796 (when (not (equal value oldvalue)) 1735 (when (not (equal value oldvalue))
1797 (save-window-excursion 1736 (save-window-excursion
1798 (todos-show) 1737 (todos-show)
@@ -1802,7 +1741,7 @@ Number of entries for each category is given by `todos-print-priorities'."
1802 nil t) 1741 nil t)
1803 (remove-overlays (point) (point)))) 1742 (remove-overlays (point) (point))))
1804 ;; activate the prefix setting (save-restriction does not help) 1743 ;; activate the prefix setting (save-restriction does not help)
1805 (todos-show))))) 1744 (todos-category-select)))))
1806 1745
1807;; FIXME: should be defsubst? 1746;; FIXME: should be defsubst?
1808(defun todos-category-number (cat) 1747(defun todos-category-number (cat)
@@ -1823,75 +1762,50 @@ Number of entries for each category is given by `todos-print-priorities'."
1823 (concat "^" (regexp-quote (concat todos-category-beg name)) 1762 (concat "^" (regexp-quote (concat todos-category-beg name))
1824 "$")) 1763 "$"))
1825 (let ((begin (1+ (line-end-position))) 1764 (let ((begin (1+ (line-end-position)))
1826 (end (or (and (re-search-forward (concat "^" todos-category-beg) nil t) 1765 (end (if (re-search-forward (concat "^" todos-category-beg) nil t)
1827 (match-beginning 0)) 1766 (match-beginning 0)
1828 (point-max)))) 1767 (point-max))))
1829 (narrow-to-region begin end) 1768 (narrow-to-region begin end)
1830 (goto-char (point-min)))) 1769 (goto-char (point-min))))
1831 (todos-prefix-overlays) 1770 (todos-prefix-overlays)
1832 ;; display or hide done items as per todos-show-with-done 1771 (unless (eq major-mode 'todos-archive-mode)
1833 (save-excursion 1772 ;; display or hide done items as per todos-show-with-done
1834 (when (re-search-forward (concat "\n\\(\\[" (regexp-quote todos-done-string) 1773 (save-excursion
1835 "\\)") nil t) 1774 (when (re-search-forward (concat "\n\\(\\[" (regexp-quote todos-done-string)
1836 (let (done end done-sep prefix ov-pref ov-done) 1775 "\\)") nil t)
1837 (setq done (match-beginning 1) 1776 (let (done end done-sep prefix ov-pref ov-done)
1838 end (match-beginning 0)) 1777 (setq done (match-beginning 1)
1839 (if todos-show-with-done 1778 end (match-beginning 0))
1840 (progn 1779 (if todos-show-with-done
1841 (setq done-sep todos-done-separator) 1780 (progn
1842 (unless (string-match "^[[:space:]]*$" todos-done-separator) 1781 (setq done-sep todos-done-separator)
1843 (setq done-sep (propertize (concat todos-done-separator "\n") 1782 (unless (string-match "^[[:space:]]*$" todos-done-separator)
1844 'face 'todos-done-sep)) 1783 (setq done-sep (propertize (concat todos-done-separator "\n")
1845 (setq prefix (propertize 1784 'face 'todos-done-sep))
1846 (concat (if todos-number-prefix "1" todos-prefix) " ") 1785 (setq prefix (propertize (concat (if todos-number-prefix
1847 'face 'todos-prefix-string)) 1786 "1"
1848 ;; FIXME? Just deleting done-sep overlay results in bad 1787 todos-prefix) " ")
1849 ;; display (except when stepping though in edebug) 1788 'face 'todos-prefix-string))
1850 (remove-overlays done done) 1789 ;; FIXME? Just deleting done-sep overlay results in bad
1851 ;; must make separator overlay after making prefix overlay to get 1790 ;; display (except when stepping though in edebug)
1852 ;; the order separator before prefix 1791 (remove-overlays done done)
1853 (setq ov-pref (make-overlay done done) 1792 ;; must make separator overlay after making prefix overlay to get
1854 ov-done (make-overlay done done)) 1793 ;; the order separator before prefix
1855 (overlay-put ov-pref 'before-string prefix) 1794 (setq ov-pref (make-overlay done done)
1856 (overlay-put ov-done 'before-string done-sep))) 1795 ov-done (make-overlay done done))
1857 (narrow-to-region (point-min) end)))))) 1796 (overlay-put ov-pref 'before-string prefix)
1858 1797 (overlay-put ov-done 'before-string done-sep)))
1859;; FIXME: why autoload? 1798 (narrow-to-region (point-min) end)))))))
1860;;;###autoload
1861;; (defun todos-add-item-non-interactively (item category)
1862;; "Insert item ITEM into category CATEGORY and set its priority."
1863;; (todos-category-number category)
1864;; (todos-show) ; now at point-min
1865;; (unless (or (eq (point-min) (point-max)) ; no unfinished items
1866;; (when (re-search-forward (concat "^\\["
1867;; (regexp-quote todos-done-string))
1868;; nil t)
1869;; (forward-line -1)
1870;; (bobp))) ; there are done items but no unfinished items
1871;; (let* ((maxnum (1+ (car (todos-item-counts category))))
1872;; priority candidate prompt)
1873;; (while (null priority)
1874;; (setq candidate
1875;; (string-to-number (read-from-minibuffer
1876;; (concat prompt
1877;; (format "Set item priority (1-%d): "
1878;; maxnum)))))
1879;; (setq prompt
1880;; (when (or (< candidate 1) (> candidate maxnum))
1881;; (format "Priority must be an integer between 1 and %d.\n" maxnum)))
1882;; (unless prompt (setq priority candidate)))
1883;; (goto-char (point-min))
1884;; (unless (= priority 1) (todos-forward-item (1- priority)))))
1885;; (todos-insert-with-overlays item))
1886 1799
1887(defun todos-set-item-priority (item cat) 1800(defun todos-set-item-priority (item cat)
1888 "Set the priority of unfinished item ITEM in category CAT." 1801 "Set the priority of unfinished item ITEM in category CAT."
1889 (todos-category-number cat) 1802 (todos-category-number cat)
1890 (todos-category-select) 1803 (todos-category-select)
1891 (let* ((not-done (car (todos-item-counts cat))) 1804 (let* ((catsym (intern-soft (concat "todos-" cat)))
1892 (maxnum (1+ not-done)) 1805 (todo (get catsym 'todo))
1806 (maxnum (1+ todo))
1893 priority candidate prompt) 1807 priority candidate prompt)
1894 (unless (zerop not-done) 1808 (unless (zerop todo)
1895 (while (null priority) 1809 (while (null priority)
1896 (setq candidate 1810 (setq candidate
1897 (string-to-number (read-from-minibuffer 1811 (string-to-number (read-from-minibuffer
@@ -1907,13 +1821,14 @@ Number of entries for each category is given by `todos-print-priorities'."
1907 1821
1908(defun todos-jump-to-category-noninteractively (cat) 1822(defun todos-jump-to-category-noninteractively (cat)
1909 "" 1823 ""
1910 (let ((bufname (buffer-name))) 1824 ;; (let ((bufname (buffer-name)))
1911 (cond ((string= bufname todos-categories-buffer) 1825 ;; (cond ((string= bufname todos-categories-buffer)
1912 (switch-to-buffer (file-name-nondirectory todos-file-do))) 1826 ;; (switch-to-buffer (file-name-nondirectory todos-file-do)))
1913 ((string= bufname todos-archived-categories-buffer) 1827 ;; ((string= bufname todos-archived-categories-buffer)
1914 ;; FIXME: is pop-to-buffer better for this case? 1828 ;; ;; FIXME: is pop-to-buffer better for this case?
1915 (switch-to-buffer (file-name-nondirectory todos-archive-file)))) 1829 ;; (switch-to-buffer (file-name-nondirectory todos-archive-file))))
1916 (kill-buffer bufname)) 1830 ;; (kill-buffer bufname))
1831 (switch-to-buffer (file-name-nondirectory todos-current-todos-file))
1917 (widen) 1832 (widen)
1918 (goto-char (point-min)) 1833 (goto-char (point-min))
1919 (todos-category-number cat) 1834 (todos-category-number cat)
@@ -1924,9 +1839,7 @@ Number of entries for each category is given by `todos-print-priorities'."
1924 (todos-item-start) 1839 (todos-item-start)
1925 (insert item "\n") 1840 (insert item "\n")
1926 (todos-backward-item) 1841 (todos-backward-item)
1927 ;; (if todos-number-prefix 1842 (todos-prefix-overlays))
1928 ;; (todos-update-numbered-prefix)
1929 (todos-prefix-overlays));)
1930 1843
1931(defun todos-item-string-start () 1844(defun todos-item-string-start ()
1932 "Return the start of this TODO list entry as a string." 1845 "Return the start of this TODO list entry as a string."
@@ -1966,10 +1879,6 @@ Number of entries for each category is given by `todos-print-priorities'."
1966 (end (progn (todos-item-end) (1+ (point)))) 1879 (end (progn (todos-item-end) (1+ (point))))
1967 (ov-start (car (overlays-in beg beg)))) 1880 (ov-start (car (overlays-in beg beg))))
1968 (when ov-start 1881 (when ov-start
1969 ;; ;; don't cache numbers, since they can be popped out of order in
1970 ;; ;; todos-prefix-overlays
1971 ;; (unless todos-number-prefix
1972 ;; (push ov-start todos-item-start-overlays))
1973 (delete-overlay ov-start)) 1882 (delete-overlay ov-start))
1974 (delete-region beg end))) 1883 (delete-region beg end)))
1975 1884
@@ -1983,65 +1892,79 @@ Number of entries for each category is given by `todos-print-priorities'."
1983 (todos-item-start) 1892 (todos-item-start)
1984 (looking-at (concat "^\\[" (regexp-quote todos-done-string))))) 1893 (looking-at (concat "^\\[" (regexp-quote todos-done-string)))))
1985 1894
1986 1895(defun todos-make-categories-list ()
1987(defvar todos-categories-alist nil 1896 "Return a list of Todos categories and set their property lists.
1988 "Variable for storing the result of todos-make-categories-alist.") 1897The properties are at least the category number and the numbers
1989(defun todos-make-categories-alist () 1898of todo items, done items and archived items in the category."
1990 "Return an alist of categories and some of their properties. 1899 (let (catlist)
1991The properties are at least the numbers of the unfinished and
1992done items in the category."
1993 (let (todos-categories-alist)
1994 (save-excursion 1900 (save-excursion
1995 (save-restriction 1901 (save-restriction
1996 (widen) 1902 (widen)
1997 (goto-char (point-min)) 1903 (goto-char (point-min))
1998 (let ((not-done 0) 1904 (let ((num 0)
1999 (done 0) 1905 cat catsym archive-check)
2000 category beg end)
2001 (while (not (eobp)) 1906 (while (not (eobp))
2002 (cond ((looking-at (concat (regexp-quote todos-category-beg) 1907 (cond ((looking-at (concat (regexp-quote todos-category-beg)
2003 "\\(.*\\)\n")) 1908 "\\(.*\\)\n"))
2004 (setq not-done 0 done 0) 1909 (setq cat (match-string-no-properties 1))
2005 (push (list (match-string-no-properties 1) (cons not-done done)) 1910 (setq num (1+ num))
2006 todos-categories-alist)) 1911 (setq archive-check nil)
1912 ;; FIXME: ok to intern in global obarray?
1913 (setq catsym (intern (concat "todos-" cat)))
1914 (setplist catsym (list 'catnum num 'todo 0 'done 0 'archived 0))
1915 (push cat catlist))
2007 ((looking-at (concat "^\\[" (regexp-quote todos-done-string))) 1916 ((looking-at (concat "^\\[" (regexp-quote todos-done-string)))
2008 (setq done (1+ done)) 1917 (put catsym 'done (1+ (get catsym 'done))))
2009 (setcdr (cadr (car todos-categories-alist)) done))
2010 ((looking-at (concat "^\\[?" todos-date-pattern)) 1918 ((looking-at (concat "^\\[?" todos-date-pattern))
2011 (setq not-done (1+ not-done)) 1919 (put catsym 'todo (1+ (get catsym 'todo)))))
2012 (setcar (cadr (car todos-categories-alist)) not-done))) 1920 (unless (or archive-check
1921 (string= (buffer-file-name)
1922 (expand-file-name todos-archive-file)))
1923 (let ((archive (find-file-noselect todos-archive-file)))
1924 (with-current-buffer archive
1925 (goto-char (point-min))
1926 (when (re-search-forward
1927 (concat (regexp-quote todos-category-beg) cat)
1928 (point-max) t)
1929 (forward-line)
1930 (while (not (or (looking-at
1931 (concat (regexp-quote todos-category-beg)
1932 "\\(.*\\)\n"))
1933 (eobp)))
1934 (when (looking-at
1935 (concat "^\\[" (regexp-quote todos-done-string)))
1936 (put catsym 'archived (1+ (get catsym 'archived))))
1937 (forward-line)))))
1938 (setq archive-check t))
2013 (forward-line))))) 1939 (forward-line)))))
2014 todos-categories-alist)) 1940 catlist))
2015 1941
2016(defun todos-item-counts (cat &optional how) 1942(defun todos-item-counts (cat &optional how)
2017 "" 1943 ""
2018 (let* ((counts (cadr (assoc cat todos-categories-alist))) 1944 (let ((catsym (intern-soft (concat "todos-" cat))))
2019 (not-done (car counts)) 1945 ;; FIXME: need this?
2020 (done (cdr counts))) 1946 ;; (when catsym
2021 (cond ((eq how 'insert) 1947 (cond ((eq how 'insert)
2022 (setcar counts (1+ not-done))) 1948 (put catsym 'todo (1+ (get catsym 'todo))))
2023 ((eq how 'delete) 1949 ((eq how 'delete)
2024 (if (todos-done-item-p) ;FIXME: fails if last done item was deleted 1950 (if (todos-done-item-p) ;FIXME: fails if last done item was deleted
2025 (setcdr counts (1- done)) 1951 (put catsym 'done (1- (get catsym 'done)))
2026 (setcar counts (1- not-done)))) 1952 (put catsym 'todo (1- (get catsym 'todo)))))
2027 ;; ((eq how 'move-failed)
2028 ;; (setcar counts not-done))
2029 ((eq how 'done) 1953 ((eq how 'done)
2030 (setcar counts (1- not-done)) 1954 (put catsym 'todo (1- (get catsym 'todo)))
2031 (setcdr counts (1+ done))) 1955 (put catsym 'done (1+ (get catsym 'done))))
2032 ((eq how 'undo) 1956 ((eq how 'undo)
2033 (setcar counts (1+ not-done)) 1957 (put catsym 'todo (1+ (get catsym 'todo)))
2034 (setcdr counts (1- done))) 1958 (put catsym 'done (1- (get catsym 'done))))
2035 ((eq how 'archive) 1959 ((eq how 'archive)
2036 (setcdr counts 0)) 1960 (put catsym 'archived (+ (get catsym 'done) (get catsym 'archived)))
2037 (t 1961 (put catsym 'done 0)))))
2038 (cons not-done done)))))
2039 1962
2040(defun todos-longest-category-name-length (categories) 1963(defun todos-longest-category-name-length (categories)
2041 "" 1964 ""
2042 (let ((longest 0)) 1965 (let ((longest 0))
2043 (dolist (c categories longest) 1966 (dolist (c categories longest)
2044 (setq longest (max longest (length (car c))))))) 1967 (setq longest (max longest (length c))))))
2045 1968
2046(defun todos-string-count-lines (string) 1969(defun todos-string-count-lines (string)
2047 "Return the number of lines STRING spans." 1970 "Return the number of lines STRING spans."
@@ -2052,7 +1975,7 @@ done items in the category."
2052 (> (todos-string-count-lines string) 1)) 1975 (> (todos-string-count-lines string) 1))
2053 1976
2054(defun todos-read-category () 1977(defun todos-read-category ()
2055 "Return an existing category name, with tab completion." 1978 "Return a category name (existing names with tab completion)."
2056 ;; allow SPC to insert spaces, for adding new category names with 1979 ;; allow SPC to insert spaces, for adding new category names with
2057 ;; todos-move-item 1980 ;; todos-move-item
2058 (let ((map minibuffer-local-completion-map)) 1981 (let ((map minibuffer-local-completion-map))
@@ -2076,7 +1999,8 @@ done items in the category."
2076 (while (and (cond ((string= "" cat) 1999 (while (and (cond ((string= "" cat)
2077 (setq prompt "Enter a non-empty category name: ")) 2000 (setq prompt "Enter a non-empty category name: "))
2078 ((string-match "\\`\\s-+\\'" cat) 2001 ((string-match "\\`\\s-+\\'" cat)
2079 (setq prompt "Enter a category name that is not only white space: ")) 2002 (setq prompt
2003 "Enter a category name that is not only white space: "))
2080 ((member cat todos-categories) 2004 ((member cat todos-categories)
2081 (setq prompt "Enter a non-existing category name: "))) 2005 (setq prompt "Enter a non-existing category name: ")))
2082 (setq cat (read-from-minibuffer prompt))))) 2006 (setq cat (read-from-minibuffer prompt)))))
@@ -2120,28 +2044,28 @@ done items in the category."
2120 (let (valid answer) 2044 (let (valid answer)
2121 (while (not valid) 2045 (while (not valid)
2122 (setq answer (read-from-minibuffer 2046 (setq answer (read-from-minibuffer
2123 "Enter a clock time: ")) 2047 "Enter a clock time (or return for none): "))
2124 (when (or (string= "" answer) 2048 (when (or (string= "" answer)
2125 (string-match diary-time-regexp answer)) 2049 (string-match diary-time-regexp answer))
2126 (setq valid t))) 2050 (setq valid t)))
2127 answer)) 2051 answer))
2128 2052
2129(defun todos-categories-list (buf) 2053;; (defun todos-categories-list (buf)
2130 "Return a list of the Todo mode categories in buffer BUF." 2054;; "Return a list of the Todo mode categories in buffer BUF."
2131 (let (categories) 2055;; (let (categories)
2132 (with-current-buffer buf 2056;; (with-current-buffer buf
2133 (save-excursion 2057;; (save-excursion
2134 (save-restriction 2058;; (save-restriction
2135 (widen) 2059;; (widen)
2136 (goto-char (point-max)) 2060;; (goto-char (point-max))
2137 (while (re-search-backward (concat "^" (regexp-quote todos-category-beg) 2061;; (while (re-search-backward (concat "^" (regexp-quote todos-category-beg)
2138 "\\(.*\\)\n") nil t) 2062;; "\\(.*\\)\n") nil t)
2139 (push (match-string-no-properties 1) categories))))) 2063;; (push (match-string-no-properties 1) categories)))))
2140 categories)) 2064;; categories))
2141 2065
2142(defun todos-padded-string (str) 2066(defun todos-padded-string (str)
2143 "" 2067 ""
2144 (let* ((len (todos-longest-category-name-length todos-categories-alist)) 2068 (let* ((len (todos-longest-category-name-length todos-categories))
2145 (strlen (length str)) 2069 (strlen (length str))
2146 (strlen-odd (eq (logand strlen 1) 1)) ; oddp from cl.el 2070 (strlen-odd (eq (logand strlen 1) 1)) ; oddp from cl.el
2147 (padding (/ (- len strlen) 2))) 2071 (padding (/ (- len strlen) 2)))
@@ -2150,9 +2074,8 @@ done items in the category."
2150 2074
2151(defun todos-insert-category-name (cat &optional nonum) 2075(defun todos-insert-category-name (cat &optional nonum)
2152 "" 2076 ""
2153 (let* ((buf (get-buffer (file-name-nondirectory todos-file-do))) 2077 (let ((catsym (intern-soft (concat "todos-" cat)))
2154 (cat-alist todos-categories-alist) 2078 (archive (string= todos-current-todos-file todos-archive-file)))
2155 (counts (todos-item-counts cat)))
2156 ;; num is declared in caller 2079 ;; num is declared in caller
2157 (setq num (1+ num)) 2080 (setq num (1+ num))
2158 (if nonum 2081 (if nonum
@@ -2163,11 +2086,17 @@ done items in the category."
2163 'action 2086 'action
2164 `(lambda (button) 2087 `(lambda (button)
2165 (todos-jump-to-category-noninteractively ,cat))) 2088 (todos-jump-to-category-noninteractively ,cat)))
2166 (insert (make-string 8 32) 2089 (insert (concat (make-string 8 32)
2167 (format "%2d" (car counts)) 2090 (unless archive
2168 (make-string 5 32) 2091 (concat
2169 (format "%2d" (cdr counts))) 2092 (format "%2d" (get catsym 'todo))
2170 (newline))) 2093 (make-string 5 32)))
2094 (format "%2d" (get catsym 'done))
2095 (unless archive
2096 (concat
2097 (make-string 5 32)
2098 (format "%2d" (get catsym 'archived))))
2099 "\n"))))
2171 2100
2172(defun todos-initial-setup () 2101(defun todos-initial-setup ()
2173 "Set up things to work properly in TODO mode." 2102 "Set up things to work properly in TODO mode."
@@ -2178,4 +2107,25 @@ done items in the category."
2178 2107
2179(provide 'todos) 2108(provide 'todos)
2180 2109
2110;;; UI
2111;; - display
2112;; - show todos in cat
2113;; - show done in cat
2114;; - show catlist
2115;; - show top priorities in all cats
2116;; - show archived
2117;; - navigation
2118;; -
2119;; - editing
2120;;
2121;;; Internals
2122;; - cat props: name, number, todos, done, archived
2123;; - item props: priority, date-time, status?
2124;; - file format
2125;; - cat begin
2126;; - todo items 0...n
2127;; - empty line
2128;; - done-separator
2129;; - done item 0...n
2130
2181;;; todos.el ends here 2131;;; todos.el ends here