]> code.delx.au - gnu-emacs/blobdiff - lisp/calendar/todo-mode.el
(calendar-mode-map, calendar-mouse-3-map): Refer to
[gnu-emacs] / lisp / calendar / todo-mode.el
index ce37bd523f77f66af615c4a773ed00f8bd950525..6f96ec1cdb224385d2b7cebabcb308516bbe6d4e 100644 (file)
@@ -1,12 +1,12 @@
-;; todo-mode.el -- Major mode for editing TODO list files
+;;; todo-mode.el --- major mode for editing TODO list files
 
-;; Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001, 2002, 2003, 2004, 2005, 2006
+;;   Free Software Foundation, Inc.
 
-;; Author: Oliver.Seidel@cl.cam.ac.uk
-;; Maintainer: FSF (unless Seidel can be found)
+;; Author: Oliver Seidel <os10000@seidel-space.de>
+;;   [Not clear the above works, July 2000]
 ;; Created: 2 Aug 1997
-;; Version: $Id: todo-mode.el,v 1.39 2000/05/12 10:56:20 fx Exp $
-;; Keywords: Categorised TODO list editor, todo-mode
+;; Keywords: calendar, todo
 
 ;; This file is part of GNU Emacs.
 
@@ -22,8 +22,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;; ---------------------------------------------------------------------------
 
 ;;      You may now enter new items by typing "M-x todo-insert-item",
 ;;      or enter your TODO list file by typing "M-x todo-show".
 ;;
-;;      -------------------------------------------------------------
-;;
-;;      oh no, it doesn't work any more ... but Alex Schroeder
-;;      <a.schroeder@bsiag.ch> writes:
-;;
-;;      -------------------------------------------------------------
-;;
-;;      1. Call todo-show (I called todo-insert first)
-;;      2. Add some categories (I called todo-insert)
-;;      3. Save the buffer, restart Emacs (perhaps restarting Emacs is not
-;;         required)
-;;      4. Only now can you start to add entries.
-;;
-;;      This is a bit cumbersome, and it should be documented.  You probably
-;;
-;;      -------------------------------------------------------------
-;;
-;;      and right he is.  My apologies, I'll try to fix it sometime.
-;;
-;;      -------------------------------------------------------------
-;;
 ;;      The TODO list file has a special format and some auxiliary
 ;;      information, which will be added by the todo-show function if
 ;;      it attempts to visit an un-initialised file.  Hence it is
 ;;      extensions that are not explicitly listed in the above quick
 ;;      installation.
 ;;
-;;  Version
+;;  Pre-Requisites
 ;;
-;;      Which version of todo-mode.el does this documentation refer to?
+;;      This package will require the following packages to be
+;;      available on the load-path:
 ;;
-;;      $Id: todo-mode.el,v 1.39 2000/05/12 10:56:20 fx Exp $
+;;          time-stamp
+;;          easymenu
 ;;
 ;;  Operation
 ;;
 ;;
 ;;         M-x todo-show   will enter the todo list screen, here type
 ;;
-;;        spc  will toggle the display of sub-trees
-;;
 ;;         +  to go to next category
 ;;          -  to go to previous category
 ;;          d  to file the current entry, including a
 
 ;;; Code:
 
