todo-mode.el 4.69 KB
Newer Older
Oliver Seidel's avatar
Oliver Seidel committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
;; todomode.el -- major mode for editing Todo-List files

;; ---------------------------------------------------------------------------

;; Note: You may copy this file freely for non-commercial use; otherwise,
;;       please contact   (address) O Seidel, Lessingstr 8, Eschborn, FRG
;;                        (e-mail ) Oliver.Seidel@cl.cam.ac.uk (2 Aug 1997)

;; $Id:$
;;
;; $Log:$
;;

;; ---------------------------------------------------------------------------

;; User-configurable variables:

(defvar todo-file-do   "~/.todo-do"   "TODO mode filename of list file")
(defvar todo-file-done "~/.todo-done" "TODO mode filename of archive file")
(defvar todo-mode-hook nil "Hooks invoked when the *TODO* buffer is created.")

;; ---------------------------------------------------------------------------

(require 'time-stamp)

(defvar todo-begin (point-min) "TODO mode beginning of line")
(defvar todo-end   (point-min) "TODO mode end of line")

(setq todo-mode-map (make-keymap))
(suppress-keymap todo-mode-map)
(define-key todo-mode-map "p" 'todo-cmd-prev)
(define-key todo-mode-map "n" 'todo-cmd-next)
(define-key todo-mode-map "q" 'todo-cmd-done)
(define-key todo-mode-map "e" 'todo-cmd-edit)
(define-key todo-mode-map "i" 'todo-cmd-inst)
(define-key todo-mode-map "k" 'todo-cmd-kill)
(define-key todo-mode-map "f" 'todo-cmd-file)

(defun todo-cmd-prev () "Select previous entry."
  (interactive)
  (forward-line -1)
  (beginning-of-line nil)
  (message "")
  )

(defun todo-cmd-next () "Select next entry."
  (interactive)
  (forward-line 1)
  (beginning-of-line nil)
  (message "")
  )

(defun todo-cmd-done () "Done with todo list for now."
  (interactive)
  (save-buffer)
  (bury-buffer)
  )

(defun todo-line () "Find current line in buffer."
  (end-of-line nil)       (setq todo-end (point))
  (beginning-of-line nil) (setq todo-begin (point))
  (buffer-substring todo-begin todo-end)
  )

(defun todo-cmd-edit () "Edit current todo list entry."
  (interactive)
  (setq todo-entry (todo-line))
  (delete-region todo-begin todo-end)
  (insert (read-from-minibuffer "Edit: " todo-entry))
  (beginning-of-line nil)
  (message "")
  )

(defvar todo-prv-lne 0 "previous line that I asked about.")
(defvar todo-prv-ans 0 "previous answer that I got.")

(defun todo-ask (lne) "Ask whether entry is more important than at LNE."
  (if (not (equal todo-prv-lne lne) )
      (progn
	(setq todo-prv-lne lne)
	(goto-line todo-prv-lne)
	(setq todo-prv-ans (y-or-n-p (concat "More important than '" (todo-line) "'? ")))
	)
    )
  todo-prv-ans
  )

(defun todo-cmd-inst () "Insert new todo list entry."
  (interactive)
  (setq todo-entry (read-from-minibuffer "New TODO entry: "))
  (save-window-excursion
    (find-file todo-file-do)
    (setq todo-prv-lne 0)
    (let* ((todo-fst 1)
	   (todo-lst (+ 1 (count-lines (point-min) (point-max)))))
      (while (< todo-fst todo-lst)
	(setq todo-cur (/ (+ todo-fst todo-lst) 2))
	(setq todo-ans (if (< todo-cur todo-lst) (todo-ask todo-cur) nil))
	(if todo-ans
	    (setq todo-lst todo-cur)
	  (setq todo-fst (+ todo-cur 1)))
	)
      (goto-line todo-fst)
      )
    (insert (concat todo-entry "\n"))
    (forward-char -1)
    )
  (beginning-of-line nil)
  (message "")
  )

(defun todo-cmd-kill () "Delete current todo list entry."
  (interactive)
  (if (> (count-lines (point-min) (point-max)) 0)
      (progn
	(setq todo-entry (todo-line))
	(setq todo-answer (y-or-n-p (concat "Permanently remove '" todo-entry "'? ")))
	(if todo-answer (progn (delete-region todo-begin (+ 1 todo-end)) (forward-char -1)))
	)
    (message "No entry to delete.")
    )
  (beginning-of-line nil)
  (message "")
  )

(defun todo-cmd-file () "File away the current todo list entry."
  (interactive)
  (if (> (count-lines (point-min) (point-max)) 0)
      (progn
	(setq time-stamp-format " %2d, %y, %02I:%02M%p %b")
	(setq tmp (time-stamp-string))
	(beginning-of-line nil)
	(insert (concat (substring tmp 19 22) (substring tmp 0 19)))
	(end-of-line nil)
	(insert (concat " (" (read-from-minibuffer "Comment: ") ")"))
	(todo-line)
	(append-to-file todo-begin (+ 1 todo-end) todo-file-done)
	(delete-region todo-begin (+ 1 todo-end))
	(forward-char -1)
	)
    (message "No entry to delete.")
    )
  (beginning-of-line nil)
  (message "")
  )

;; ---------------------------------------------------------------------------

(defun todo-mode ()
  "Major mode for editing TODO lists.\n\n\\{todo-mode-map}"
  (interactive)
  (find-file todo-file-do)
  (setq major-mode 'todo-mode)
  (setq mode-name "TODO")
  (use-local-map todo-mode-map)
  (run-hooks 'todo-mode-hook) )

(provide 'todomode)

;; ---------------------------------------------------------------------------

;;; todomode.el ends here

;; ---------------------------------------------------------------------------