aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Seidel1997-10-16 21:21:16 +0000
committerOliver Seidel1997-10-16 21:21:16 +0000
commit01b864bc53fa6b78966ee7af3f5adb514e189e3e (patch)
tree753b26a433d1198da37c7334696c841214748166
parent7b33b170cd6d431f6c307e075d3554538ea4a2b2 (diff)
downloademacs-01b864bc53fa6b78966ee7af3f5adb514e189e3e.tar.gz
emacs-01b864bc53fa6b78966ee7af3f5adb514e189e3e.zip
Jari Aalto <jari.aalto@ntc.nokia.com> writes:
I just downloaded your package and after reading the docs I decided to do some reformatting. Hope you don't mind. Now they are in such a format that the html page can be automatically generated from the source file. As an example, I generated the attached page using the following command: ripdoc.pls | \ t2html.pls -a "Oliver.Seidel" -e Oliver.Seidel@cl.cam.ac.uk -simple And of course I appreciate it. Jari's stuff can be found at: ftp://cs.uta.fi/pub/ssjaaa/, while I'm making the 1997-10-15T17:18:11Z!os10000@seidel-space.de page available at http://www.cl.cam.ac.uk/users/os10000/doc/todo-mode.html (That link will be valid until 10/1998 or slightly longer.)
-rw-r--r--lisp/calendar/todo-mode.el609
1 files changed, 299 insertions, 310 deletions
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 723549071d5..078bbd1dfd1 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -1,10 +1,10 @@
1;;; todo-mode.el -- Major mode for editing TODO list files 1;; todo-mode.el -- Major mode for editing TODO list files
2 2
3;; Copyright (C) 1997 Free Software Foundation, Inc. 3;; Copyright (C) 1997 Free Software Foundation, Inc.
4 4
5;; Author: Oliver.Seidel@cl.cam.ac.uk (was valid on Aug 2, 1997) 5;; Author: Oliver.Seidel@cl.cam.ac.uk (was valid on Aug 2, 1997)
6;; Created: 2 Aug 1997 6;; Created: 2 Aug 1997
7;; Version: $Id: todo-mode.el,v 1.17 1997/10/15 14:30:41 os10000 Exp os10000 $ 7;; Version: $Id: todo-mode.el,v 1.18 1997/10/15 17:18:11 os10000 Exp os10000 $
8;; Keywords: Categorised TODO list editor, todo-mode 8;; Keywords: Categorised TODO list editor, todo-mode
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -28,194 +28,177 @@
28 28
29;;; Commentary: 29;;; Commentary:
30 30
31;; Quickstart Installation: 31;; Preface, Quickstart Installation
32;; ========================
33;; 32;;
34;; To get this to work, make emacs execute the line 33;; To get this to work, make emacs execute the line
35;; 34;;
36;; (require 'todo-mode) ;; load the TODO package 35;; (require 'todo-mode) ;; load the TODO package
37;; 36;;
38;; You may now enter new items by typing "M-x todo-insert-item", or enter 37;; You may now enter new items by typing "M-x todo-insert-item", or enter
39;; your the TODO list file by typing "M-x todo-show". 38;; your the TODO list file by typing "M-x todo-show".
40;; 39;;
41;; The TODO list file has a special format and some auxiliary information, 40;; The TODO list file has a special format and some auxiliary
42;; which will be added by the todo-show function if it attempts to visit 41;; information, which will be added by the todo-show function if it
43;; an un-initialised file. Hence it is recommended to use the todo-show 42;; attempts to visit an un-initialised file. Hence it is
44;; function for the first time, in order to initialise the file, but it 43;; recommended to use the todo-show function for the first time, in
45;; is not necessary afterwards. 44;; order to initialise the file, but it is not necessary
45;; afterwards.
46;; 46;;
47;; As these commands are quite long to type, I would recommend the addition 47;; As these commands are quite long to type, I would recommend the
48;; of two bindings to your to your global keymap. I personally have the 48;; addition of two bindings to your to your global keymap. I
49;; following in my initialisation file: 49;; personally have the following in my initialisation file:
50;;
51;; (global-set-key "\C-ct" 'todo-show) ;; switch to TODO buffer
52;; (global-set-key "\C-ci" 'todo-insert-item) ;; insert new item
53;;
54;; Note, however, that this recommendation has prompted some criticism,
55;; since the keys C-c LETTER are reserved for user functions. I believe
56;; my recommendation is acceptable, since the Emacs Lisp Manual *Tips*
57;; section also details that the mode itself should not bind any functions
58;; to those keys. The express aim of the above two bindings is to work
59;; outside the mode, which doesn't need the show function and offers
60;; a different binding for the insert function. They serve as shortcuts
61;; and are not even needed (since the TODO mode will be entered by
62;; visiting the TODO file, and later by switching to its buffer).
63;; 50;;
51;; (global-set-key "\C-ct" 'todo-show) ;; switch to TODO buffer
52;; (global-set-key "\C-ci" 'todo-insert-item) ;; insert new item
64;; 53;;
54;; Note, however, that this recommendation has prompted some
55;; criticism, since the keys C-c LETTER are reserved for user
56;; functions. I believe my recommendation is acceptable, since the
57;; Emacs Lisp Manual *Tips* section also details that the mode itself
58;; should not bind any functions to those keys. The express aim of
59;; the above two bindings is to work outside the mode, which doesn't
60;; need the show function and offers a different binding for the
61;; insert function. They serve as shortcuts and are not even needed
62;; (since the TODO mode will be entered by visiting the TODO file, and
63;; later by switching to its buffer).
65;; 64;;
66;; Pre-Requisites 65;; Pre-Requisites
67;; ==============
68;;
69;; This package will require the following packages to be available on
70;; the load-path:
71;; - time-stamp
72;; - easymenu
73;;
74;;
75;;
76;; Description:
77;; ============
78;;
79;; TODO is a major mode for EMACS which offers functionality to treat
80;; most lines in one buffer as a list of items one has to do. There
81;; are facilities to add new items, which are categorised, to edit or
82;; even delete items from the buffer. The buffer contents are currently
83;; compatible with the diary, so that the list of todo-items will show
84;; up in the FANCY diary mode.
85;;
86;; Notice: Besides the major mode, this file also exports the function
87;; "todo-show" which will change to the one specific TODO file that has
88;; been specified in the todo-file-do variable. If this file does not
89;; conform to the TODO mode conventions, the todo-show function will add
90;; the appropriate header and footer. I don't anticipate this to cause
91;; much grief, but be warned, in case you attempt to read a plain text file.
92;;
93;;
94;;
95;; Operation:
96;; ==========
97;;
98;; You will have the following facilities available:
99;;
100;; M-x todo-show will enter the todo list screen, here type
101;;
102;; + to go to next category
103;; - to go to previous category
104;; e to edit the current entry
105;; f to file the current entry, including a
106;; comment and timestamp
107;; i to insert a new entry
108;; k to kill the current entry
109;; l to lower the current entry's priority
110;; n for the next entry
111;; p for the previous entry
112;; q to save the list and exit the buffer
113;; r to raise the current entry's priority
114;; s to save the list
115;;
116;; When you add a new entry, you are asked for the text and then for the
117;; category. I for example have categories for things that I want to do
118;; in the office (like mail my mum), that I want to do in town (like buy
119;; cornflakes) and things I want to do at home (move my suitcases). The
120;; categories can be selected with the cursor keys and if you type in the
121;; name of a category which didn't exist before, an empty category of the
122;; desired name will be added and filled with the new entry.
123;;
124;;
125;;
126;; Configuration:
127;; ==============
128;;
129;; --- todo-prefix
130;;
131;; I would like to recommend that you use the prefix "*/*" (by
132;; leaving the variable 'todo-prefix' untouched) so that the diary
133;; displays each entry every day.
134;;
135;; To understand what I mean, please read the documentation that goes
136;; with the calendar since that will tell you how you can set up the
137;; fancy diary display and use the #include command to include your
138;; todo list file as part of your diary.
139;;
140;; If you have the diary package set up to usually display more than
141;; one day's entries at once, consider using
142;; "&%%(equal (calendar-current-date) date)"
143;; as the value of `todo-prefix'. Please note that this may slow down
144;; the processing of your diary file some.
145;;
146;;
147;; --- todo-file-do
148;; 66;;
149;; This variable is fairly self-explanatory. You have to store your TODO 67;; This package will require the following packages to be available on
150;; list somewhere. This variable tells the package where to go and find 68;; the load-path:
151;; this file. 69;;
152;; 70;; time-stamp
153;; 71;; easymenu
154;; --- todo-file-done 72;;
155;; 73;; Mode Description
156;; Even when you're done, you may wish to retain the entries. Given 74;;
157;; that they're timestamped and you are offered to add a comment, this 75;; TODO is a major mode for EMACS which offers functionality to treat
158;; can make a useful diary of past events. It will even blend in with 76;; most lines in one buffer as a list of items one has to do. There
159;; the EMACS diary package. So anyway, this variable holds the name 77;; are facilities to add new items, which are categorised, to edit or
160;; of the file for the filed todo-items. 78;; even delete items from the buffer. The buffer contents are
161;; 79;; currently compatible with the diary, so that the list of todo-items
162;; 80;; will show up in the FANCY diary mode.
163;; --- todo-mode-hook 81;;
164;; 82;; Notice: Besides the major mode, this file also exports the function
165;; Just like other modes, too, this mode offers to call your functions 83;; "todo-show" which will change to the one specific TODO file that
166;; before it goes about its business. This variable will be inspected 84;; has been specified in the todo-file-do variable. If this file does
167;; for any functions you may wish to have called once the other TODO 85;; not conform to the TODO mode conventions, the todo-show function
168;; mode preparations have been completed. 86;; will add the appropriate header and footer. I don't anticipate
169;; 87;; this to cause much grief, but be warned, in case you attempt to
170;; 88;; read a plain text file.
171;; --- todo-insert-threshold 89;;
172;; 90;; Operation
173;; Another nifty feature is the insertion accuracy. If you have 8 items 91;;
174;; in your TODO list, then you may get asked 4 questions by the binary 92;; You will have the following facilities available:
175;; insertion algorithm. However, you may not really have a need for such 93;;
176;; accurate priorities amongst your TODO items. If you now think about 94;; M-x todo-show will enter the todo list screen, here type
177;; the binary insertion halfing the size of the window each time, then 95;;
178;; the threshhold is the window size at which it will stop. If you set 96;; + to go to next category
179;; the threshhold to zero, the upper and lower bound will coincide at the 97;; - to go to previous category
180;; end of the loop and you will insert your item just before that point. 98;; e to edit the current entry
181;; If you set the threshhold to i.e. 8, it will stop as soon as the window 99;; f to file the current entry, including a
182;; size drops below that amount and will insert the item in the approximate 100;; comment and timestamp
183;; centre of that window. I got the idea for this feature after reading 101;; i to insert a new entry
184;; a very helpful e-mail reply from Trey Jackson <trey@cs.berkeley.edu> 102;; k to kill the current entry
185;; who corrected some of my awful coding and pointed me towards some good 103;; l to lower the current entry's priority
186;; reading. Thanks Trey! 104;; n for the next entry
187;; 105;; p for the previous entry
188;; 106;; q to save the list and exit the buffer
189;; 107;; r to raise the current entry's priority
190;; 108;; s to save the list
191;; Things to do: 109;;
192;; ============= 110;; When you add a new entry, you are asked for the text and then for
193;; 111;; the category. I for example have categories for things that I want
194;; - licence / version function 112;; to do in the office (like mail my mum), that I want to do in town
195;; - export to diary file 113;; (like buy cornflakes) and things I want to do at home (move my
196;; - todo-report-bug 114;; suitcases). The categories can be selected with the cursor keys
197;; - GNATS support 115;; and if you type in the name of a category which didn't exist
198;; - add idea from Urban Boquist <boquist@cs.chalmers.se>: multi-line-entries 116;; before, an empty category of the desired name will be added and
199;; - 'e' opens buffer for multi-line entry 117;; filled with the new entry.
200;; - elide multiline 118;;
201;; - rewrite complete package to store data as lisp objects and have 119;; Configuration
202;; display modes for display, for diary export, etc. 120;;
203;; 121;; Variable todo-prefix
204;; 122;;
205;; 123;; I would like to recommend that you use the prefix "*/*" (by
206;; History and Gossip: 124;; leaving the variable 'todo-prefix' untouched) so that the diary
207;; =================== 125;; displays each entry every day.
208;; 126;;
209;; Many thanks to all the ones who have contributed to the evolution of this 127;; To understand what I mean, please read the documentation that goes
210;; package! I hope I have listed all of you somewhere in the documentation 128;; with the calendar since that will tell you how you can set up the
211;; or at least in the RCS history! 129;; fancy diary display and use the #include command to include your
212;; 130;; todo list file as part of your diary.
213;; Enjoy this package and express your gratitude by sending nice things 131;;
214;; to my parents' address! 132;; If you have the diary package set up to usually display more than
215;; 133;; one day's entries at once, consider using
216;; Oliver Seidel 134;;
217;; 135;; "&%%(equal (calendar-current-date) date)"
218;; (O Seidel, Lessingstr. 8, 65760 Eschborn, Federal Republic of Germany) 136;;
137;; as the value of `todo-prefix'. Please note that this may slow down
138;; the processing of your diary file some.
139;;
140;; Variable todo-file-do
141;;
142;; This variable is fairly self-explanatory. You have to store your TODO
143;; list somewhere. This variable tells the package where to go and find
144;; this file.
145;;
146;; Variable todo-file-done
147;;
148;; Even when you're done, you may wish to retain the entries. Given
149;; that they're timestamped and you are offered to add a comment, this
150;; can make a useful diary of past events. It will even blend in with
151;; the EMACS diary package. So anyway, this variable holds the name
152;; of the file for the filed todo-items.
153;;
154;; Variable todo-mode-hook
155;;
156;; Just like other modes, too, this mode offers to call your functions
157;; before it goes about its business. This variable will be inspected
158;; for any functions you may wish to have called once the other TODO
159;; mode preparations have been completed.
160;;
161;; Variables todo-insert-threshold
162;;
163;; Another nifty feature is the insertion accuracy. If you have 8
164;; items in your TODO list, then you may get asked 4 questions by the
165;; binary insertion algorithm. However, you may not really have a
166;; need for such accurate priorities amongst your TODO items. If you
167;; now think about the binary insertion halfing the size of the window
168;; each time, then the threshhold is the window size at which it will
169;; stop. If you set the threshhold to zero, the upper and lower bound
170;; will coincide at the end of the loop and you will insert your item
171;; just before that point. If you set the threshhold to i.e. 8, it
172;; will stop as soon as the window size drops below that amount and
173;; will insert the item in the approximate centre of that window. I
174;; got the idea for this feature after reading a very helpful e-mail
175;; reply from Trey Jackson <trey@cs.berkeley.edu> who corrected some
176;; of my awful coding and pointed me towards some good reading.
177;; Thanks Trey!
178;;
179;; Things to do
180;;
181;; o licence / version function
182;; o export to diary file
183;; o todo-report-bug
184;; o GNATS support
185;; o elide multiline
186;; o rewrite complete package to store data as lisp objects and have
187;; display modes for display, for diary export, etc.
188;; (Richard Stallman pointed out this is a bad idea)
189;; o base todo-mode.el on generic-mode.el instead
190;;
191;; History and Gossip
192;;
193;; Many thanks to all the ones who have contributed to the evolution
194;; of this package! I hope I have listed all of you somewhere in the
195;; documentation or at least in the RCS history!
196;;
197;; Enjoy this package and express your gratitude by sending nice things
198;; to my parents' address!
199;;
200;; Oliver Seidel
201;; (O Seidel, Lessingstr. 8, 65760 Eschborn, Federal Republic of Germany)
219;; 202;;
220 203
221;; --------------------------------------------------------------------------- 204;; ---------------------------------------------------------------------------
@@ -225,6 +208,12 @@
225;;; Change Log: 208;;; Change Log:
226 209
227;; $Log: todo-mode.el,v $ 210;; $Log: todo-mode.el,v $
211;; Revision 1.18 1997/10/15 17:18:11 os10000
212;; Everything seems to work in Harald Melands Emacs 20.02 and
213;; my Emacs 19.34. Beware of the spelling in some of the
214;; variable names. I looked up "threshold" in a dictionary
215;; and here in Britain this appears to be the way to spell it.
216;;
228;; Revision 1.17 1997/10/15 14:30:41 os10000 217;; Revision 1.17 1997/10/15 14:30:41 os10000
229;; Attempted to reconcile Harald's changes with mine since 1.15. 218;; Attempted to reconcile Harald's changes with mine since 1.15.
230;; 219;;
@@ -313,13 +302,13 @@
313 302
314;; User-configurable variables: 303;; User-configurable variables:
315 304
316(defvar todo-prefix "*/*" "*TODO mode prefix for entries.") 305(defvar todo-prefix "*/*" "*TODO mode prefix for entries.")
317(defvar todo-file-do "~/.todo-do" "*TODO mode list file.") 306(defvar todo-file-do "~/.todo-do" "*TODO mode list file.")
318(defvar todo-file-done "~/.todo-done" "*TODO mode archive file.") 307(defvar todo-file-done "~/.todo-done" "*TODO mode archive file.")
319(defvar todo-mode-hook nil "*TODO mode hooks.") 308(defvar todo-mode-hook nil "*TODO mode hooks.")
320(defvar todo-edit-mode-hook nil "*TODO Edit mode hooks.") 309(defvar todo-edit-mode-hook nil "*TODO Edit mode hooks.")
321(defvar todo-insert-threshold 0 "*TODO mode insertion accuracy.") 310(defvar todo-insert-threshold 0 "*TODO mode insertion accuracy.")
322(defvar todo-edit-buffer " *TODO Edit*" "TODO Edit buffer name.") 311(defvar todo-edit-buffer " *TODO Edit*" "TODO Edit buffer name.")
323 312
324;; Thanks for the ISO time stamp format go to Karl Eichwalder <ke@suse.de> 313;; Thanks for the ISO time stamp format go to Karl Eichwalder <ke@suse.de>
325;; My format string for the appt.el package is "%3b %2d, %y, %02I:%02M%p". 314;; My format string for the appt.el package is "%3b %2d, %y, %02I:%02M%p".
@@ -340,13 +329,13 @@ For details see the variable `time-stamp-format'.")
340 329
341;; Set up some helpful context ... 330;; Set up some helpful context ...
342 331
343(defvar todo-categories nil "TODO categories.") 332(defvar todo-categories nil "TODO categories.")
344(defvar todo-cats nil 333(defvar todo-cats nil
345 "Old variable for holding the TODO categories. Use `todo-categories' instead.") 334 "Old variable for holding the TODO categories. Use `todo-categories' instead.")
346(defvar todo-previous-line 0 "Previous line that I asked about.") 335(defvar todo-previous-line 0 "Previous line that I asked about.")
347(defvar todo-previous-answer 0 "Previous answer that I got.") 336(defvar todo-previous-answer 0 "Previous answer that I got.")
348(defvar todo-mode-map nil "TODO mode keymap.") 337(defvar todo-mode-map nil "TODO mode keymap.")
349(defvar todo-category-number 0 "TODO category number.") 338(defvar todo-category-number 0 "TODO category number.")
350 339
351;; --------------------------------------------------------------------------- 340;; ---------------------------------------------------------------------------
352 341
@@ -373,7 +362,7 @@ For details see the variable `time-stamp-format'.")
373 "Make TODO mode display the current category correctly." 362 "Make TODO mode display the current category correctly."
374 (let ((name (nth todo-category-number todo-categories))) 363 (let ((name (nth todo-category-number todo-categories)))
375 (setq mode-line-buffer-identification 364 (setq mode-line-buffer-identification
376 (concat "Category: " name)) 365 (concat "Category: " name))
377 (widen) 366 (widen)
378 (goto-char (point-min)) 367 (goto-char (point-min))
379 (search-forward-regexp 368 (search-forward-regexp
@@ -387,14 +376,14 @@ For details see the variable `time-stamp-format'.")
387(defun todo-forward-category () "Go forward to TODO list of next category." 376(defun todo-forward-category () "Go forward to TODO list of next category."
388 (interactive) 377 (interactive)
389 (setq todo-category-number 378 (setq todo-category-number
390 (mod (1+ todo-category-number) (length todo-categories))) 379 (mod (1+ todo-category-number) (length todo-categories)))
391 (todo-category-select)) 380 (todo-category-select))
392(defalias 'todo-cmd-forw 'todo-forward-category) 381(defalias 'todo-cmd-forw 'todo-forward-category)
393 382
394(defun todo-backward-category () "Go back to TODO list of previous category." 383(defun todo-backward-category () "Go back to TODO list of previous category."
395 (interactive) 384 (interactive)
396 (setq todo-category-number 385 (setq todo-category-number
397 (mod (1- todo-category-number) (length todo-categories))) 386 (mod (1- todo-category-number) (length todo-categories)))
398 (todo-category-select)) 387 (todo-category-select))
399(defalias 'todo-cmd-back 'todo-backward-category) 388(defalias 'todo-cmd-back 'todo-backward-category)
400 389
@@ -429,12 +418,12 @@ For details see the variable `time-stamp-format'.")
429 (interactive) 418 (interactive)
430 (let ((item (todo-item-string))) 419 (let ((item (todo-item-string)))
431 (if (todo-string-multiline-p item) 420 (if (todo-string-multiline-p item)
432 (todo-edit-multiline) 421 (todo-edit-multiline)
433 (let ((new (read-from-minibuffer "Edit: " item))) 422 (let ((new (read-from-minibuffer "Edit: " item)))
434 (todo-remove-item) 423 (todo-remove-item)
435 (insert new "\n") 424 (insert new "\n")
436 (todo-backward-item) 425 (todo-backward-item)
437 (message ""))))) 426 (message "")))))
438(defalias 'todo-cmd-edit 'todo-edit-item) 427(defalias 'todo-cmd-edit 'todo-edit-item)
439 428
440(defun todo-edit-multiline () 429(defun todo-edit-multiline ()
@@ -442,7 +431,7 @@ For details see the variable `time-stamp-format'.")
442 (interactive) 431 (interactive)
443 (let ((buffer-name (generate-new-buffer-name todo-edit-buffer))) 432 (let ((buffer-name (generate-new-buffer-name todo-edit-buffer)))
444 (switch-to-buffer (make-indirect-buffer (file-name-nondirectory todo-file-do) 433 (switch-to-buffer (make-indirect-buffer (file-name-nondirectory todo-file-do)
445 buffer-name)) 434 buffer-name))
446 (message "To exit, simply kill this buffer and return to list.") 435 (message "To exit, simply kill this buffer and return to list.")
447 (todo-edit-mode) 436 (todo-edit-mode)
448 (narrow-to-region (todo-item-start) (todo-item-end)))) 437 (narrow-to-region (todo-item-start) (todo-item-end))))
@@ -457,43 +446,43 @@ For details see the variable `time-stamp-format'.")
457 (let ((posn (search-forward "-*- mode: todo; " 17 t))) 446 (let ((posn (search-forward "-*- mode: todo; " 17 t)))
458 (if (not (null posn)) (goto-char posn)) 447 (if (not (null posn)) (goto-char posn))
459 (if (equal posn nil) 448 (if (equal posn nil)
460 (progn 449 (progn
461 (insert "-*- mode: todo; \n") 450 (insert "-*- mode: todo; \n")
462 (forward-char -1)) 451 (forward-char -1))
463 (kill-line))) 452 (kill-line)))
464 (insert (format "todo-categories: %S; -*-" todo-categories)) 453 (insert (format "todo-categories: %S; -*-" todo-categories))
465 (forward-char 1) 454 (forward-char 1)
466 (insert (format "%s --- %s\n--- End\n%s %s\n" 455 (insert (format "%s --- %s\n--- End\n%s %s\n"
467 todo-prefix cat todo-prefix (make-string 75 ?-)))) 456 todo-prefix cat todo-prefix (make-string 75 ?-))))
468 0) 457 0)
469 458
470(defun todo-insert-item () 459(defun todo-insert-item ()
471 "Insert new TODO list entry." 460 "Insert new TODO list entry."
472 (interactive) 461 (interactive)
473 (let* ((new-item (concat todo-prefix " " 462 (let* ((new-item (concat todo-prefix " "
474 (read-from-minibuffer "New TODO entry: "))) 463 (read-from-minibuffer "New TODO entry: ")))
475 (categories todo-categories) 464 (categories todo-categories)
476 (history (cons 'categories (1+ todo-category-number))) 465 (history (cons 'categories (1+ todo-category-number)))
477 (category (completing-read "Category: " 466 (category (completing-read "Category: "
478 (todo-category-alist) nil nil 467 (todo-category-alist) nil nil
479 (nth todo-category-number todo-categories) 468 (nth todo-category-number todo-categories)
480 history))) 469 history)))
481 (let ((cat-exists (member category todo-categories))) 470 (let ((cat-exists (member category todo-categories)))
482 (setq todo-category-number 471 (setq todo-category-number
483 (if cat-exists 472 (if cat-exists
484 (- (length todo-categories) (length cat-exists)) 473 (- (length todo-categories) (length cat-exists))
485 (todo-add-category category)))) 474 (todo-add-category category))))
486 (todo-show) 475 (todo-show)
487 (setq todo-previous-line 0) 476 (setq todo-previous-line 0)
488 (let ((top 1) 477 (let ((top 1)
489 (bottom (1+ (count-lines (point-min) (point-max))))) 478 (bottom (1+ (count-lines (point-min) (point-max)))))
490 (while (> (- bottom top) todo-insert-threshold) 479 (while (> (- bottom top) todo-insert-threshold)
491 (let* ((current (/ (+ top bottom) 2)) 480 (let* ((current (/ (+ top bottom) 2))
492 (answer (if (< current bottom) 481 (answer (if (< current bottom)
493 (todo-more-important-p current) nil))) 482 (todo-more-important-p current) nil)))
494 (if answer 483 (if answer
495 (setq bottom current) 484 (setq bottom current)
496 (setq top (1+ current))))) 485 (setq top (1+ current)))))
497 (setq top (/ (+ top bottom) 2)) 486 (setq top (/ (+ top bottom) 2))
498 ;; goto-line doesn't have the desired behavior in a narrowed buffer 487 ;; goto-line doesn't have the desired behavior in a narrowed buffer
499 (goto-char (point-min)) 488 (goto-char (point-min))
@@ -504,16 +493,16 @@ For details see the variable `time-stamp-format'.")
504 (message ""))) 493 (message "")))
505(defalias 'todo-cmd-inst 'todo-insert-item) 494(defalias 'todo-cmd-inst 'todo-insert-item)
506 495
507(defun todo-more-important-p (line) 496(defun todo-more-important-p (line)
508 "Ask whether entry is more important than the one at LINE." 497 "Ask whether entry is more important than the one at LINE."
509 (if (not (equal todo-previous-line line)) 498 (if (not (equal todo-previous-line line))
510 (progn 499 (progn
511 (setq todo-previous-line line) 500 (setq todo-previous-line line)
512 (goto-char (point-min)) 501 (goto-char (point-min))
513 (forward-line (1- todo-previous-line)) 502 (forward-line (1- todo-previous-line))
514 (let ((item (todo-item-string-start))) 503 (let ((item (todo-item-string-start)))
515 (setq todo-previous-answer 504 (setq todo-previous-answer
516 (y-or-n-p (concat "More important than '" item "'? ")))))) 505 (y-or-n-p (concat "More important than '" item "'? "))))))
517 todo-previous-answer) 506 todo-previous-answer)
518(defalias 'todo-ask-p 'todo-more-important-p) 507(defalias 'todo-ask-p 'todo-more-important-p)
519 508
@@ -521,13 +510,13 @@ For details see the variable `time-stamp-format'.")
521 (interactive) 510 (interactive)
522 (if (> (count-lines (point-min) (point-max)) 0) 511 (if (> (count-lines (point-min) (point-max)) 0)
523 (let* ((todo-entry (todo-item-string-start)) 512 (let* ((todo-entry (todo-item-string-start))
524 (todo-answer (y-or-n-p (concat "Permanently remove '" 513 (todo-answer (y-or-n-p (concat "Permanently remove '"
525 todo-entry "'? ")))) 514 todo-entry "'? "))))
526 (if todo-answer 515 (if todo-answer
527 (progn 516 (progn
528 (todo-remove-item) 517 (todo-remove-item)
529 (todo-backward-item))) 518 (todo-backward-item)))
530 (message "")) 519 (message ""))
531 (error "No TODO list entry to delete"))) 520 (error "No TODO list entry to delete")))
532(defalias 'todo-cmd-kill 'todo-delete-item) 521(defalias 'todo-cmd-kill 'todo-delete-item)
533 522
@@ -535,11 +524,11 @@ For details see the variable `time-stamp-format'.")
535 (interactive) 524 (interactive)
536 (if (> (count-lines (point-min) (point)) 0) 525 (if (> (count-lines (point-min) (point)) 0)
537 (let ((item (todo-item-string))) 526 (let ((item (todo-item-string)))
538 (todo-remove-item) 527 (todo-remove-item)
539 (todo-backward-item) 528 (todo-backward-item)
540 (save-excursion 529 (save-excursion
541 (insert item "\n")) 530 (insert item "\n"))
542 (message "")) 531 (message ""))
543 (error "No TODO list entry to raise"))) 532 (error "No TODO list entry to raise")))
544(defalias 'todo-cmd-rais 'todo-raise-item) 533(defalias 'todo-cmd-rais 'todo-raise-item)
545 534
@@ -547,11 +536,11 @@ For details see the variable `time-stamp-format'.")
547 (interactive) 536 (interactive)
548 (if (> (count-lines (point) (point-max)) 1) ; Assume there is a final newline 537 (if (> (count-lines (point) (point-max)) 1) ; Assume there is a final newline
549 (let ((item (todo-item-string))) 538 (let ((item (todo-item-string)))
550 (todo-remove-item) 539 (todo-remove-item)
551 (todo-forward-item) 540 (todo-forward-item)
552 (save-excursion 541 (save-excursion
553 (insert item "\n")) 542 (insert item "\n"))
554 (message "")) 543 (message ""))
555 (error "No TODO list entry to lower"))) 544 (error "No TODO list entry to lower")))
556(defalias 'todo-cmd-lowr 'todo-lower-item) 545(defalias 'todo-cmd-lowr 'todo-lower-item)
557 546
@@ -559,26 +548,26 @@ For details see the variable `time-stamp-format'.")
559 (interactive) 548 (interactive)
560 (if (> (count-lines (point-min) (point-max)) 0) 549 (if (> (count-lines (point-min) (point-max)) 0)
561 (let ((comment (read-from-minibuffer "Comment: ")) 550 (let ((comment (read-from-minibuffer "Comment: "))
562 (time-stamp-format todo-time-string-format)) 551 (time-stamp-format todo-time-string-format))
563 (if (> (length comment) 0) 552 (if (> (length comment) 0)
564 (progn 553 (progn
565 (goto-char (todo-item-end)) 554 (goto-char (todo-item-end))
566 (insert (if (save-excursion (beginning-of-line) 555 (insert (if (save-excursion (beginning-of-line)
567 (looking-at (regexp-quote todo-prefix))) 556 (looking-at (regexp-quote todo-prefix)))
568 " " 557 " "
569 "\n\t") 558 "\n\t")
570 "(" (nth todo-category-number todo-categories) ": " 559 "(" (nth todo-category-number todo-categories) ": "
571 comment ")\n"))) 560 comment ")\n")))
572 (goto-char (todo-item-start)) 561 (goto-char (todo-item-start))
573 (let ((temp-point (point))) 562 (let ((temp-point (point)))
574 (if (looking-at (regexp-quote todo-prefix)) 563 (if (looking-at (regexp-quote todo-prefix))
575 (replace-match (time-stamp-string)) ; Standard prefix -> timestamp 564 (replace-match (time-stamp-string)) ; Standard prefix -> timestamp
576 ;; Else prefix non-standard item start with timestamp 565 ;; Else prefix non-standard item start with timestamp
577 (insert (time-stamp-string))) 566 (insert (time-stamp-string)))
578 (append-to-file temp-point (todo-item-end) todo-file-done) 567 (append-to-file temp-point (todo-item-end) todo-file-done)
579 (delete-region temp-point (1+ (todo-item-end)))) 568 (delete-region temp-point (1+ (todo-item-end))))
580 (todo-backward-item) 569 (todo-backward-item)
581 (message "")) 570 (message ""))
582 (error "No TODO list entry to file away"))) 571 (error "No TODO list entry to file away")))
583 572
584;; --------------------------------------------------------------------------- 573;; ---------------------------------------------------------------------------
@@ -593,15 +582,15 @@ For details see the variable `time-stamp-format'.")
593 ;; Suitable for putting in the minibuffer when asking the user 582 ;; Suitable for putting in the minibuffer when asking the user
594 (let ((item (todo-item-string))) 583 (let ((item (todo-item-string)))
595 (if (> (length item) 60) 584 (if (> (length item) 60)
596 (setq item (concat (substring item 0 56) "..."))) 585 (setq item (concat (substring item 0 56) "...")))
597 item)) 586 item))
598 587
599(defun todo-item-start () "Return point at start of current TODO list item." 588(defun todo-item-start () "Return point at start of current TODO list item."
600 (save-excursion 589 (save-excursion
601 (beginning-of-line) 590 (beginning-of-line)
602 (if (not (looking-at (regexp-quote todo-prefix))) 591 (if (not (looking-at (regexp-quote todo-prefix)))
603 (search-backward-regexp 592 (search-backward-regexp
604 (concat "^" (regexp-quote todo-prefix)) nil t)) 593 (concat "^" (regexp-quote todo-prefix)) nil t))
605 (point))) 594 (point)))
606 595
607(defun todo-item-end () "Return point at end of current TODO list item." 596(defun todo-item-end () "Return point at end of current TODO list item."
@@ -627,21 +616,21 @@ For details see the variable `time-stamp-format'.")
627(defun todo-category-alist () 616(defun todo-category-alist ()
628 "Generate an alist fro use in `completing-read' from `todo-categories'" 617 "Generate an alist fro use in `completing-read' from `todo-categories'"
629 (mapcar (lambda (cat) (cons cat nil)) 618 (mapcar (lambda (cat) (cons cat nil))
630 todo-categories)) 619 todo-categories))
631 620
632;; utility functions: These are available in XEmacs, but not in Emacs 19.34 621;; utility functions: These are available in XEmacs, but not in Emacs 19.34
633 622
634(if (not (fboundp 'point-at-bol)) 623(if (not (fboundp 'point-at-bol))
635 (defun point-at-bol () "Return value of point at beginning of line." 624 (defun point-at-bol () "Return value of point at beginning of line."
636 (save-excursion 625 (save-excursion
637 (beginning-of-line) 626 (beginning-of-line)
638 (point)))) 627 (point))))
639 628
640(if (not (fboundp 'point-at-eol)) 629(if (not (fboundp 'point-at-eol))
641 (defun point-at-eol () "Return value of point at end of line." 630 (defun point-at-eol () "Return value of point at end of line."
642 (save-excursion 631 (save-excursion
643 (end-of-line) 632 (end-of-line)
644 (point)))) 633 (point))))
645 634
646;; splits at a white space, returns a list 635;; splits at a white space, returns a list
647(if (not (fboundp 'split-string)) 636(if (not (fboundp 'split-string))
@@ -652,42 +641,42 @@ The substrings between the splitting points are made into a list
652which is returned. 641which is returned.
653If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." 642If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
654 (let ((rexp (or separators "[ \f\t\n\r\v]+")) 643 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
655 (start 0) 644 (start 0)
656 (list nil)) 645 (list nil))
657 (while (string-match rexp string start) 646 (while (string-match rexp string start)
658 (or (eq (match-beginning 0) 0) 647 (or (eq (match-beginning 0) 0)
659 (setq list 648 (setq list
660 (cons (substring string start (match-beginning 0)) 649 (cons (substring string start (match-beginning 0))
661 list))) 650 list)))
662 (setq start (match-end 0))) 651 (setq start (match-end 0)))
663 (or (eq start (length string)) 652 (or (eq start (length string))
664 (setq list 653 (setq list
665 (cons (substring string start) 654 (cons (substring string start)
666 list))) 655 list)))
667 (nreverse list)))) 656 (nreverse list))))
668 657
669;; --------------------------------------------------------------------------- 658;; ---------------------------------------------------------------------------
670 659
671(easy-menu-define todo-menu todo-mode-map "Todo Menu" 660(easy-menu-define todo-menu todo-mode-map "Todo Menu"
672 '("Todo" 661 '("Todo"
673 ["Next category" todo-forward-category t] 662 ["Next category" todo-forward-category t]
674 ["Previous category" todo-backward-category t] 663 ["Previous category" todo-backward-category t]
675 "---" 664 "---"
676 ["Edit item" todo-edit-item t] 665 ["Edit item" todo-edit-item t]
677 ["File item" todo-file-item t] 666 ["File item" todo-file-item t]
678 ["Insert new item" todo-insert-item t] 667 ["Insert new item" todo-insert-item t]
679 ["Kill item" todo-delete-item t] 668 ["Kill item" todo-delete-item t]
680 "---" 669 "---"
681 ["Lower item priority" todo-lower-item t] 670 ["Lower item priority" todo-lower-item t]
682 ["Raise item priority" todo-raise-item t] 671 ["Raise item priority" todo-raise-item t]
683 "---" 672 "---"
684 ["Next item" todo-forward-item t] 673 ["Next item" todo-forward-item t]
685 ["Previous item" todo-backward-item t] 674 ["Previous item" todo-backward-item t]
686 "---" 675 "---"
687 ["Save" todo-save t] 676 ["Save" todo-save t]
688 "---" 677 "---"
689 ["Quit" todo-quit t] 678 ["Quit" todo-quit t]
690 )) 679 ))
691 680
692(defun todo-mode () "Major mode for editing TODO lists.\n\n\\{todo-mode-map}" 681(defun todo-mode () "Major mode for editing TODO lists.\n\n\\{todo-mode-map}"
693 (interactive) 682 (interactive)
@@ -711,13 +700,13 @@ If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
711 (todo-initial-setup)) 700 (todo-initial-setup))
712 (if (null todo-categories) 701 (if (null todo-categories)
713 (if (null todo-cats) 702 (if (null todo-cats)
714 (error "Error in %s: No categories in list `todo-categories'" 703 (error "Error in %s: No categories in list `todo-categories'"
715 todo-file-do) 704 todo-file-do)
716 (goto-char (point-min)) 705 (goto-char (point-min))
717 (and (search-forward "todo-cats:" nil t) 706 (and (search-forward "todo-cats:" nil t)
718 (replace-match "todo-categories:")) 707 (replace-match "todo-categories:"))
719 (make-local-variable todo-categories) 708 (make-local-variable todo-categories)
720 (setq todo-categories todo-cats))) 709 (setq todo-categories todo-cats)))
721 (beginning-of-line) 710 (beginning-of-line)
722 (todo-category-select)) 711 (todo-category-select))
723 712