Patch from Paul Stodghill <stodghil@CS.Cornell.EDU>:
[bpt/emacs.git] / lisp / calendar / todo-mode.el
CommitLineData
01b864bc 1;; todo-mode.el -- Major mode for editing TODO list files
3cb152f9 2
7c896f63 3;; Copyright (C) 1997 Free Software Foundation, Inc.
3cb152f9 4
7c896f63
OS
5;; Author: Oliver.Seidel@cl.cam.ac.uk (was valid on Aug 2, 1997)
6;; Created: 2 Aug 1997
49b2ae0e 7;; Version: $Id: todo-mode.el,v 1.26 1997/10/28 21:14:51 os10000 Exp os10000 $
7c896f63 8;; Keywords: Categorised TODO list editor, todo-mode
3cb152f9 9
7c896f63 10;; This file is part of GNU Emacs.
595b2334 11
7c896f63 12;; GNU Emacs is free software; you can redistribute it and/or modify
595b2334
OS
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
7c896f63
OS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
595b2334
OS
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
7c896f63 21
595b2334
OS
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;; ---------------------------------------------------------------------------
28
7c896f63
OS
29;;; Commentary:
30
85b3b166
OS
31;; Mode Description
32;;
33;; TODO is a major mode for EMACS which offers functionality to
34;; treat most lines in one buffer as a list of items one has to
35;; do. There are facilities to add new items, which are
36;; categorised, to edit or even delete items from the buffer.
37;; The buffer contents are currently compatible with the diary,
38;; so that the list of todo-items will show up in the FANCY diary
39;; mode.
40;;
41;; Notice: Besides the major mode, this file also exports the
42;; function `todo-show' which will change to the one specific
43;; TODO file that has been specified in the todo-file-do
44;; variable. If this file does not conform to the TODO mode
45;; conventions, the todo-show function will add the appropriate
46;; header and footer. I don't anticipate this to cause much
47;; grief, but be warned, in case you attempt to read a plain text
48;; file.
49;;
01b864bc 50;; Preface, Quickstart Installation
595b2334 51;;
e4541b67 52;; To get this to work, make emacs execute the line
3d8105fb 53;;
e4541b67 54;; (autoload 'todo-mode "todo-mode"
4cbc9d5a
OS
55;; "Major mode for editing TODO lists." t)
56;; (autoload 'todo-show "todo-mode"
57;; "Show TODO items." t)
58;; (autoload 'todo-insert-item "todo-mode"
59;; "Add TODO item." t)
7c896f63 60;;
e4541b67
OS
61;; You may now enter new items by typing "M-x todo-insert-item",
62;; or enter your TODO list file by typing "M-x todo-show".
63;;
64;; The TODO list file has a special format and some auxiliary
65;; information, which will be added by the todo-show function if
66;; it attempts to visit an un-initialised file. Hence it is
67;; recommended to use the todo-show function for the first time,
68;; in order to initialise the file, but it is not necessary
69;; afterwards.
70;;
71;; As these commands are quite long to type, I would recommend
72;; the addition of two bindings to your to your global keymap. I
73;; personally have the following in my initialisation file:
74;;
75;; (global-set-key "\C-ct" 'todo-show) ;; switch to TODO buffer
01b864bc 76;; (global-set-key "\C-ci" 'todo-insert-item) ;; insert new item
7c896f63 77;;
e4541b67
OS
78;; Note, however, that this recommendation has prompted some
79;; criticism, since the keys C-c LETTER are reserved for user
80;; functions. I believe my recommendation is acceptable, since
81;; the Emacs Lisp Manual *Tips* section also details that the
82;; mode itself should not bind any functions to those keys. The
83;; express aim of the above two bindings is to work outside the
84;; mode, which doesn't need the show function and offers a
85;; different binding for the insert function. They serve as
86;; shortcuts and are not even needed (since the TODO mode will be
87;; entered by visiting the TODO file, and later by switching to
88;; its buffer).
89;;
90;; Version
7c896f63 91;;
e4541b67 92;; Which version of todo-mode.el does this documentation refer to?
579e1c67 93;;
49b2ae0e 94;; $Id: todo-mode.el,v 1.26 1997/10/28 21:14:51 os10000 Exp os10000 $
01b864bc 95;;
e4541b67
OS
96;; Pre-Requisites
97;;
98;; This package will require the following packages to be
99;; available on the load-path:
100;;
101;; time-stamp
01b864bc
OS
102;; easymenu
103;;
e4541b67 104;; Operation
01b864bc
OS
105;;
106;; You will have the following facilities available:
107;;
108;; M-x todo-show will enter the todo list screen, here type
109;;
110;; + to go to next category
111;; - to go to previous category
e4541b67
OS
112;; d to file the current entry, including a
113;; comment and timestamp
01b864bc
OS
114;; e to edit the current entry
115;; f to file the current entry, including a
116;; comment and timestamp
117;; i to insert a new entry
e4541b67 118;; j jump to category
01b864bc
OS
119;; k to kill the current entry
120;; l to lower the current entry's priority
121;; n for the next entry
122;; p for the previous entry
e4541b67 123;; P print
01b864bc
OS
124;; q to save the list and exit the buffer
125;; r to raise the current entry's priority
126;; s to save the list
f1757bdd 127;; S to save the list of top priorities
85b3b166 128;; t show top priority items for each category
01b864bc 129;;
e4541b67
OS
130;; When you add a new entry, you are asked for the text and then
131;; for the category. I for example have categories for things
132;; that I want to do in the office (like mail my mum), that I
133;; want to do in town (like buy cornflakes) and things I want to
134;; do at home (move my suitcases). The categories can be
135;; selected with the cursor keys and if you type in the name of a
136;; category which didn't exist before, an empty category of the
137;; desired name will be added and filled with the new entry.
01b864bc
OS
138;;
139;; Configuration
140;;
141;; Variable todo-prefix
142;;
143;; I would like to recommend that you use the prefix "*/*" (by
e4541b67
OS
144;; leaving the variable 'todo-prefix' untouched) so that the
145;; diary displays each entry every day.
01b864bc 146;;
e4541b67
OS
147;; To understand what I mean, please read the documentation that
148;; goes with the calendar since that will tell you how you can
149;; set up the fancy diary display and use the #include command to
150;; include your todo list file as part of your diary.
01b864bc 151;;
e4541b67
OS
152;; If you have the diary package set up to usually display more
153;; than one day's entries at once, consider using
01b864bc
OS
154;;
155;; "&%%(equal (calendar-current-date) date)"
156;;
e4541b67
OS
157;; as the value of `todo-prefix'. Please note that this may slow
158;; down the processing of your diary file some.
01b864bc
OS
159;;
160;; Variable todo-file-do
161;;
e4541b67
OS
162;; This variable is fairly self-explanatory. You have to store
163;; your TODO list somewhere. This variable tells the package
164;; where to go and find this file.
01b864bc
OS
165;;
166;; Variable todo-file-done
167;;
e4541b67
OS
168;; Even when you're done, you may wish to retain the entries.
169;; Given that they're timestamped and you are offered to add a
170;; comment, this can make a useful diary of past events. It will
171;; even blend in with the EMACS diary package. So anyway, this
172;; variable holds the name of the file for the filed todo-items.
01b864bc 173;;
f1757bdd
OS
174;; Variable todo-file-top
175;;
176;; File storing the top priorities of your TODO list when
177;; todo-save-top-priorities is non-nil. Nice to include in your
178;; diary instead of the complete TODO list.
179;;
01b864bc
OS
180;; Variable todo-mode-hook
181;;
e4541b67
OS
182;; Just like other modes, too, this mode offers to call your
183;; functions before it goes about its business. This variable
184;; will be inspected for any functions you may wish to have
185;; called once the other TODO mode preparations have been
186;; completed.
187;;
188;; Variable todo-insert-threshold
189;;
190;; Another nifty feature is the insertion accuracy. If you have
191;; 8 items in your TODO list, then you may get asked 4 questions
192;; by the binary insertion algorithm. However, you may not
193;; really have a need for such accurate priorities amongst your
194;; TODO items. If you now think about the binary insertion
195;; halfing the size of the window each time, then the threshhold
196;; is the window size at which it will stop. If you set the
197;; threshhold to zero, the upper and lower bound will coincide at
198;; the end of the loop and you will insert your item just before
85b3b166 199;; that point. If you set the threshhold to, e.g. 8, it will stop
e4541b67
OS
200;; as soon as the window size drops below that amount and will
201;; insert the item in the approximate centre of that window. I
202;; got the idea for this feature after reading a very helpful
203;; e-mail reply from Trey Jackson <trey@cs.berkeley.edu> who
204;; corrected some of my awful coding and pointed me towards some
205;; good reading. Thanks Trey!
01b864bc
OS
206;;
207;; Things to do
208;;
e4541b67
OS
209;; These originally were my ideas, but now also include all the
210;; suggestions that I included before forgetting them:
211;;
e4541b67
OS
212;; o Fancy fonts for todo/top-priority buffer
213;; o Remove todo-prefix option in todo-top-priorities
214;; o Rename category
215;; o Move entry from one category to another one
216;; o Entries which both have the generic */* prefix and a
217;; "deadline" entry which are understood by diary, indicating
218;; an event (unless marked by &)
219;; o The optional COUNT variable of todo-forward-item should be
220;; applied to the other functions performing similar tasks
221;; o Modularization could be done for repeaded elements of
222;; the code, like the completing-read lines of code.
223;; o license / version function
01b864bc
OS
224;; o export to diary file
225;; o todo-report-bug
226;; o GNATS support
e4541b67
OS
227;; o elide multiline (as in bbdb, or, to a lesser degree, in
228;; outline mode)
229;; o rewrite complete package to store data as lisp objects
230;; and have display modes for display, for diary export,
231;; etc. (Richard Stallman pointed out this is a bad idea)
232;; o so base todo-mode.el on generic-mode.el instead
01b864bc 233;;
e4541b67 234;; History and Gossip
01b864bc 235;;
e4541b67
OS
236;; Many thanks to all the ones who have contributed to the
237;; evolution of this package! I hope I have listed all of you
238;; somewhere in the documentation or at least in the RCS history!
01b864bc 239;;
e4541b67
OS
240;; Enjoy this package and express your gratitude by sending nice
241;; things to my parents' address!
01b864bc
OS
242;;
243;; Oliver Seidel
e4541b67 244;; (Lessingstr. 8, 65760 Eschborn, Federal Republic of Germany)
579e1c67
OS
245;;
246
247;; ---------------------------------------------------------------------------
248
7c896f63
OS
249;;; Change Log:
250
251;; $Log: todo-mode.el,v $
49b2ae0e
OS
252;; Revision 1.26 1997/10/28 21:14:51 os10000
253;; Improvements sent in by Dave Love <d.love@dl.ac.uk>:
254;; todo-mode.el: Doc fixes. Customization.
255;; (todo-add-item-non-interactively): New arg -- don't dynamically bind ARG.
256;; (todo-insert-item): Use it.
257;;
85b3b166
OS
258;; Revision 1.25 1997/10/28 20:03:27 os10000
259;; Harald Backer <harald.backer@fou.telenor.no> sent the following:
260;; Added `todo-save-top-priorities' and option to automatically save top
261;; priorities file when saving todo-file. Changed some default values.
262;; Bug fixes.
263;;
f1757bdd
OS
264;; Revision 1.24 1997/10/28 19:41:53 os10000
265;; Added fix from Frank Ridderbusch <ridderbusch.pad@sni.de>,
266;; an apostrophe was missing.
267;;
e05e3850
OS
268;; Revision 1.23 1997/10/24 17:30:54 os10000
269;; Added three suggestions from Carsten
270;; Dominik <dominik@strw.LeidenUniv.nl>:
271;;
272;; - recommend autoloading instead of require
273;; - inserting from different buffer didn't work
274;; (now fixed -- I pray)
275;; - provided public entry point to insert items
276;; from normal lisp code
277;;
4cbc9d5a
OS
278;; Revision 1.22 1997/10/24 16:53:20 os10000
279;; Paul Stodghill <stodghil@CS.Cornell.EDU> writes:
280;;
281;; When invoked with a prefix, todo-insert-item
282;; should not prompt for a category. (He adds:
283;; At least that's what I think.)
284;;
2e590030
OS
285;; Revision 1.21 1997/10/24 16:51:02 os10000
286;; Rafael Laboissiere <rafael@icp.inpg.fr> writes:
287;;
288;; I was just annoyed with the fact that there is no way
289;; to dynamically control the insertion accuracy. I mean:
290;; the variable `todo-insert-threshold' does the job, but
291;; it is not very handy if one wants to mix the two
292;; behaviors (bisection and "insert right here under the
293;; cursor").
294;;
295;; Therefore I did a quick hack in the function
296;; `todo-insert-item'. Now by giving a prefix argument to
297;; the insert command (i.e. by typing "C-u i"), entries
298;; are inserted exactly at the line where the cursor is.
299;; It would be better to give the value of
300;; `todo-insert-threshold' as a numeric argument of
301;; `todo-insert-item' (like "M-8 i"), but it's too late
302;; now for continuing to hack.
303;;
0aa18b36
OS
304;; Revision 1.20 1997/10/17 15:41:57 os10000
305;; Thanks to Harald Backer <harald.backer@fou.telenor.no>, we now have
306;; the following facilities available:
307;;
308;; Added todo-print, todo-top-priorities and todo-jump with matching
309;; variables; Parameterized todo-header, todo-category-beg,
310;; todo-category-end and todo-category-sep; Added autoload comments;
311;; todo-category-select: Modified regexp to make category names unique;
312;; todo-forward-item: Added optional COUNT vaiable; todo-insert-item:
313;; Rewrote completing read entry.
314;;
315;; Also, check out the extended list of things left to be done to this
316;; package at the end of the documentation!
317;;
e4541b67
OS
318;; Revision 1.19 1997/10/16 21:21:16 os10000
319;; Jari Aalto <jari.aalto@poboxes.com> writes:
320;;
321;; I just downloaded your package and after reading the docs I
322;; decided to do some reformatting. Hope you don't mind. Now
323;; they are in such a format that the html page can be
324;; automatically generated from the source file. As an example, I
325;; generated the attached page using the following command:
326;; ripdoc.pls < todo-mode.el | t2html.pls -a "Oliver.Seidel" -e \
0aa18b36 327;; Oliver.Seidel@cl.cam.ac.uk -simple -base
e4541b67
OS
328;;
329;; And of course I appreciate it. Jari's stuff can be found at:
330;; ftp://cs.uta.fi/pub/ssjaaa/, while I'm making the rev 1.18 page
331;; available at http://www.cl.cam.ac.uk/users/os10000/doc/todo-mode.html
332;; (That link will be valid until 10/1998 or slightly longer.)
333;;
01b864bc
OS
334;; Revision 1.18 1997/10/15 17:18:11 os10000
335;; Everything seems to work in Harald Melands Emacs 20.02 and
336;; my Emacs 19.34. Beware of the spelling in some of the
337;; variable names. I looked up "threshold" in a dictionary
338;; and here in Britain this appears to be the way to spell it.
339;;
ab618c6e
OS
340;; Revision 1.17 1997/10/15 14:30:41 os10000
341;; Attempted to reconcile Harald's changes with mine since 1.15.
342;;
b7e04170
OS
343;; Revision 1.16 1997/10/15 14:00:12 os10000
344;; Fixed 'file-item' and added 20.02 split-string function.
345;;
91e9443e
OS
346;; Revision 1.15 1997/10/14 22:22:35 os10000
347;; Added string-split (which I stole from ediff-util), changed
348;; pop-to-buffer to switch-to-buffer and added message on how
349;; to exit the multi-line-edit mode.
350;;
2186b974
OS
351;; Revision 1.14 1997/10/09 09:24:50 os10000
352;; Harald Meland <harald.meland@usit.uio.no> asked for
353;; the latest version, got 1.13, and returned this.
354;; He writes:
355;;
356;; Thanks a lot for the new version of todo-mode.el. As you will see I
357;; have messed it up a bit, hopefully for the better -- I don't like
358;; short, cryptic names for variables and functions, so I renamed most of
359;; them, and `defalias'ed the old function names. I hope you don't mind
360;; too much, I just kinda couldn't stop myself.
361;;
362;; Additionally, I included some support for multiline entries, cleaned
363;; up (IMHO :) a lot of the code, included completion-support for which
364;; category to install a new entry in, and possibly some other changes I
365;; can't remember :)
366;;
367;; It's getting rather late, and I have just done some preliminary
368;; testing on whether all of this really works, but so far it looks
369;; good.
370;;
7f6241ea
OS
371;; Revision 1.13 1997/08/19 14:00:36 seidel
372;; - changed name to todo-mode
373;; - fixed menu descriptions
374;; - fixed "pressing abort while filing"
375;; - attempted Emacs Lisp Manual *Tips* section compliance
376;;
7c896f63
OS
377;; Revision 1.12 1997/08/06 10:56:15 os10000
378;; Fixed header, typos, layout, documentation.
579e1c67 379;;
cf1ebf43
OS
380;; Revision 1.11 1997/08/06 09:14:25 os10000
381;; Applied patch from Istvan Marko <istvan@cmdmail.amd.com>
382;; to make menus work anywhere.
383;;
49c48a1b
OS
384;; Revision 1.10 1997/08/06 08:56:03 os10000
385;; Acted upon suggestion from Shane Holder <holder@rsn.hp.com>:
386;; Cancelling the editing of an entry will not delete it any more.
387;;
03944ca7
OS
388;; Revision 1.9 1997/08/06 08:12:03 os10000
389;; Improved documentation. Broke some lines to comply with
390;; Richard Stallman's email to please keep in sync with the
391;; rest of the Emacs distribution files.
392;;
579e1c67 393;; Revision 1.8 1997/08/05 22:39:04 os10000
7c896f63 394;; Made todo-mode.el available under GPL.
579e1c67
OS
395;;
396;; Revision 1.7 1997/08/05 22:34:14 os10000
397;; Fixed insertion routine with help from Trey Jackson
7f6241ea 398;; <trey@cs.berkeley.edu>; added todo-inst-tresh;
579e1c67
OS
399;; fixed keyboard layout to remove unwanted keys.
400;;
401;; Revision 1.6 1997/08/05 16:47:01 os10000
402;; Incorporated menus for XEmacs from Allan.Cochrane@soton.sc.philips.com,
403;; fixed TYPO, fixed todo-file-cmd, cleaned up rcs history.
404;;
405;; Revision 1.5 1997/08/05 14:43:39 os10000
406;; Added improvements from Ron Gut <rgut@aware.com>.
407;; Added category management.
408;;
409;; Revision 1.4 1997/08/04 16:18:45 os10000
410;; Added Raise/Lower item.
411;;
412;; Revision 1.3 1997/08/03 12:47:26 os10000
413;; Cleaned up variables, prefix and cursor position.
414;;
415;; Revision 1.2 1997/08/03 12:15:28 os10000
416;; It appears to work.
417;;
418;; Revision 1.1 1997/08/03 12:15:13 os10000
419;; Initial revision
420;;
7e6ed9b9
OS
421
422;; ---------------------------------------------------------------------------
423
7c896f63
OS
424;;; Code:
425
85b3b166
OS
426(eval-and-compile ; Removable for installation in
427 ; Emacs 20.
428 (condition-case ()
429 (require 'custom)
430 (error nil))
431 (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
432 nil ;; We've got what we needed
433 ;; We have the old custom-library, hack around it!
434 (defmacro defgroup (&rest args)
435 nil)
436 (defmacro defcustom (var value doc &rest args)
437 (` (defvar (, var) (, value) (, doc))))))
438
3cb152f9
OS
439;; User-configurable variables:
440
85b3b166
OS
441(defgroup todo nil
442 "Maintain a list of todo items."
443 :group 'calendar)
444
445(defcustom todo-prefix "*/*"
446 "*TODO mode prefix for entries.
447
448This is useful in conjunction with `calendar' and `diary' if you use
449
450#include \"~/.todo-do\"
451
452in your diary file to include your todo list file as part of your
453diary. With the default value \"*/*\" the diary displays each entry
454every day and it may also be marked on every day of the calendar.
455Using \"&%%(equal (calendar-current-date) date)\" instead will only
456show and mark todo entreis for today, but may slow down processing of
457the diary file somewhat."
458 :type 'string
459 :group 'todo)
460(defcustom todo-file-do "~/.todo-do"
461 "*TODO mode list file."
462 :type 'file
463 :group 'todo)
464(defcustom todo-file-done "~/.todo-done"
465 "*TODO mode archive file."
466 :type 'file
467 :group 'todo)
468(defcustom todo-mode-hook nil
469 "*TODO mode hooks."
470 :type 'hook
471 :group 'todo)
472(defcustom todo-edit-mode-hook nil
473 "*TODO Edit mode hooks."
474 :type 'hook
475 :group 'todo)
476(defcustom todo-insert-threshold 0
477 "*TODO mode insertion accuracy.
478
479If you have 8 items in your TODO list, then you may get asked 4
480questions by the binary insertion algorithm. However, you may not
481really have a need for such accurate priorities amongst your TODO
482items. If you now think about the binary insertion halfing the size
483of the window each time, then the threshhold is the window size at
484which it will stop. If you set the threshhold to zero, the upper and
485lower bound will coincide at the end of the loop and you will insert
486your item just before that point. If you set the threshhold to,
487e.g. 8, it will stop as soon as the window size drops below that
488amount and will insert the item in the approximate centre of that
489window."
490 :type 'integer
491 :group 'todo)
01b864bc 492(defvar todo-edit-buffer " *TODO Edit*" "TODO Edit buffer name.")
85b3b166 493(defcustom todo-file-top "~/.todo-top"
f1757bdd 494 "*TODO mode top priorities file.
85b3b166 495
f1757bdd 496Not in TODO format, but diary compatible.
85b3b166
OS
497Automatically generated when `todo-save-top-priorities' is non-nil."
498 :type 'string
499 :group 'todo)
500
501(defcustom todo-print-function 'ps-print-buffer-with-faces
502 "*Function to print the current buffer."
503 :type 'symbol
504 :group 'todo)
505(defcustom todo-show-priorities 1
506 "*Default number of priorities to show by \\[todo-top-priorities].
5070 means show all entries."
508 :type 'integer
509 :group 'todo)
510(defcustom todo-print-priorities 0
511 "*Default number of priorities to print by \\[todo-print].
5120 means print all entries."
513 :type 'integer
514 :group 'todo)
515(defcustom todo-remove-separator t
516 "*Non-nil to remove category separators in\
517\\[todo-top-priorities] and \\[todo-print]."
518 :type 'boolean
519 :group 'todo)
520(defcustom todo-save-top-priorities-too t
f1757bdd 521 "*Non-nil makes todo-save automatically save top-priorities in
85b3b166
OS
522`todo-file-top'."
523 :type 'boolean
524 :group 'todo)
e4541b67 525
7c896f63
OS
526;; Thanks for the ISO time stamp format go to Karl Eichwalder <ke@suse.de>
527;; My format string for the appt.el package is "%3b %2d, %y, %02I:%02M%p".
528;;
85b3b166 529(defcustom todo-time-string-format
ab618c6e 530 "%:y-%02m-%02d %02H:%02M"
85b3b166
OS
531 "*TODO mode time string format for done entries.
532For details see the variable `time-stamp-format'."
533 :type 'string
534 :group 'todo)
535
536(defcustom todo-entry-prefix-function 'todo-entry-timestamp-initials
537 "*Function producing text to insert at start of todo entry."
538 :type 'symbol
539 :group 'todo)
540(defcustom todo-initials (or (getenv "INITIALS") (user-login-name))
541 "*Initials of todo item author."
542 :type 'string
543 :group 'todo)
e4541b67
OS
544
545(defun todo-entry-timestamp-initials ()
f1757bdd 546 "Prepend timestamp and your initials to the head of a TODO entry."
e4541b67
OS
547 (let ((time-stamp-format todo-time-string-format))
548 (concat (time-stamp-string) " " todo-initials ": ")))
549
3cb152f9
OS
550;; ---------------------------------------------------------------------------
551
49c48a1b
OS
552;; Get some outside help ...
553
3cb152f9 554(require 'time-stamp)
49c48a1b
OS
555(require 'easymenu)
556
557;; ---------------------------------------------------------------------------
3cb152f9 558
cf1ebf43
OS
559;; Set up some helpful context ...
560
01b864bc 561(defvar todo-categories nil "TODO categories.")
85b3b166
OS
562(defvar todo-cats nil
563 "Old variable for holding the TODO categories.
564Use `todo-categories' instead.")
01b864bc
OS
565(defvar todo-previous-line 0 "Previous line that I asked about.")
566(defvar todo-previous-answer 0 "Previous answer that I got.")
567(defvar todo-mode-map nil "TODO mode keymap.")
568(defvar todo-category-number 0 "TODO category number.")
cf1ebf43 569
f1757bdd 570(defvar todo-tmp-buffer-name "*Tmp*")
e4541b67
OS
571
572(defvar todo-category-sep (make-string 75 ?-)
573 "Category separator.")
574(defvar todo-category-beg " --- "
575 "Category start separator to be prepended onto category name.")
576(defvar todo-category-end "--- End"
577 "Separator after a category.")
578(defvar todo-header "-*- mode: todo; "
579 "Header of todo files.")
580
581
582
cf1ebf43
OS
583;; ---------------------------------------------------------------------------
584
3d8105fb
OS
585(if todo-mode-map
586 nil
587 (let ((map (make-keymap)))
588 (suppress-keymap map t)
7f6241ea
OS
589 (define-key map "+" 'todo-forward-category)
590 (define-key map "-" 'todo-backward-category)
591 (define-key map "e" 'todo-edit-item)
592 (define-key map "E" 'todo-edit-multiline)
e4541b67 593 (define-key map "d" 'todo-file-item) ;done/delete
7f6241ea
OS
594 (define-key map "f" 'todo-file-item)
595 (define-key map "i" 'todo-insert-item)
e4541b67 596 (define-key map "j" 'todo-jump-to-category)
7f6241ea
OS
597 (define-key map "k" 'todo-delete-item)
598 (define-key map "l" 'todo-lower-item)
599 (define-key map "n" 'todo-forward-item)
600 (define-key map "p" 'todo-backward-item)
e4541b67 601 (define-key map "P" 'todo-print)
7f6241ea
OS
602 (define-key map "q" 'todo-quit)
603 (define-key map "r" 'todo-raise-item)
604 (define-key map "s" 'todo-save)
f1757bdd 605 (define-key map "S" 'todo-save-top-priorities)
e4541b67 606 (define-key map "t" 'todo-top-priorities)
3d8105fb 607 (setq todo-mode-map map)))
3cb152f9 608
7f6241ea
OS
609(defun todo-category-select ()
610 "Make TODO mode display the current category correctly."
611 (let ((name (nth todo-category-number todo-categories)))
579e1c67 612 (setq mode-line-buffer-identification
01b864bc 613 (concat "Category: " name))
da2ee685
OS
614 (widen)
615 (goto-char (point-min))
7f6241ea 616 (search-forward-regexp
e4541b67
OS
617 (concat "^"
618 (regexp-quote (concat todo-prefix todo-category-beg name))
619 "$"))
7f6241ea 620 (let ((begin (1+ (point-at-eol))))
e4541b67 621 (search-forward-regexp (concat "^" todo-category-end))
7f6241ea
OS
622 (narrow-to-region begin (point-at-bol))
623 (goto-char (point-min)))))
624(defalias 'todo-cat-slct 'todo-category-select)
625
626(defun todo-forward-category () "Go forward to TODO list of next category."
da2ee685 627 (interactive)
7f6241ea 628 (setq todo-category-number
01b864bc 629 (mod (1+ todo-category-number) (length todo-categories)))
7f6241ea
OS
630 (todo-category-select))
631(defalias 'todo-cmd-forw 'todo-forward-category)
da2ee685 632
7f6241ea 633(defun todo-backward-category () "Go back to TODO list of previous category."
da2ee685 634 (interactive)
7f6241ea 635 (setq todo-category-number
01b864bc 636 (mod (1- todo-category-number) (length todo-categories)))
7f6241ea
OS
637 (todo-category-select))
638(defalias 'todo-cmd-back 'todo-backward-category)
da2ee685 639
7f6241ea 640(defun todo-backward-item () "Select previous entry of TODO list."
3cb152f9 641 (interactive)
7f6241ea 642 (search-backward-regexp (concat "^" (regexp-quote todo-prefix)) nil t)
cf1ebf43 643 (message ""))
7f6241ea 644(defalias 'todo-cmd-prev 'todo-backward-item)
3cb152f9 645
e4541b67 646(defun todo-forward-item (&optional count)
85b3b166 647 "Select COUNT-th next entry of TODO list."
e4541b67
OS
648 (interactive "P")
649 (if (listp count) (setq count (car count)))
7f6241ea 650 (end-of-line)
e4541b67
OS
651 (search-forward-regexp (concat "^" (regexp-quote todo-prefix))
652 nil 'goto-end count)
7f6241ea 653 (beginning-of-line)
cf1ebf43 654 (message ""))
7f6241ea 655(defalias 'todo-cmd-next 'todo-forward-item)
3cb152f9 656
7f6241ea 657(defun todo-save () "Save the TODO list."
da2ee685 658 (interactive)
f1757bdd
OS
659 (save-buffer)
660 (if todo-save-top-priorities-too (todo-save-top-priorities))
661 )
7f6241ea 662(defalias 'todo-cmd-save 'todo-save)
da2ee685 663
7f6241ea 664(defun todo-quit () "Done with TODO list for now."
3cb152f9 665 (interactive)
da2ee685 666 (widen)
f1757bdd 667 (todo-save)
7e6ed9b9 668 (message "")
cf1ebf43 669 (bury-buffer))
7f6241ea 670(defalias 'todo-cmd-done 'todo-quit)
3cb152f9 671
7f6241ea 672(defun todo-edit-item () "Edit current TODO list entry."
3cb152f9 673 (interactive)
7f6241ea
OS
674 (let ((item (todo-item-string)))
675 (if (todo-string-multiline-p item)
01b864bc 676 (todo-edit-multiline)
7f6241ea 677 (let ((new (read-from-minibuffer "Edit: " item)))
01b864bc
OS
678 (todo-remove-item)
679 (insert new "\n")
680 (todo-backward-item)
681 (message "")))))
7f6241ea
OS
682(defalias 'todo-cmd-edit 'todo-edit-item)
683
684(defun todo-edit-multiline ()
685 "Set up a buffer for editing a multiline TODO list entry."
686 (interactive)
687 (let ((buffer-name (generate-new-buffer-name todo-edit-buffer)))
e4541b67
OS
688 (switch-to-buffer
689 (make-indirect-buffer
690 (file-name-nondirectory todo-file-do) buffer-name))
2186b974 691 (message "To exit, simply kill this buffer and return to list.")
7f6241ea
OS
692 (todo-edit-mode)
693 (narrow-to-region (todo-item-start) (todo-item-end))))
3cb152f9 694
e4541b67 695;;;### autoload
85b3b166
OS
696(defun todo-add-category (cat)
697 "Add new category CAT to the TODO list."
3cb152f9 698 (interactive)
3cb152f9 699 (save-window-excursion
7f6241ea 700 (setq todo-categories (cons cat todo-categories))
3cb152f9 701 (find-file todo-file-do)
da2ee685
OS
702 (widen)
703 (goto-char (point-min))
704 (let ((posn (search-forward "-*- mode: todo; " 17 t)))
705 (if (not (null posn)) (goto-char posn))
579e1c67 706 (if (equal posn nil)
01b864bc
OS
707 (progn
708 (insert "-*- mode: todo; \n")
709 (forward-char -1))
710 (kill-line)))
7f6241ea 711 (insert (format "todo-categories: %S; -*-" todo-categories))
da2ee685 712 (forward-char 1)
e4541b67
OS
713 (insert (format "%s%s%s\n%s\n%s %s\n"
714 todo-prefix todo-category-beg cat
715 todo-category-end
716 todo-prefix todo-category-sep)))
cf1ebf43 717 0)
da2ee685 718
e4541b67 719;;;### autoload
85b3b166
OS
720(defun todo-add-item-non-interactively (new-item category ARG)
721 "Insert NEW-ITEM in TODO list as a new entry in CATEGORY."
4cbc9d5a 722 (save-excursion
49b2ae0e
OS
723 (todo-show))
724 (save-excursion
e4541b67
OS
725 (if (string= "" category)
726 (setq category (nth todo-category-number todo-categories)))
7f6241ea
OS
727 (let ((cat-exists (member category todo-categories)))
728 (setq todo-category-number
01b864bc
OS
729 (if cat-exists
730 (- (length todo-categories) (length cat-exists))
731 (todo-add-category category))))
0aa18b36
OS
732 (if (not ARG)
733 (progn
734 (todo-show)
735 (setq todo-previous-line 0)
736 (let ((top 1)
737 (bottom (1+ (count-lines (point-min) (point-max)))))
738 (while (> (- bottom top) todo-insert-threshold)
739 (let* ((current (/ (+ top bottom) 2))
740 (answer (if (< current bottom)
741 (todo-more-important-p current) nil)))
742 (if answer
743 (setq bottom current)
744 (setq top (1+ current)))))
745 (setq top (/ (+ top bottom) 2))
746 ;; goto-line doesn't have the desired behavior in a narrowed buffer
747 (goto-char (point-min))
748 (forward-line (1- top))))
749 (beginning-of-line))
7f6241ea
OS
750 (insert new-item "\n")
751 (todo-backward-item)
f1757bdd 752 (todo-save)
3d8105fb 753 (message "")))
4cbc9d5a
OS
754
755;;;### autoload
756(defun todo-insert-item (ARG)
85b3b166
OS
757 "Insert new TODO list entry.
758With a prefix argument solicit the category, otherwise use the current
759category."
4cbc9d5a 760 (interactive "P")
49b2ae0e 761 (save-excursion
4cbc9d5a 762 (todo-show)
49b2ae0e 763 )
4cbc9d5a
OS
764 (let* ((new-item (concat todo-prefix " "
765 (read-from-minibuffer
766 "New TODO entry: "
85b3b166
OS
767 (if todo-entry-prefix-function
768 (funcall todo-entry-prefix-function)))))
4cbc9d5a
OS
769 (categories todo-categories)
770 (history (cons 'categories (1+ todo-category-number)))
771 (current-category (nth todo-category-number todo-categories))
772 (category
773 (if ARG
774 current-category
85b3b166
OS
775 (completing-read
776 (concat "Category ["
777 current-category "]: ")
778 (todo-category-alist) nil nil nil history))))
779 (todo-add-item-non-interactively new-item category ARG)))
4cbc9d5a 780
7f6241ea 781(defalias 'todo-cmd-inst 'todo-insert-item)
3d8105fb 782
01b864bc 783(defun todo-more-important-p (line)
7f6241ea
OS
784 "Ask whether entry is more important than the one at LINE."
785 (if (not (equal todo-previous-line line))
3d8105fb 786 (progn
7f6241ea 787 (setq todo-previous-line line)
3d8105fb 788 (goto-char (point-min))
7f6241ea 789 (forward-line (1- todo-previous-line))
01b864bc
OS
790 (let ((item (todo-item-string-start)))
791 (setq todo-previous-answer
792 (y-or-n-p (concat "More important than '" item "'? "))))))
7f6241ea
OS
793 todo-previous-answer)
794(defalias 'todo-ask-p 'todo-more-important-p)
795
796(defun todo-delete-item () "Delete current TODO list entry."
3cb152f9
OS
797 (interactive)
798 (if (> (count-lines (point-min) (point-max)) 0)
7f6241ea 799 (let* ((todo-entry (todo-item-string-start))
01b864bc
OS
800 (todo-answer (y-or-n-p (concat "Permanently remove '"
801 todo-entry "'? "))))
802 (if todo-answer
803 (progn
804 (todo-remove-item)
805 (todo-backward-item)))
806 (message ""))
7f6241ea
OS
807 (error "No TODO list entry to delete")))
808(defalias 'todo-cmd-kill 'todo-delete-item)
3cb152f9 809
7f6241ea 810(defun todo-raise-item () "Raise priority of current entry."
8cdc3b3d 811 (interactive)
7f6241ea
OS
812 (if (> (count-lines (point-min) (point)) 0)
813 (let ((item (todo-item-string)))
01b864bc
OS
814 (todo-remove-item)
815 (todo-backward-item)
816 (save-excursion
817 (insert item "\n"))
818 (message ""))
7f6241ea
OS
819 (error "No TODO list entry to raise")))
820(defalias 'todo-cmd-rais 'todo-raise-item)
8cdc3b3d 821
7f6241ea 822(defun todo-lower-item () "Lower priority of current entry."
8cdc3b3d 823 (interactive)
e4541b67
OS
824 (if (> (count-lines (point) (point-max)) 1)
825 ;; Assume there is a final newline
7f6241ea 826 (let ((item (todo-item-string)))
01b864bc
OS
827 (todo-remove-item)
828 (todo-forward-item)
829 (save-excursion
830 (insert item "\n"))
831 (message ""))
7f6241ea
OS
832 (error "No TODO list entry to lower")))
833(defalias 'todo-cmd-lowr 'todo-lower-item)
8cdc3b3d 834
7f6241ea 835(defun todo-file-item () "File the current TODO list entry away."
3cb152f9
OS
836 (interactive)
837 (if (> (count-lines (point-min) (point-max)) 0)
7f6241ea 838 (let ((comment (read-from-minibuffer "Comment: "))
01b864bc
OS
839 (time-stamp-format todo-time-string-format))
840 (if (> (length comment) 0)
841 (progn
842 (goto-char (todo-item-end))
e4541b67
OS
843 (insert
844 (if (save-excursion (beginning-of-line)
845 (looking-at (regexp-quote todo-prefix)))
846 " "
847 "\n\t")
848 "(" (nth todo-category-number todo-categories) ": "
849 comment ")\n")))
01b864bc
OS
850 (goto-char (todo-item-start))
851 (let ((temp-point (point)))
852 (if (looking-at (regexp-quote todo-prefix))
e4541b67
OS
853 (replace-match (time-stamp-string))
854 ;; Standard prefix -> timestamp
01b864bc
OS
855 ;; Else prefix non-standard item start with timestamp
856 (insert (time-stamp-string)))
857 (append-to-file temp-point (todo-item-end) todo-file-done)
858 (delete-region temp-point (1+ (todo-item-end))))
859 (todo-backward-item)
860 (message ""))
7f6241ea 861 (error "No TODO list entry to file away")))
3cb152f9
OS
862
863;; ---------------------------------------------------------------------------
864
7f6241ea
OS
865;; Utility functions:
866
e4541b67
OS
867
868;;;###autoload
869(defun todo-top-priorities (&optional nof-priorities category-pr-page)
870 "List top priorities for each category.
871
872Number of entries for each category is given by NOF-PRIORITIES which
873defaults to \'todo-show-priorities\'.
874
875If CATEGORY-PR-PAGE is non-nil, a page separator \'^L\' is inserted
876between each category."
877
878 (interactive "P")
879 (or nof-priorities (setq nof-priorities todo-show-priorities))
880 (if (listp nof-priorities) ;universal argument
881 (setq nof-priorities (car nof-priorities)))
85b3b166
OS
882 (let ((todo-print-buffer-name "*Tmp*")
883 ;;(todo-print-category-number 0)
884 (todo-category-break (if category-pr-page "\f" ""))
e4541b67
OS
885 (cat-end
886 (concat
887 (if todo-remove-separator
888 (concat todo-category-end "\n"
889 (regexp-quote todo-prefix) " " todo-category-sep "\n")
890 (concat todo-category-end "\n"))))
891 beg end)
892 (todo-show)
893 (save-excursion
894 (save-restriction
895 (widen)
85b3b166
OS
896 (copy-to-buffer todo-print-buffer-name (point-min) (point-max))
897 (set-buffer todo-print-buffer-name)
e4541b67
OS
898 (goto-char (point-min))
899 (if (re-search-forward (regexp-quote todo-header) nil t)
900 (progn
901 (beginning-of-line 1)
902 (kill-line))) ;Remove mode line
903 (while (re-search-forward ;Find category start
904 (regexp-quote (concat todo-prefix todo-category-beg))
905 nil t)
906 (setq beg (+ (point-at-eol) 1)) ;Start of first entry.
907 (re-search-forward cat-end nil t)
908 (setq end (match-beginning 0))
909 (replace-match todo-category-break)
910 (narrow-to-region beg end) ;In case we have too few entries.
911 (goto-char (point-min))
912 (if (= 0 nof-priorities) ;Traverse entries.
913 (goto-char end) ;All entries
914 (todo-forward-item nof-priorities))
915 (setq beg (point))
916 (delete-region beg end)
917 (widen))
f1757bdd 918 (and (looking-at "\f") (replace-match "")) ;Remove trailing form-feed.
e4541b67
OS
919 (goto-char (point-min)) ;Due to display buffer
920 ))
921 ;; Could have used switch-to-buffer as it has a norecord argument,
922 ;; which is nice when we are called from e.g. todo-print.
f1757bdd 923 ;; Else we could have used pop-to-buffer.
85b3b166 924 (display-buffer todo-print-buffer-name)
e4541b67 925 (message "Type C-x 1 to remove %s window. M-C-v to scroll the help."
85b3b166 926 todo-print-buffer-name)
e4541b67
OS
927 ))
928
f1757bdd
OS
929;;;###autoload
930(defun todo-save-top-priorities (&optional nof-priorities)
931 "Save top priorities for each category in `todo-file-top'.
932
933Number of entries for each category is given by NOF-PRIORITIES which
934defaults to `todo-show-priorities'."
935 (interactive "P")
936 (save-window-excursion
937 (save-excursion
938 (save-restriction
939 (todo-top-priorities nof-priorities)
940 (set-buffer todo-tmp-buffer-name)
941 (write-file todo-file-top)
942 (kill-this-buffer)
943 ))))
944
e4541b67
OS
945;;;###autoload
946(defun todo-print (&optional category-pr-page)
947 "Print todo summary using \\\[todo-print-function].
948If CATEGORY-PR-PAGE is non-nil, a page separator \'^L\' is inserted
949between each category.
950
951Number of entries for each category is given by
952\'todo-print-priorities\'."
953 (interactive "P")
f1757bdd
OS
954 (if todo-print-function
955 (progn
e4541b67
OS
956 (save-window-excursion
957 (save-excursion
958 (save-restriction
959 (todo-top-priorities todo-print-priorities
960 category-pr-page)
f1757bdd
OS
961 (set-buffer todo-tmp-buffer-name)
962 (and (funcall todo-print-function)
963 (kill-this-buffer))
e4541b67 964 (message "Todo printing done."))
f1757bdd
OS
965 )))
966 (message "todo-print-function undefinded")
967 ))
e4541b67
OS
968
969(defun todo-jump-to-category ()
970 "Jump to a category. Default is previous category."
971 (interactive)
972 (let* ((categories todo-categories)
973 (history (cons 'categories (1+ todo-category-number)))
974 (category (completing-read
975 (concat "Category ["
976 (nth todo-category-number todo-categories) "]: ")
977 (todo-category-alist) nil nil nil history)))
978 (if (string= "" category)
979 (setq category (nth todo-category-number todo-categories)))
980 (setq todo-category-number
981 (if (member category todo-categories)
982 (- (length todo-categories)
983 (length (member category todo-categories)))
984 (todo-add-category category)))
985 (todo-show)))
986
7f6241ea
OS
987(defun todo-line-string () "Return current line in buffer as a string."
988 (buffer-substring (point-at-bol) (point-at-eol)))
989
990(defun todo-item-string-start ()
991 "Return the start of this TODO list entry as a string."
992 ;; Suitable for putting in the minibuffer when asking the user
993 (let ((item (todo-item-string)))
994 (if (> (length item) 60)
01b864bc 995 (setq item (concat (substring item 0 56) "...")))
7f6241ea
OS
996 item))
997
998(defun todo-item-start () "Return point at start of current TODO list item."
999 (save-excursion
1000 (beginning-of-line)
1001 (if (not (looking-at (regexp-quote todo-prefix)))
01b864bc
OS
1002 (search-backward-regexp
1003 (concat "^" (regexp-quote todo-prefix)) nil t))
7f6241ea
OS
1004 (point)))
1005
1006(defun todo-item-end () "Return point at end of current TODO list item."
1007 (save-excursion
1008 (end-of-line)
e4541b67
OS
1009 (search-forward-regexp
1010 (concat "^" (regexp-quote todo-prefix)) nil 'goto-end)
7f6241ea
OS
1011 (1- (point-at-bol))))
1012
1013(defun todo-remove-item () "Delete the current entry from the TODO list."
1014 (delete-region (todo-item-start) (1+ (todo-item-end))))
1015
1016(defun todo-item-string () "Return current TODO list entry as a string."
1017 (buffer-substring (todo-item-start) (todo-item-end)))
1018
1019(defun todo-string-count-lines (string)
1020 "Return the number of lines STRING spans."
1021 (length (split-string string "\n")))
1022
1023(defun todo-string-multiline-p (string)
85b3b166 1024 "Return non-nil if STRING spans several lines."
7f6241ea
OS
1025 (> (todo-string-count-lines string) 1))
1026
1027(defun todo-category-alist ()
85b3b166 1028 "Generate an alist for use in `completing-read' from `todo-categories'."
b7e04170 1029 (mapcar (lambda (cat) (cons cat nil))
01b864bc 1030 todo-categories))
7f6241ea 1031
da2ee685
OS
1032;; utility functions: These are available in XEmacs, but not in Emacs 19.34
1033
1034(if (not (fboundp 'point-at-bol))
7f6241ea 1035 (defun point-at-bol () "Return value of point at beginning of line."
da2ee685 1036 (save-excursion
01b864bc
OS
1037 (beginning-of-line)
1038 (point))))
da2ee685
OS
1039
1040(if (not (fboundp 'point-at-eol))
7f6241ea 1041 (defun point-at-eol () "Return value of point at end of line."
da2ee685 1042 (save-excursion
01b864bc
OS
1043 (end-of-line)
1044 (point))))
da2ee685 1045
2186b974
OS
1046;; splits at a white space, returns a list
1047(if (not (fboundp 'split-string))
91e9443e
OS
1048 (defun split-string (string &optional separators)
1049 "Splits STRING into substrings where there are matches for SEPARATORS.
1050Each match for SEPARATORS is a splitting point.
1051The substrings between the splitting points are made into a list
1052which is returned.
1053If SEPARATORS is absent, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
1054 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
01b864bc
OS
1055 (start 0)
1056 (list nil))
1057 (while (string-match rexp string start)
1058 (or (eq (match-beginning 0) 0)
1059 (setq list
1060 (cons (substring string start (match-beginning 0))
1061 list)))
1062 (setq start (match-end 0)))
1063 (or (eq start (length string))
1064 (setq list
1065 (cons (substring string start)
1066 list)))
1067 (nreverse list))))
2186b974 1068
da2ee685
OS
1069;; ---------------------------------------------------------------------------
1070
49c48a1b 1071(easy-menu-define todo-menu todo-mode-map "Todo Menu"
01b864bc
OS
1072 '("Todo"
1073 ["Next category" todo-forward-category t]
1074 ["Previous category" todo-backward-category t]
e4541b67
OS
1075 ["Jump to category" todo-jump-to-category t]
1076 ["Show top priority items" todo-top-priorities t]
1077 ["Print categories" todo-print t]
01b864bc
OS
1078 "---"
1079 ["Edit item" todo-edit-item t]
1080 ["File item" todo-file-item t]
1081 ["Insert new item" todo-insert-item t]
1082 ["Kill item" todo-delete-item t]
1083 "---"
1084 ["Lower item priority" todo-lower-item t]
1085 ["Raise item priority" todo-raise-item t]
1086 "---"
1087 ["Next item" todo-forward-item t]
1088 ["Previous item" todo-backward-item t]
1089 "---"
1090 ["Save" todo-save t]
f1757bdd 1091 ["Save Top Priorities" todo-save-top-priorities t]
01b864bc
OS
1092 "---"
1093 ["Quit" todo-quit t]
1094 ))
a360be79 1095
e4541b67
OS
1096;; As calendar reads .todo-do before todo-mode is loaded.
1097;;;### autoload
da2ee685 1098(defun todo-mode () "Major mode for editing TODO lists.\n\n\\{todo-mode-map}"
3cb152f9 1099 (interactive)
3cb152f9
OS
1100 (setq major-mode 'todo-mode)
1101 (setq mode-name "TODO")
1102 (use-local-map todo-mode-map)
49c48a1b
OS
1103 (easy-menu-add todo-menu)
1104 (run-hooks 'todo-mode-hook))
da2ee685 1105
7f6241ea
OS
1106(defun todo-edit-mode ()
1107 "Major mode for editing items in the TODO list\n\n\\{todo-edit-mode-map}"
1108 (text-mode)
1109 (setq major-mode 'todo-edit-mode)
1110 (setq mode-name "TODO Edit")
1111 (run-hooks 'todo-edit-mode-hook))
1112
e4541b67 1113;;;### autoload
da2ee685
OS
1114(defun todo-show () "Show TODO list."
1115 (interactive)
7f6241ea
OS
1116 (if (file-exists-p todo-file-do)
1117 (find-file todo-file-do)
1118 (todo-initial-setup))
1119 (if (null todo-categories)
1120 (if (null todo-cats)
01b864bc
OS
1121 (error "Error in %s: No categories in list `todo-categories'"
1122 todo-file-do)
1123 (goto-char (point-min))
1124 (and (search-forward "todo-cats:" nil t)
1125 (replace-match "todo-categories:"))
e05e3850 1126 (make-local-variable 'todo-categories)
01b864bc 1127 (setq todo-categories todo-cats)))
7f6241ea
OS
1128 (beginning-of-line)
1129 (todo-category-select))
1130
1131(defun todo-initial-setup () "Set up things to work properly in TODO mode."
da2ee685 1132 (find-file todo-file-do)
7f6241ea
OS
1133 (erase-buffer)
1134 (todo-mode)
1135 (todo-add-category "Todo"))
3cb152f9 1136
7c896f63 1137(provide 'todo-mode)
3cb152f9
OS
1138
1139;; ---------------------------------------------------------------------------
7c896f63 1140;;; todo-mode.el ends here
3cb152f9 1141;; ---------------------------------------------------------------------------