;;; todo-mode.el --- facilities for making and maintaining todo lists
-;; Copyright (C) 1997, 1999, 2001-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2016 Free Software Foundation, Inc.
;; Author: Oliver Seidel <privat@os10000.net>
;; Stephen Berman <stephen.berman@gmx.net>
(let ((files (if (file-exists-p todo-directory)
(mapcar 'file-truename
(directory-files todo-directory t
- (if archives "\.toda$" "\.todo$") t)))))
+ (if archives "\\.toda$" "\\.todo$") t)))))
(sort files (lambda (s1 s2) (let ((cis1 (upcase s1))
(cis2 (upcase s2)))
(string< cis1 cis2))))))
(when (string= (widget-value widget) todo-item-mark)
(widget-put
widget :error
- "Invalid value: must be distinct from `todo-item-mark'")
+ (format-message
+ "Invalid value: must be distinct from `todo-item-mark'"))
widget)))
:initialize 'custom-initialize-default
:set 'todo-reset-prefix
todo-filtered-items-mode))))
(if (funcall todo-files-function)
(todo-read-file-name "Choose a todo file to visit: "
- nil t)
+ nil t)
(user-error "There are no todo files")))
((and (eq major-mode 'todo-archive-mode)
;; Called noninteractively via todo-quit
(when (or (member file todo-visited)
(eq todo-show-first 'first))
(unless (todo-check-file file) (throw 'end nil))
- (set-window-buffer (selected-window)
+ ;; If todo-show is called from the minibuffer, don't visit
+ ;; the todo file there.
+ (set-window-buffer (if (minibufferp) (minibuffer-selected-window)
+ (selected-window))
(set-buffer (find-file-noselect file 'nowarn)))
(if (equal (file-name-extension (buffer-file-name)) "toda")
(unless (derived-mode-p 'todo-archive-mode) (todo-archive-mode))
(setq todo-category-number (todo-category-number cat)))
;; If this is a new todo file, add its first category.
(when (zerop (buffer-size))
+ ;; Don't confuse an erased buffer with a fresh buffer for
+ ;; adding a new todo file -- it might have been erased by
+ ;; mistake or due to a bug (e.g. Bug#20832).
+ (when (buffer-modified-p)
+ (error "Buffer is empty but modified, please report a bug"))
(let (cat-added)
(unwind-protect
(setq todo-category-number
(snname (todo-short-file-name nname))
(files (directory-files todo-directory t
(concat ".*" (regexp-quote soname)
- ".*\.tod[aorty]$") t)))
+ ".*\\.tod[aorty]$") t)))
(dolist (f files)
(let* ((sfname (todo-short-file-name f))
(fext (file-name-extension f t))
"deleting it will also delete the file.\n"
"Do you want to proceed? ")))
((> archived 0)
- (todo-y-or-n-p (concat "This category has archived items; "
+ (todo-y-or-n-p (format-message
+ (concat "This category has archived items; "
"the archived category will remain\n"
"after deleting the todo category. "
"Do you still want to delete it\n"
"(see `todo-skip-archived-categories' "
- "for another option)? ")))
+ "for another option)? "))))
(t
(todo-y-or-n-p (concat "Permanently remove category \"" cat
"\"" (and arg " and all its entries")
(when (string= (widget-value widget) todo-prefix)
(widget-put
widget :error
- "Invalid value: must be distinct from `todo-prefix'")
+ (format-message
+ "Invalid value: must be distinct from `todo-prefix'"))
widget)))
:set (lambda (symbol value)
(custom-set-default symbol (propertize value 'face 'todo-mark)))
(mlist (append tmn-array nil))
(tma-array todo-month-abbrev-array)
(mablist (append tma-array nil))
- (yy (and oyear (unless (string= oyear "*")
- (string-to-number oyear))))
- (mm (or (and omonth (unless (string= omonth "*")
+ (yy (and oyear (string-to-number oyear))) ; 0 if year is "*".
+ (mm (or (and omonth (if (string= omonth "*") 13
(string-to-number omonth)))
(1+ (- (length mlist)
(length (or (member omonthname mlist)
(if omonth
(number-to-string mm)
(aref tma-array (1- mm))))))
- (let ((yy (string-to-number year)) ; 0 if year is "*".
- ;; When mm is 13 (corresponding to "*" as value
- ;; of month), this raises an args-out-of-range
- ;; error in calendar-last-day-of-month, so use 1
- ;; (corresponding to January) to get 31 days.
- (mm (if (= mm 13) 1 mm)))
+ ;; Since the number corresponding to the arbitrary
+ ;; month name "*" is out of the range of
+ ;; calendar-last-day-of-month, set it to 1
+ ;; (corresponding to January) to allow 31 days.
+ (let ((mm (if (= mm 13) 1 mm)))
(if (> (string-to-number day)
(calendar-last-day-of-month mm yy))
(user-error "%s %s does not have %s days"
monthname omonthname
day (cond
((not current-prefix-arg)
- (todo-read-date 'day mm oyear))
+ (todo-read-date 'day mm yy))
((string= oday "*")
(user-error "Cannot increment *"))
((or (string= omonth "*") (string= omonthname "*"))
(defun todo-find-filtered-items-file ()
"Choose a filtered items file and visit it."
(interactive)
- (let ((files (directory-files todo-directory t "\.tod[rty]$" t))
+ (let ((files (directory-files todo-directory t "\\.tod[rty]$" t))
falist file)
(dolist (f files)
(let ((type (cond ((equal (file-name-extension f) "todr") "regexp")
(goto-char (match-beginning 0))
(goto-char (point-max)))
(backward-char)
- (when (looking-back "\\[\\([^][]+\\)\\]")
+ (when (looking-back "\\[\\([^][]+\\)\\]"
+ (line-beginning-position))
(setq cat (match-string 1))
(goto-char (match-beginning 0))
(replace-match ""))
;; If the item ends with a non-comment parenthesis not
;; followed by a period, we lose (but we inherit that
;; problem from the legacy code).
+ ;; FIXME: fails on multiline comment
(when (looking-back "(\\(.*\\)) " (line-beginning-position))
(setq comment (match-string 1))
(replace-match "")
(widen)
(goto-char (point-min))
(setq todo-categories
- (if (looking-at "\(\(\"")
+ (if (looking-at "((\"")
(read (buffer-substring-no-properties
(line-beginning-position)
(line-end-position)))
;; Warn user if categories sexp has changed.
(unless (string= ssexp cats)
(message (concat "The sexp at the beginning of the file differs "
- "from the value of `todo-categories.\n"
+ "from the value of `todo-categories'.\n"
"If the sexp is wrong, you can fix it with "
"M-x todo-repair-categories-sexp,\n"
"but note this reverts any changes you have "
(with-current-buffer buffer
(widen)
(let ((todo-category-number (cdr (assq 'catnum misc))))
- (todo-category-select))))
+ (todo-category-select)
+ (current-buffer))))
(add-to-list 'desktop-buffer-mode-handlers
'(todo-mode . todo-restore-desktop-buffer))
The list consists of item insertion parameters that can be passed
as insertion command arguments in fixed positions. If a position
in the list is not occupied by the corresponding parameter, it is
-occupied by `nil'."
+occupied by nil."
(let* ((arg (list (car todo-insert-item--args)))
(args (nconc (cdr todo-insert-item--args)
(list (car (todo-insert-item--argsleft
'(add/edit delete))
" comment"))))
params " "))
- (this-key (let ((key (read-key (concat todo-edit-item--prompt p->k))))
+ (key-prompt (substitute-command-keys todo-edit-item--prompt))
+ (this-key (let ((key (read-key (concat key-prompt p->k))))
(and (characterp key) (char-to-string key))))
(this-param (car (rassoc this-key params))))
(pcase this-param
(when deleted
(let ((pl (> (length deleted) 1))
(names (mapconcat (lambda (f) (concat "\"" f "\"")) deleted ", ")))
- (message (concat "File" (if pl "s" "") " " names " ha" (if pl "ve" "s")
+ (message (concat "File" (if pl "s" "") " %s ha" (if pl "ve" "s")
" been deleted and removed from\n"
- "the list of category completion files")))
+ "the list of category completion files")
+ names))
(todo-reevaluate-category-completions-files-defcustom)
(custom-set-default 'todo-category-completions-files
(symbol-value 'todo-category-completions-files))
(and day (setq day (if (eq day '*)
(symbol-name '*)
(number-to-string day))))
- (and month (setq month (if (eq month '*)
+ (and month (setq month (if (= month 13)
(symbol-name '*)
(number-to-string month))))
(if arg
"The :set function for user option `todo-nondiary-marker'."
(let* ((oldvalue (symbol-value symbol))
(files (append todo-files todo-archives
- (directory-files todo-directory t "\.tod[rty]$" t))))
+ (directory-files todo-directory t "\\.tod[rty]$" t))))
(custom-set-default symbol value)
;; Need to reset these to get font-locking right.
(setq todo-nondiary-start (nth 0 todo-nondiary-marker)
"The :set function for user option `todo-done-string'."
(let ((oldvalue (symbol-value symbol))
(files (append todo-files todo-archives
- (directory-files todo-directory t "\.todr$" t))))
+ (directory-files todo-directory t "\\.todr$" t))))
(custom-set-default symbol value)
;; Need to reset this to get font-locking right.
(setq todo-done-string-start
"The :set function for user option `todo-comment-string'."
(let ((oldvalue (symbol-value symbol))
(files (append todo-files todo-archives
- (directory-files todo-directory t "\.todr$" t))))
+ (directory-files todo-directory t "\\.todr$" t))))
(custom-set-default symbol value)
(when (not (equal value oldvalue))
(dolist (f files)
"The :set function for user option `todo-highlight-item'."
(let ((oldvalue (symbol-value symbol))
(files (append todo-files todo-archives
- (directory-files todo-directory t "\.tod[rty]$" t))))
+ (directory-files todo-directory t "\\.tod[rty]$" t))))
(custom-set-default symbol value)
(when (not (equal value oldvalue))
(dolist (f files)
"Make some settings that apply to multiple Todo modes."
(add-to-invisibility-spec 'todo)
(setq buffer-read-only t)
- (when (and (boundp 'desktop-save-mode) desktop-save-mode)
- (setq-local desktop-save-buffer 'todo-desktop-save-buffer))
+ (setq-local desktop-save-buffer 'todo-desktop-save-buffer)
(when (boundp 'hl-line-range-function)
(setq-local hl-line-range-function
(lambda() (save-excursion
\\{todo-mode-map}"
(if (called-interactively-p 'any)
- (message "Type `M-x todo-show' to enter Todo mode")
+ (message "%s"
+ (substitute-command-keys
+ "Type `\\[todo-show]' to enter Todo mode"))
(todo-modes-set-1)
(todo-modes-set-2)
(todo-modes-set-3)