-(eval-when-compile
-  (require 'outline)
-  (require 'calendar)
-  ;; Calendar dynamic bondage:
-  (defvar date)
-  (defvar entry))
-(autoload 'time-stamp-string "time-stamp")
+(require 'time-stamp)
+
 
 ;; User-configurable variables:
 
 (defgroup todo nil
   "Maintain a list of todo items."
+  :link '(emacs-commentary-link "todo-mode")
   :version "21.1"
   :group 'calendar)
 
-(defcustom todo-prefix "*/*"
+(defcustom todo-prefix     "*/*"
   "*TODO mode prefix for entries.
 
 This is useful in conjunction with `calendar' and `diary' if you use
@@ -309,11 +284,11 @@ show and mark todo entreis for today, but may slow down processing of
 the diary file somewhat."
   :type 'string
   :group 'todo)
-(defcustom todo-file-do "~/.todo-do"
+(defcustom todo-file-do    "~/.todo-do"
   "*TODO mode list file."
   :type 'file
   :group 'todo)
-(defcustom todo-file-done "~/.todo-done"
+(defcustom todo-file-done  "~/.todo-done"
   "*TODO mode archive file."
   :type 'file
   :group 'todo)
@@ -337,11 +312,12 @@ which it will stop.  If you set the threshhold to zero, the upper and
 lower bound will coincide at the end of the loop and you will insert
 your item just before that point.  If you set the threshhold to,
 e.g. 8, it will stop as soon as the window size drops below that
-amount and will insert the item in the approximate centre of that
+amount and will insert the item in the approximate center of that
 window."
   :type 'integer
   :group 'todo)
-(defvar todo-edit-buffer " *TODO Edit*" "TODO Edit buffer name.")
+(defvar todo-edit-buffer " *TODO Edit*"
+  "TODO Edit buffer name.")
 (defcustom todo-file-top "~/.todo-top"
   "*TODO mode top priorities file.
 
@@ -378,7 +354,7 @@ Automatically generated when `todo-save-top-priorities' is non-nil."
 ;; My format string for the appt.el package is "%3b %2d, %y, %02I:%02M%p".
 ;;
 (defcustom todo-time-string-format
-  "%04y-%02m-%02d %02H:%02M"
+  "%:y-%02m-%02d %02H:%02M"
   "*TODO mode time string format for done entries.
 For details see the variable `time-stamp-format'."
   :type 'string
@@ -398,36 +374,26 @@ For details see the variable `time-stamp-format'."
   (let ((time-stamp-format todo-time-string-format))
     (concat (time-stamp-string) " " todo-initials ": ")))
 
+;; ---------------------------------------------------------------------------
+
 ;; Set up some helpful context ...
 
 (defvar todo-categories nil
   "TODO categories.")
+
 (defvar todo-cats nil
   "Old variable for holding the TODO categories.
 Use `todo-categories' instead.")
-(defvar todo-previous-line      0
-  "Previous line asked about.")
-(defvar todo-previous-answer    0
-  "Previous answer got.")
-(defvar todo-category-number    0
-  "TODO category number.")
 
-(defvar todo-category-sep (make-string 75 ?-)
-  "Category separator.")
-(defvar todo-category-beg " --- "
-  "Category start separator to be prepended onto category name.")
-(defvar todo-category-end "--- End"
-  "Separator after a category.")
-(defvar todo-header "-*- mode: todo; "
-  "Header of todo files.")
+(defvar todo-previous-line 0
+  "Previous line asked about.")
 
-;; ---------------------------------------------------------------------------
+(defvar todo-previous-answer 0
+  "Previous answer got.")
 
 (defvar todo-mode-map
   (let ((map (make-keymap)))
     (suppress-keymap map t)
-    (define-key map "?" 'todo-help)
-    (define-key map " " 'todo-hide-show-subtree)
     (define-key map "+" 'todo-forward-category)
     (define-key map "-" 'todo-backward-category)
     (define-key map "d" 'todo-file-item) ;done/delete
@@ -450,22 +416,29 @@ Use `todo-categories' instead.")
     map)
   "TODO mode keymap.")
 
-(defun todo-position (item list)
-  "Return the position of the element in LIST testing `equal' to ITEM.
-Return nil if ITEM not found."
-  (let ((pos 0)
-       found)
-    (while list
-      (if (equal item (pop list))
-         (setq list nil
-               found pos)
-       (setq pos (1+ pos))))
-    found))
+(defvar todo-category-number 0 "TODO category number.")
+
+(defvar todo-tmp-buffer-name " *todo tmp*")
+
+(defvar todo-category-sep (make-string 75 ?-)
+  "Category separator.")
+
+(defvar todo-category-beg " --- "
+  "Category start separator to be prepended onto category name.")
+
+(defvar todo-category-end "--- End"
+  "Separator after a category.")
+
+(defvar todo-header "-*- mode: todo; "
+  "Header of todo files.")
+
+;; ---------------------------------------------------------------------------
 
 (defun todo-category-select ()
   "Make TODO mode display the current category correctly."
   (let ((name (nth todo-category-number todo-categories)))
     (setq mode-line-buffer-identification
+;;          (concat "Category: " name))
           (concat "Category: " (format "%18s" name)))
     (widen)
     (goto-char (point-min))
@@ -479,19 +452,6 @@ Return nil if ITEM not found."
       (goto-char (point-min)))))
 (defalias 'todo-cat-slct 'todo-category-select)
 
-(defun todo-help () "Show TODO mode help."
-  (interactive)
-  (describe-function 'todo-mode))
-
-(defun todo-hide-show-subtree ()
-  "Hide or Show subtrees in the TODO list."
-  (interactive)
-  (save-excursion
-    (end-of-line)
-    (if (outline-visible)
-       (hide-subtree)
-      (show-subtree))))
-
 (defun todo-forward-category ()
   "Go forward to TODO list of next category."
   (interactive)
@@ -526,14 +486,17 @@ Return nil if ITEM not found."
   (message ""))
 (defalias 'todo-cmd-next 'todo-forward-item)
 
-(defun todo-save () "Save the TODO list."
+(defun todo-save ()
+  "Save the TODO list."
   (interactive)
-  (save-buffer)
-  (if todo-save-top-priorities-too (todo-save-top-priorities))
-  )
+  (save-excursion
+    (save-restriction
+      (save-buffer)))
+  (if todo-save-top-priorities-too (todo-save-top-priorities)))
 (defalias 'todo-cmd-save 'todo-save)
 
-(defun todo-quit () "Done with TODO list for now."
+(defun todo-quit ()
+  "Done with TODO list for now."
   (interactive)
   (widen)
   (todo-save)
@@ -541,7 +504,8 @@ Return nil if ITEM not found."
   (bury-buffer))
 (defalias 'todo-cmd-done 'todo-quit)
 
-(defun todo-edit-item () "Edit current TODO list entry."
+(defun todo-edit-item ()
+  "Edit current TODO list entry."
   (interactive)
   (let ((item (todo-item-string)))
     (if (todo-string-multiline-p item)
@@ -559,16 +523,17 @@ Return nil if ITEM not found."
   (let ((buffer-name (generate-new-buffer-name todo-edit-buffer)))
     (switch-to-buffer
      (make-indirect-buffer
-      (find-buffer-visiting todo-file-do) buffer-name))
+      (file-name-nondirectory todo-file-do) buffer-name))
     (message "To exit, simply kill this buffer and return to list.")
     (todo-edit-mode)
     (narrow-to-region (todo-item-start) (todo-item-end))))
 
+;;;###autoload
 (defun todo-add-category (cat)
   "Add new category CAT to the TODO list."
   (interactive "sCategory: ")
   (save-window-excursion
-    (add-to-list 'todo-categories cat)
+    (setq todo-categories (cons cat todo-categories))
     (find-file todo-file-do)
     (widen)
     (goto-char (point-min))
@@ -584,10 +549,10 @@ Return nil if ITEM not found."
     (insert (format "%s%s%s\n%s\n%s %s\n"
                     todo-prefix todo-category-beg cat
                     todo-category-end
-                    todo-prefix todo-category-sep))
-    (save-buffer))
+                    todo-prefix todo-category-sep)))
   0)
 
+;;;###autoload
 (defun todo-add-item-non-interactively (new-item category)
   "Insert NEW-ITEM in TODO list as a new entry in CATEGORY."
   (save-excursion
@@ -595,9 +560,11 @@ Return nil if ITEM not found."
   (save-excursion
     (if (string= "" category)
         (setq category (nth todo-category-number todo-categories)))
-    (setq todo-category-number
-           (or (todo-position category todo-categories)
-               (todo-add-category category)))
+    (let ((cat-exists (member category todo-categories)))
+      (setq todo-category-number
+            (if cat-exists
+                (- (length todo-categories) (length cat-exists))
+              (todo-add-category category))))
     (todo-show)
     (setq todo-previous-line 0)
     (let ((top 1)
@@ -615,16 +582,11 @@ Return nil if ITEM not found."
       (forward-line (1- top)))
     (insert new-item "\n")
     (todo-backward-item)
-    (progn ;;; horrible os10000 hack to make items appear when inserting into empty buffer
-     (widen)
-     (show-all)
-     (todo-forward-category)
-     (todo-backward-category))
     (todo-save)
     (message "")))
 
 ;;;###autoload
-(defun todo-insert-item (ARG)
+(defun todo-insert-item (arg)
   "Insert new TODO list entry.
 With a prefix argument solicit the category, otherwise use the current
 category."
@@ -640,12 +602,11 @@ category."
           (history (cons 'categories (1+ todo-category-number)))
           (current-category (nth todo-category-number todo-categories))
           (category
-           (if ARG
+           (if arg
                current-category
-             (completing-read
-              (concat "Category ["
-                      current-category "]: ")
-              (todo-category-alist) nil nil nil history))))
+             (completing-read (concat "Category [" current-category "]: ")
+                              (todo-category-alist) nil nil nil
+                              history current-category))))
       (todo-add-item-non-interactively new-item category))))
 
 (defalias 'todo-cmd-inst 'todo-insert-item)
@@ -675,7 +636,8 @@ category."
   todo-previous-answer)
 (defalias 'todo-ask-p 'todo-more-important-p)
 
-(defun todo-delete-item () "Delete current TODO list entry."
+(defun todo-delete-item ()
+  "Delete current TODO list entry."
   (interactive)
   (if (> (count-lines (point-min) (point-max)) 0)
       (let* ((todo-entry (todo-item-string-start))
@@ -689,7 +651,8 @@ category."
     (error "No TODO list entry to delete")))
 (defalias 'todo-cmd-kill 'todo-delete-item)
 
-(defun todo-raise-item () "Raise priority of current entry."
+(defun todo-raise-item ()
+  "Raise priority of current entry."
   (interactive)
   (if (> (count-lines (point-min) (point)) 0)
       (let ((item (todo-item-string)))
@@ -699,9 +662,10 @@ category."
           (insert item "\n"))
         (message ""))
     (error "No TODO list entry to raise")))
-(defalias 'todo-cmd-raise 'todo-raise-item)
+(defalias 'todo-cmd-rais 'todo-raise-item)
 
-(defun todo-lower-item () "Lower priority of current entry."
+(defun todo-lower-item ()
+  "Lower priority of current entry."
   (interactive)
   (if (> (count-lines (point) (point-max)) 1)
       ;; Assume there is a final newline
@@ -747,6 +711,8 @@ category."
 
 ;; Utility functions:
 
+
+;;;###autoload
 (defun todo-top-priorities (&optional nof-priorities category-pr-page)
   "List top priorities for each category.
 
@@ -760,7 +726,7 @@ between each category."
   (or nof-priorities (setq nof-priorities todo-show-priorities))
   (if (listp nof-priorities)            ;universal argument
       (setq nof-priorities (car nof-priorities)))
-  (let ((todo-print-buffer-name " *todo-tmp*")
+  (let ((todo-print-buffer-name todo-tmp-buffer-name)
         ;;(todo-print-category-number 0)
         (todo-category-break (if category-pr-page "\f" ""))
         (cat-end
@@ -777,10 +743,9 @@ between each category."
         (copy-to-buffer todo-print-buffer-name (point-min) (point-max))
         (set-buffer todo-print-buffer-name)
         (goto-char (point-min))
-        (if (re-search-forward (regexp-quote todo-header) nil t)
-            (progn
-              (beginning-of-line 1)
-              (kill-line)))             ;Remove mode line
+        (when (re-search-forward (regexp-quote todo-header) nil t)
+         (beginning-of-line 1)
+         (delete-region (point) (line-end-position)))
         (while (re-search-forward       ;Find category start
                 (regexp-quote (concat todo-prefix todo-category-beg))
                 nil t)
@@ -812,39 +777,48 @@ between each category."
 Number of entries for each category is given by NOF-PRIORITIES which
 defaults to `todo-show-priorities'."
   (interactive "P")
-  (with-temp-buffer
-    (todo-top-priorities nof-priorities)
-    (write-file todo-file-top)))
+  (save-window-excursion
+    (save-excursion
+      (save-restriction
+        (todo-top-priorities nof-priorities)
+        (set-buffer todo-tmp-buffer-name)
+        (write-file todo-file-top)
+        (kill-this-buffer)))))
 
 ;;;###autoload
 (defun todo-print (&optional category-pr-page)
   "Print todo summary using `todo-print-function'.
-If CATEGORY-PR-PAGE is non-nil, a page separator \'^L\' is inserted
+If CATEGORY-PR-PAGE is non-nil, a page separator `^L' is inserted
 between each category.
 
-Number of entries for each category is given by
-\'todo-print-priorities\'."
+Number of entries for each category is given by `todo-print-priorities'."
   (interactive "P")
-  (with-temp-buffer
-    (todo-top-priorities todo-print-priorities
+  (save-window-excursion
+    (save-excursion
+      (save-restriction
+       (todo-top-priorities todo-print-priorities
                             category-pr-page)
-    (funcall todo-print-function)
-    (message "Todo printing done.")))
+       (set-buffer todo-tmp-buffer-name)
+       (and (funcall todo-print-function)
+            (kill-this-buffer))
+       (message "Todo printing done.")))))
 
 (defun todo-jump-to-category ()
   "Jump to a category.  Default is previous category."
   (interactive)
   (let* ((categories todo-categories)
-        (history (cons 'categories (1+ todo-category-number)))
+         (history (cons 'categories (1+ todo-category-number)))
+        (default (nth todo-category-number todo-categories))
         (category (completing-read
-                    (concat "Category ["
-                            (nth todo-category-number todo-categories) "]: ")
-                    (todo-category-alist) nil nil nil history)))
+                    (concat "Category [" default "]: ")
+                    (todo-category-alist) nil nil nil history default)))
     (if (string= "" category)
         (setq category (nth todo-category-number todo-categories)))
     (setq todo-category-number
-         (or (todo-position category todo-categories)
-             (todo-add-category category)))
+          (if (member category todo-categories)
+              (- (length todo-categories)
+                 (length (member category todo-categories)))
+            (todo-add-category category)))
     (todo-show)))
 
 (defun todo-line-string ()
@@ -880,7 +854,8 @@ Number of entries for each category is given by
   "Delete the current entry from the TODO list."
   (delete-region (todo-item-start) (1+ (todo-item-end))))
 
-(defun todo-item-string () "Return current TODO list entry as a string."
+(defun todo-item-string ()
+  "Return current TODO list entry as a string."
   (buffer-substring (todo-item-start) (todo-item-end)))
 
 (defun todo-string-count-lines (string)
@@ -897,32 +872,31 @@ Number of entries for each category is given by
 
 ;; ---------------------------------------------------------------------------
 
-(easy-menu-define
- todo-menu todo-mode-map "Todo Menu"
- '("Todo"
-   ["Next category"        todo-forward-category t]
-   ["Previous category"    todo-backward-category t]
-   ["Jump to category"     todo-jump-to-category t]
-   ["Show top priority items" todo-top-priorities t]
-   ["Print categories"     todo-print t]
-   "---"
-   ["Edit item"            todo-edit-item t]
-   ["File item"            todo-file-item t]
-   ["Insert new item"      todo-insert-item t]
-   ["Insert item here"     todo-insert-item-here t]
-   ["Kill item"            todo-delete-item t]
-   "---"
-   ["Lower item priority"  todo-lower-item t]
-   ["Raise item priority"  todo-raise-item t]
-   "---"
-   ["Next item"            todo-forward-item t]
-   ["Previous item"        todo-backward-item t]
-   "---"
-   ["Save"                 todo-save t]
-   ["Save Top Priorities"  todo-save-top-priorities t]
-   "---"
-   ["Quit"                 todo-quit t]
-   ))
+(easy-menu-define todo-menu todo-mode-map "Todo Menu"
+                  '("Todo"
+                    ["Next category"        todo-forward-category t]
+                    ["Previous category"    todo-backward-category t]
+                    ["Jump to category"     todo-jump-to-category t]
+                    ["Show top priority items" todo-top-priorities t]
+                    ["Print categories"     todo-print t]
+                    "---"
+                    ["Edit item"            todo-edit-item t]
+                    ["File item"            todo-file-item t]
+                    ["Insert new item"      todo-insert-item t]
+                    ["Insert item here"     todo-insert-item-here t]
+                    ["Kill item"            todo-delete-item t]
+                    "---"
+                    ["Lower item priority"  todo-lower-item t]
+                    ["Raise item priority"  todo-raise-item t]
+                    "---"
+                    ["Next item"            todo-forward-item t]
+                    ["Previous item"        todo-backward-item t]
+                    "---"
+                    ["Save"                 todo-save t]
+                    ["Save Top Priorities"  todo-save-top-priorities t]
+                    "---"
+                    ["Quit"                 todo-quit t]
+                    ))
 
 ;; As calendar reads .todo-do before todo-mode is loaded.
 ;;;###autoload
@@ -931,20 +905,16 @@ Number of entries for each category is given by
 
 \\{todo-mode-map}"
   (interactive)
+  (kill-all-local-variables)
   (setq major-mode 'todo-mode)
   (setq mode-name "TODO")
   (use-local-map todo-mode-map)
   (easy-menu-add todo-menu)
-  (setq fill-prefix "\t\t")
-  (let ((prefix (regexp-quote todo-prefix)))
-    (setq paragraph-separate prefix)
-    (setq outline-regexp prefix))
-  (outline-minor-mode 1)
-  (goto-char (point-min))
-  (outline-next-heading)               ; get past -*- line
-  (hide-other)
-  (auto-fill-mode 1)
-  (run-hooks 'todo-mode-hook))
+  (run-mode-hooks 'todo-mode-hook))
+
+(eval-when-compile
+  (defvar date)
+  (defvar entry))
 
 ;; Read about this function in the setup instructions above!
 ;;;###autoload
@@ -953,14 +923,10 @@ Number of entries for each category is given by
   (if (equal (calendar-current-date) date)
       entry))
 
-(defun todo-edit-mode ()
+(define-derived-mode todo-edit-mode text-mode "TODO Edit"
   "Major mode for editing items in the TODO list.
 
-\\{todo-edit-mode-map}"
-  (text-mode)
-  (setq major-mode 'todo-edit-mode)
-  (setq mode-name "TODO Edit")
-  (run-hooks 'todo-edit-mode-hook))
+\\{todo-edit-mode-map}")
 
 ;;;###autoload
 (defun todo-show ()
@@ -990,6 +956,5 @@ Number of entries for each category is given by
 
 (provide 'todo-mode)
 
-;; ---------------------------------------------------------------------------
+;;; arch-tag: 6fd91be5-776e-4464-a109-da4ea0e4e497
 ;;; todo-mode.el ends here
-;; ---------------------------------------------------------------------------