]> code.delx.au - gnu-emacs/blobdiff - lisp/calendar/todo-mode.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / calendar / todo-mode.el
index 27ca17b4e4fe1641a2b0eb4915279e8c3718d029..8e7525860530f3d6f9bb743f147ba610e692f84b 100644 (file)
@@ -1,6 +1,6 @@
 ;;; 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>
@@ -612,11 +612,12 @@ Otherwise, `todo-show' always visits `todo-default-todo-file'."
 (defun todo-show (&optional solicit-file interactive)
   "Visit a todo file and display one of its categories.
 
-When invoked in Todo mode, prompt for which todo file to visit.
-When invoked outside of Todo mode with non-nil prefix argument
-SOLICIT-FILE prompt for which todo file to visit; otherwise visit
-`todo-default-todo-file'.  Subsequent invocations from outside
-of Todo mode revisit this file or, with option
+When invoked in Todo mode, Todo Archive mode or Todo Filtered
+Items mode, or when invoked anywhere else with a prefix argument,
+prompt for which todo file to visit.  When invoked outside of a
+Todo mode buffer without a prefix argument, visit
+`todo-default-todo-file'.  Subsequent invocations from outside of
+Todo mode revisit this file or, with option
 `todo-show-current-file' non-nil (the default), whichever todo
 file was last visited.
 
@@ -643,10 +644,7 @@ In Todo mode just the category's unfinished todo items are shown
 by default.  The done items are hidden, but typing
 `\\[todo-toggle-view-done-items]' displays them below the todo
 items.  With non-nil user option `todo-show-with-done' both todo
-and done items are always shown on visiting a category.
-
-Invoking this command in Todo Archive mode visits the
-corresponding todo file, displaying the corresponding category."
+and done items are always shown on visiting a category."
   (interactive "P\np")
   (when todo-default-todo-file
     (todo-check-file (todo-absolute-file-name todo-default-todo-file)))
@@ -904,17 +902,19 @@ Categories mode."
       (todo-show)
     (let* ((archive (eq where 'archive))
           (cat (unless archive where))
+           (goto-archive (and cat
+                              todo-skip-archived-categories
+                              (zerop (todo-get-count 'todo cat))
+                              (zerop (todo-get-count 'done cat))
+                              (not (zerop (todo-get-count 'archived cat)))))
           (file0 (when cat             ; We're in Todo Categories mode.
-                   ;; With non-nil `todo-skip-archived-categories'
-                   ;; jump to archive file of a category with only
-                   ;; archived items.
-                   (if (and todo-skip-archived-categories
-                            (zerop (todo-get-count 'todo cat))
-                            (zerop (todo-get-count 'done cat))
-                            (not (zerop (todo-get-count 'archived cat))))
+                   (if goto-archive
+                       ;; If the category has only archived items and
+                       ;; `todo-skip-archived-categories' is non-nil, jump to
+                       ;; the archive category.
                        (concat (file-name-sans-extension
                                 todo-current-todo-file) ".toda")
-                     ;; Otherwise, jump to current todo file.
+                     ;; Otherwise, jump to the category in the todo file.
                      todo-current-todo-file)))
           (len (length todo-categories))
           (cat+file (unless cat
@@ -925,18 +925,15 @@ Categories mode."
           (category (or cat (car cat+file))))
       (unless cat (setq file0 (cdr cat+file)))
       (with-current-buffer (find-file-noselect file0 'nowarn)
-       (setq todo-current-todo-file file0)
-       ;; If called from Todo Categories mode, clean up before jumping.
-       (if (string= (buffer-name) todo-categories-buffer)
-           (kill-buffer))
-       (set-window-buffer (selected-window)
-                          (set-buffer (find-buffer-visiting file0)))
-       (unless todo-global-current-todo-file
-         (setq todo-global-current-todo-file todo-current-todo-file))
-       (todo-category-number category)
-       (todo-category-select)
-       (goto-char (point-min))
-       (when add-item (todo-insert-item--basic))))))
+        (when goto-archive (todo-archive-mode))
+        (set-window-buffer (selected-window)
+                           (set-buffer (find-buffer-visiting file0)))
+        (unless todo-global-current-todo-file
+          (setq todo-global-current-todo-file todo-current-todo-file))
+        (todo-category-number category)
+        (todo-category-select)
+        (goto-char (point-min))
+        (when add-item (todo-insert-item--basic))))))
 
 (defun todo-next-item (&optional count)
   "Move point down to the beginning of the next item.
@@ -1414,7 +1411,12 @@ the archive of the file moved to, creating it if it does not exist."
        (setq todo-files (funcall todo-files-function))
        (todo-reevaluate-filelist-defcustoms))
       (dolist (buf buffers)
+        ;; Make sure archive file is in Todo Archive mode so that
+        ;; todo-categories has correct value.
        (with-current-buffer (find-file-noselect buf)
+          (when (equal (file-name-extension (buffer-file-name)) "toda")
+            (unless (derived-mode-p 'todo-archive-mode)
+              (todo-archive-mode)))
          (widen)
          (goto-char (point-max))
          (let* ((beg (re-search-backward
@@ -1466,10 +1468,18 @@ the archive of the file moved to, creating it if it does not exist."
                  (re-search-backward
                   (concat "^" (regexp-quote todo-category-beg)
                           "\\(" (regexp-quote cat) "\\)$") nil t)
-                 (replace-match new nil nil nil 1)))
-             (setq todo-categories
-                   (append todo-categories (list (cons (or new cat) counts))))
-             (todo-update-categories-sexp)
+                 (replace-match new nil nil nil 1))
+                (setq todo-categories
+                      (append todo-categories (list (cons (or new cat) counts))))
+                (goto-char (point-min))
+                (if (looking-at "((\"")
+                    ;; Delete existing sexp.
+                    (delete-region (line-beginning-position) (line-end-position))
+                  ;; Otherwise, file is new, so make space for categories sexp.
+                  (insert "\n")
+                  (goto-char (point-min)))
+                ;; Insert (new or updated) sexp.
+                (prin1 todo-categories (current-buffer)))
              ;; If archive was just created, save it to avoid "File
              ;; <xyz> no longer exists!" message on invoking
              ;; `todo-view-archived-items'.
@@ -1500,9 +1510,7 @@ the archive of the file moved to, creating it if it does not exist."
                (setq todo-category-number 1))
              (todo-category-select)))))
       (set-window-buffer (selected-window)
-                        (set-buffer (find-file-noselect nfile)))
-      (todo-category-number (or new cat))
-      (todo-category-select))))
+                        (set-buffer (find-file-noselect nfile))))))
 
 (defun todo-merge-category (&optional file)
   "Merge current category into another existing category.
@@ -2262,9 +2270,8 @@ made in the number or names of categories."
                 (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)
@@ -2330,12 +2337,11 @@ made in the number or names of categories."
                             (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"
@@ -2347,7 +2353,7 @@ made in the number or names of categories."
                      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 "*"))
@@ -4654,13 +4660,15 @@ name in `todo-directory'.  See also the documentation string of
                    (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 "")
@@ -5230,7 +5238,8 @@ Also preserve category display, if applicable."
   (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))
@@ -5930,7 +5939,7 @@ number of the last the day of the month."
     (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
@@ -6579,8 +6588,7 @@ Added to `window-configuration-change-hook' in Todo mode."
   "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