diff options
| author | Stephen Berman | 2013-07-05 16:03:35 +0200 |
|---|---|---|
| committer | Stephen Berman | 2013-07-05 16:03:35 +0200 |
| commit | d610f6dd0f7afd919c243e1c0786174010c19be8 (patch) | |
| tree | 49c6a022508410b20c1a7d75ab198f973bc9e0f4 | |
| parent | ddbdfd6f90c513e15ad5896dea156110f048322f (diff) | |
| download | emacs-d610f6dd0f7afd919c243e1c0786174010c19be8.tar.gz emacs-d610f6dd0f7afd919c243e1c0786174010c19be8.zip | |
* calendar/todo-mode.el: Add handling of file deletion, both by
mode command and externally. Fix various related bugs. Clarify
Commentary and improve some documentation strings and code.
(todo-delete-file): New command.
(todo-check-file): New function.
(todo-show): Handle external deletion of the file we're trying to
show. Replace called-interactively-p by an optional
prefix argument to avoid problematic interaction with catch form
when byte compiled (bug#14702).
(todo-quit): Handle external deletion of the archive's todo file.
Make sure the buffer that was visiting the archive file is still
live before trying to bury it.
(todo-category-completions): Handle external deletion of any
category completion files.
(todo-jump-to-category, todo-basic-insert-item): Recalculate list
of todo files, in case of external deletion.
(todo-add-file): Replace unnecessary setq by let-binding.
(todo-find-archive): Check whether there are any archives.
Replace unnecessary setq by let-binding.
(todo-archive-done-item): Use find-file-noselect to get the
archive buffer whether or not the archive already exists. Remove
superfluous code. Use file size instead of buffer-file-name to
check if the archive is new; if it is, update list of archives.
(todo-default-todo-file): Allow nil to be a valid value for when
there are no todo files.
(todo-reevaluate-default-file-defcustom): Use corrected definition
of todo-default-todo-file.
(todo-key-bindings-t+a+f): Add key binding for todo-delete-file.
(todo-delete-category, todo-show-categories-table)
(todo-category-number): Clarify comment.
(todo-filter-items): Clarify documentation string.
(todo-show-current-file, todo-display-as-todo-file)
(todo-reset-and-enable-done-separator): Tweak documentation string.
(todo-done-separator): Make separator length window-width, since
bug#2749 is now fixed.
Fixes: debbugs:14688
| -rw-r--r-- | lisp/ChangeLog | 38 | ||||
| -rw-r--r-- | lisp/calendar/todo-mode.el | 539 |
2 files changed, 379 insertions, 198 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 3dfa2f4a11b..46c728abbe7 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,41 @@ | |||
| 1 | 2013-07-05 Stephen Berman <stephen.berman@gmx.net> | ||
| 2 | |||
| 3 | * calendar/todo-mode.el: Add handling of file deletion, both by | ||
| 4 | mode command and externally. Fix various related bugs. Clarify | ||
| 5 | Commentary and improve some documentation strings and code. | ||
| 6 | (todo-delete-file): New command. | ||
| 7 | (todo-check-file): New function. | ||
| 8 | (todo-show): Handle external deletion of the file we're trying to | ||
| 9 | show (bug#14688). Replace called-interactively-p by an optional | ||
| 10 | prefix argument to avoid problematic interaction with catch form | ||
| 11 | when byte compiled (bug#14702). | ||
| 12 | (todo-quit): Handle external deletion of the archive's todo file. | ||
| 13 | Make sure the buffer that was visiting the archive file is still | ||
| 14 | live before trying to bury it. | ||
| 15 | (todo-category-completions): Handle external deletion of any | ||
| 16 | category completion files. | ||
| 17 | (todo-jump-to-category, todo-basic-insert-item): Recalculate list | ||
| 18 | of todo files, in case of external deletion. | ||
| 19 | (todo-add-file): Replace unnecessary setq by let-binding. | ||
| 20 | (todo-find-archive): Check whether there are any archives. | ||
| 21 | Replace unnecessary setq by let-binding. | ||
| 22 | (todo-archive-done-item): Use find-file-noselect to get the | ||
| 23 | archive buffer whether or not the archive already exists. Remove | ||
| 24 | superfluous code. Use file size instead of buffer-file-name to | ||
| 25 | check if the archive is new; if it is, update list of archives. | ||
| 26 | (todo-default-todo-file): Allow nil to be a valid value for when | ||
| 27 | there are no todo files. | ||
| 28 | (todo-reevaluate-default-file-defcustom): Use corrected definition | ||
| 29 | of todo-default-todo-file. | ||
| 30 | (todo-key-bindings-t+a+f): Add key binding for todo-delete-file. | ||
| 31 | (todo-delete-category, todo-show-categories-table) | ||
| 32 | (todo-category-number): Clarify comment. | ||
| 33 | (todo-filter-items): Clarify documentation string. | ||
| 34 | (todo-show-current-file, todo-display-as-todo-file) | ||
| 35 | (todo-reset-and-enable-done-separator): Tweak documentation string. | ||
| 36 | (todo-done-separator): Make separator length window-width, since | ||
| 37 | bug#2749 is now fixed. | ||
| 38 | |||
| 1 | 2013-07-05 Michael Albinus <michael.albinus@gmx.de> | 39 | 2013-07-05 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 40 | ||
| 3 | * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support | 41 | * net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Support |
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index a497f759e87..934dfb92a57 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el | |||
| @@ -37,11 +37,14 @@ | |||
| 37 | ;; can edit todo items, reprioritize them within their category, move | 37 | ;; can edit todo items, reprioritize them within their category, move |
| 38 | ;; them to another category, delete them, or mark items as done and | 38 | ;; them to another category, delete them, or mark items as done and |
| 39 | ;; store them separately from the not yet done items in a category. | 39 | ;; store them separately from the not yet done items in a category. |
| 40 | ;; You can add new todo files and categories, rename categories, move | 40 | ;; You can add new todo files, edit and delete them. You can add new |
| 41 | ;; them to another file or delete them. You can also display summary | 41 | ;; categories, rename and delete them, move categories to another file |
| 42 | ;; tables of the categories in a file and the types of items they | 42 | ;; and merge the items of two categories. You can also reorder the |
| 43 | ;; contain. And you can build cross-category lists of items that | 43 | ;; sequence of categories in a todo file for the purpose of |
| 44 | ;; satisfy various criteria. | 44 | ;; navigation. You can display summary tables of the categories in a |
| 45 | ;; file and the types of items they contain. And you can compile | ||
| 46 | ;; lists of existing items from multiple categories in one or more | ||
| 47 | ;; todo files, which are filtered by various criteria. | ||
| 45 | 48 | ||
| 46 | ;; To get started, load this package and type `M-x todo-show'. This | 49 | ;; To get started, load this package and type `M-x todo-show'. This |
| 47 | ;; will prompt you for the name of the first todo file, its first | 50 | ;; will prompt you for the name of the first todo file, its first |
| @@ -169,12 +172,7 @@ the value of `todo-done-separator'." | |||
| 169 | "Return string used as value of variable `todo-done-separator'." | 172 | "Return string used as value of variable `todo-done-separator'." |
| 170 | (let ((sep todo-done-separator-string)) | 173 | (let ((sep todo-done-separator-string)) |
| 171 | (propertize (if (= 1 (length sep)) | 174 | (propertize (if (= 1 (length sep)) |
| 172 | ;; Until bug#2749 is fixed, if separator's length | 175 | (make-string (window-width) (string-to-char sep)) |
| 173 | ;; is window-width and todo-wrap-lines is | ||
| 174 | ;; non-nil, an indented empty line appears between | ||
| 175 | ;; the separator and the first done item. | ||
| 176 | ;; (make-string (window-width) (string-to-char sep)) | ||
| 177 | (make-string (1- (window-width)) (string-to-char sep)) | ||
| 178 | todo-done-separator-string) | 176 | todo-done-separator-string) |
| 179 | 'face 'todo-done-sep))) | 177 | 'face 'todo-done-sep))) |
| 180 | 178 | ||
| @@ -578,11 +576,12 @@ This lacks the extension and directory components." | |||
| 578 | (file-name-sans-extension (file-name-nondirectory file)))) | 576 | (file-name-sans-extension (file-name-nondirectory file)))) |
| 579 | 577 | ||
| 580 | (defcustom todo-default-todo-file (todo-short-file-name | 578 | (defcustom todo-default-todo-file (todo-short-file-name |
| 581 | (car (funcall todo-files-function))) | 579 | (car (funcall todo-files-function))) |
| 582 | "Todo file visited by first session invocation of `todo-show'." | 580 | "Todo file visited by first session invocation of `todo-show'." |
| 583 | :type `(radio ,@(mapcar (lambda (f) (list 'const f)) | 581 | :type (when todo-files |
| 584 | (mapcar 'todo-short-file-name | 582 | `(radio ,@(mapcar (lambda (f) (list 'const f)) |
| 585 | (funcall todo-files-function)))) | 583 | (mapcar 'todo-short-file-name |
| 584 | (funcall todo-files-function))))) | ||
| 586 | :group 'todo) | 585 | :group 'todo) |
| 587 | 586 | ||
| 588 | (defcustom todo-show-current-file t | 587 | (defcustom todo-show-current-file t |
| @@ -630,7 +629,7 @@ Otherwise, `todo-show' always visits `todo-default-todo-file'." | |||
| 630 | :group 'todo) | 629 | :group 'todo) |
| 631 | 630 | ||
| 632 | ;;;###autoload | 631 | ;;;###autoload |
| 633 | (defun todo-show (&optional solicit-file) | 632 | (defun todo-show (&optional solicit-file interactive) |
| 634 | "Visit a todo file and display one of its categories. | 633 | "Visit a todo file and display one of its categories. |
| 635 | 634 | ||
| 636 | When invoked in Todo mode, prompt for which todo file to visit. | 635 | When invoked in Todo mode, prompt for which todo file to visit. |
| @@ -668,117 +667,124 @@ and done items are always shown on visiting a category. | |||
| 668 | 667 | ||
| 669 | Invoking this command in Todo Archive mode visits the | 668 | Invoking this command in Todo Archive mode visits the |
| 670 | corresponding todo file, displaying the corresponding category." | 669 | corresponding todo file, displaying the corresponding category." |
| 671 | (interactive "P") | 670 | (interactive "P\np") |
| 671 | (when todo-default-todo-file | ||
| 672 | (todo-check-file (todo-absolute-file-name todo-default-todo-file))) | ||
| 672 | (catch 'shown | 673 | (catch 'shown |
| 673 | ;; If there is a legacy todo file but no todo file in the current | 674 | ;; Before initializing the first todo first, check if there is a |
| 674 | ;; format, offer to convert the legacy file and show it. | 675 | ;; legacy todo file and if so, offer to convert to the current |
| 676 | ;; format and make it the first new todo file. | ||
| 675 | (unless todo-default-todo-file | 677 | (unless todo-default-todo-file |
| 676 | (let ((legacy-todo-file (if (boundp 'todo-file-do) | 678 | (let ((legacy-todo-file (if (boundp 'todo-file-do) |
| 677 | todo-file-do | 679 | todo-file-do |
| 678 | (locate-user-emacs-file "todo-do" ".todo-do")))) | 680 | (locate-user-emacs-file "todo-do" ".todo-do")))) |
| 679 | (when (and (file-exists-p legacy-todo-file) | 681 | (when (and (file-exists-p legacy-todo-file) |
| 680 | (y-or-n-p (concat "Do you want to convert a copy of your " | 682 | (y-or-n-p (concat "Do you want to convert a copy of your " |
| 681 | "old todo file to the new format? "))) | 683 | "old todo file to the new format? "))) |
| 682 | (when (todo-convert-legacy-files) | 684 | (when (todo-convert-legacy-files) |
| 683 | (throw 'shown nil))))) | 685 | (throw 'shown nil))))) |
| 684 | (let* ((cat) | 686 | (catch 'end |
| 685 | (show-first todo-show-first) | 687 | (let* ((cat) |
| 686 | (file (cond ((or solicit-file | 688 | (show-first todo-show-first) |
| 687 | (and (called-interactively-p 'any) | 689 | (file (cond ((or solicit-file |
| 688 | (memq major-mode '(todo-mode | 690 | (and interactive |
| 689 | todo-archive-mode | 691 | (memq major-mode '(todo-mode |
| 690 | todo-filtered-items-mode)))) | 692 | todo-archive-mode |
| 691 | (if (funcall todo-files-function) | 693 | todo-filtered-items-mode)))) |
| 692 | (todo-read-file-name "Choose a todo file to visit: " | 694 | (if (funcall todo-files-function) |
| 693 | nil t) | 695 | (todo-read-file-name "Choose a todo file to visit: " |
| 694 | (user-error "There are no todo files"))) | 696 | nil t) |
| 695 | ((and (eq major-mode 'todo-archive-mode) | 697 | (user-error "There are no todo files"))) |
| 696 | ;; Called noninteractively via todo-quit | 698 | ((and (eq major-mode 'todo-archive-mode) |
| 697 | ;; to jump to corresponding category in | 699 | ;; Called noninteractively via todo-quit |
| 698 | ;; todo file. | 700 | ;; to jump to corresponding category in |
| 699 | (not (called-interactively-p 'any))) | 701 | ;; todo file. |
| 700 | (setq cat (todo-current-category)) | 702 | (not interactive)) |
| 701 | (concat (file-name-sans-extension | 703 | (setq cat (todo-current-category)) |
| 702 | todo-current-todo-file) ".todo")) | 704 | (concat (file-name-sans-extension |
| 703 | (t | 705 | todo-current-todo-file) ".todo")) |
| 704 | (or todo-current-todo-file | 706 | (t |
| 705 | (and todo-show-current-file | 707 | (or todo-current-todo-file |
| 706 | todo-global-current-todo-file) | 708 | (and todo-show-current-file |
| 707 | (todo-absolute-file-name todo-default-todo-file) | 709 | todo-global-current-todo-file) |
| 708 | (todo-add-file))))) | 710 | (todo-absolute-file-name todo-default-todo-file) |
| 709 | add-item first-file) | 711 | (todo-add-file))))) |
| 710 | (unless todo-default-todo-file | 712 | add-item first-file) |
| 711 | ;; We just initialized the first todo file, so make it the default. | 713 | (unless todo-default-todo-file |
| 712 | (setq todo-default-todo-file (todo-short-file-name file) | 714 | ;; We just initialized the first todo file, so make it the default. |
| 713 | first-file t) | 715 | (setq todo-default-todo-file (todo-short-file-name file) |
| 714 | (todo-reevaluate-default-file-defcustom)) | 716 | first-file t) |
| 715 | (unless (member file todo-visited) | 717 | (todo-reevaluate-default-file-defcustom)) |
| 716 | ;; Can't setq t-c-t-f here, otherwise wrong file shown when | 718 | (unless (member file todo-visited) |
| 717 | ;; todo-show is called from todo-show-categories-table. | 719 | ;; Can't setq t-c-t-f here, otherwise wrong file shown when |
| 718 | (let ((todo-current-todo-file file)) | 720 | ;; todo-show is called from todo-show-categories-table. |
| 719 | (cond ((eq todo-show-first 'table) | 721 | (let ((todo-current-todo-file file)) |
| 720 | (todo-show-categories-table)) | 722 | (cond ((eq todo-show-first 'table) |
| 721 | ((memq todo-show-first '(top diary regexp)) | 723 | (todo-show-categories-table)) |
| 722 | (let* ((shortf (todo-short-file-name file)) | 724 | ((memq todo-show-first '(top diary regexp)) |
| 723 | (fi-file (todo-absolute-file-name | 725 | (let* ((shortf (todo-short-file-name file)) |
| 724 | shortf todo-show-first))) | 726 | (fi-file (todo-absolute-file-name |
| 725 | (when (eq todo-show-first 'regexp) | 727 | shortf todo-show-first))) |
| 726 | (let ((rxfiles (directory-files todo-directory t | 728 | (when (eq todo-show-first 'regexp) |
| 727 | ".*\\.todr$" t))) | 729 | (let ((rxfiles (directory-files todo-directory t |
| 728 | (when (and rxfiles (> (length rxfiles) 1)) | 730 | ".*\\.todr$" t))) |
| 729 | (let ((rxf (mapcar 'todo-short-file-name rxfiles))) | 731 | (when (and rxfiles (> (length rxfiles) 1)) |
| 730 | (setq fi-file (todo-absolute-file-name | 732 | (let ((rxf (mapcar 'todo-short-file-name rxfiles))) |
| 731 | (completing-read | 733 | (setq fi-file (todo-absolute-file-name |
| 732 | "Choose a regexp items file: " | 734 | (completing-read |
| 733 | rxf) 'regexp)))))) | 735 | "Choose a regexp items file: " |
| 734 | (if (file-exists-p fi-file) | 736 | rxf) 'regexp)))))) |
| 735 | (set-window-buffer | 737 | (if (file-exists-p fi-file) |
| 736 | (selected-window) | 738 | (set-window-buffer |
| 737 | (set-buffer (find-file-noselect fi-file 'nowarn))) | 739 | (selected-window) |
| 738 | (message "There is no %s file for %s" | 740 | (set-buffer (find-file-noselect fi-file 'nowarn))) |
| 739 | (cond ((eq todo-show-first 'top) | 741 | (message "There is no %s file for %s" |
| 740 | "top priorities") | 742 | (cond ((eq todo-show-first 'top) |
| 741 | ((eq todo-show-first 'diary) | 743 | "top priorities") |
| 742 | "diary items") | 744 | ((eq todo-show-first 'diary) |
| 743 | ((eq todo-show-first 'regexp) | 745 | "diary items") |
| 744 | "regexp items")) | 746 | ((eq todo-show-first 'regexp) |
| 745 | shortf) | 747 | "regexp items")) |
| 746 | (setq todo-show-first 'first))))))) | 748 | shortf) |
| 747 | (when (or (member file todo-visited) | 749 | (setq todo-show-first 'first))))))) |
| 748 | (eq todo-show-first 'first)) | 750 | (when (or (member file todo-visited) |
| 749 | (set-window-buffer (selected-window) | 751 | (eq todo-show-first 'first)) |
| 750 | (set-buffer (find-file-noselect file 'nowarn))) | 752 | (unless (todo-check-file file) (throw 'end nil)) |
| 751 | ;; When quitting an archive file, show the corresponding | 753 | (set-window-buffer (selected-window) |
| 752 | ;; category in the corresponding todo file, if it exists. | 754 | (set-buffer (find-file-noselect file 'nowarn))) |
| 753 | (when (assoc cat todo-categories) | 755 | ;; When quitting an archive file, show the corresponding |
| 754 | (setq todo-category-number (todo-category-number cat))) | 756 | ;; category in the corresponding todo file, if it exists. |
| 755 | ;; If this is a new todo file, add its first category. | 757 | (when (assoc cat todo-categories) |
| 756 | (when (zerop (buffer-size)) | 758 | (setq todo-category-number (todo-category-number cat))) |
| 757 | (let (cat-added) | 759 | ;; If this is a new todo file, add its first category. |
| 758 | (unwind-protect | 760 | (when (zerop (buffer-size)) |
| 759 | (setq todo-category-number | 761 | (let (cat-added) |
| 760 | (todo-add-category todo-current-todo-file "") | 762 | (unwind-protect |
| 761 | add-item todo-add-item-if-new-category | 763 | (setq todo-category-number |
| 762 | cat-added t) | 764 | (todo-add-category todo-current-todo-file "") |
| 763 | (if cat-added | 765 | add-item todo-add-item-if-new-category |
| 764 | ;; If the category was added, save the file now, so we | 766 | cat-added t) |
| 765 | ;; don't risk having an empty todo file, which would | 767 | (if cat-added |
| 766 | ;; signal an error if we tried to visit it later, | 768 | ;; If the category was added, save the file now, so we |
| 767 | ;; since doing that looks for category boundaries. | 769 | ;; don't risk having an empty todo file, which would |
| 768 | (save-buffer 0) | 770 | ;; signal an error if we tried to visit it later, |
| 769 | ;; If user cancels before adding the category, clean up | 771 | ;; since doing that looks for category boundaries. |
| 770 | ;; and exit, so we have a fresh slate the next time. | 772 | (save-buffer 0) |
| 771 | (delete-file file) | 773 | ;; If user cancels before adding the category, clean up |
| 772 | (setq todo-files (delete file todo-files)) | 774 | ;; and exit, so we have a fresh slate the next time. |
| 773 | (when first-file | 775 | (delete-file file) |
| 774 | (setq todo-default-todo-file nil | 776 | ;; (setq todo-files (funcall todo-files-function)) |
| 775 | todo-current-todo-file nil)) | 777 | (setq todo-files (delete file todo-files)) |
| 776 | (kill-buffer) | 778 | (when first-file |
| 777 | (keyboard-quit))))) | 779 | (setq todo-default-todo-file nil |
| 778 | (save-excursion (todo-category-select)) | 780 | todo-current-todo-file nil) |
| 779 | (when add-item (todo-basic-insert-item))) | 781 | (todo-reevaluate-default-file-defcustom)) |
| 780 | (setq todo-show-first show-first) | 782 | (kill-buffer) |
| 781 | (add-to-list 'todo-visited file)))) | 783 | (keyboard-quit))))) |
| 784 | (save-excursion (todo-category-select)) | ||
| 785 | (when add-item (todo-basic-insert-item))) | ||
| 786 | (setq todo-show-first show-first) | ||
| 787 | (add-to-list 'todo-visited file))))) | ||
| 782 | 788 | ||
| 783 | (defun todo-save () | 789 | (defun todo-save () |
| 784 | "Save the current todo file." | 790 | "Save the current todo file." |
| @@ -814,8 +820,15 @@ buries it and restores state as needed." | |||
| 814 | ;; Have to write a newly created archive to file to avoid | 820 | ;; Have to write a newly created archive to file to avoid |
| 815 | ;; subsequent errors. | 821 | ;; subsequent errors. |
| 816 | (todo-save) | 822 | (todo-save) |
| 817 | (todo-show) | 823 | (let ((todo-file (concat todo-directory |
| 818 | (bury-buffer buf)) | 824 | (todo-short-file-name todo-current-todo-file) |
| 825 | ".todo"))) | ||
| 826 | (if (todo-check-file todo-file) | ||
| 827 | (todo-show) | ||
| 828 | (message "There is no todo file for this archive"))) | ||
| 829 | ;; When todo-check-file runs in todo-show, it kills the | ||
| 830 | ;; buffer if the archive file was deleted externally. | ||
| 831 | (when (buffer-live-p buf) (bury-buffer buf))) | ||
| 819 | ((eq major-mode 'todo-mode) | 832 | ((eq major-mode 'todo-mode) |
| 820 | (todo-save) | 833 | (todo-save) |
| 821 | ;; If we just quit archive mode, just burying the buffer | 834 | ;; If we just quit archive mode, just burying the buffer |
| @@ -893,7 +906,7 @@ Categories mode." | |||
| 893 | (interactive "P") | 906 | (interactive "P") |
| 894 | ;; If invoked outside of Todo mode and there is not yet any Todo | 907 | ;; If invoked outside of Todo mode and there is not yet any Todo |
| 895 | ;; file, initialize one. | 908 | ;; file, initialize one. |
| 896 | (if (null todo-files) | 909 | (if (null (funcall todo-files-function)) |
| 897 | (todo-show) | 910 | (todo-show) |
| 898 | (let* ((archive (eq where 'archive)) | 911 | (let* ((archive (eq where 'archive)) |
| 899 | (cat (unless archive where)) | 912 | (cat (unless archive where)) |
| @@ -1069,10 +1082,9 @@ option `todo-add-item-if-new-category' is non-nil (the default), | |||
| 1069 | prompt for the first item. | 1082 | prompt for the first item. |
| 1070 | Noninteractively, return the name of the new file." | 1083 | Noninteractively, return the name of the new file." |
| 1071 | (interactive) | 1084 | (interactive) |
| 1072 | (let ((prompt (concat "Enter name of new todo file " | 1085 | (let* ((prompt (concat "Enter name of new todo file " |
| 1073 | "(TAB or SPC to see current names): ")) | 1086 | "(TAB or SPC to see current names): ")) |
| 1074 | file) | 1087 | (file (todo-read-file-name prompt))) |
| 1075 | (setq file (todo-read-file-name prompt)) | ||
| 1076 | (with-current-buffer (get-buffer-create file) | 1088 | (with-current-buffer (get-buffer-create file) |
| 1077 | (erase-buffer) | 1089 | (erase-buffer) |
| 1078 | (write-region (point-min) (point-max) file nil 'nomessage nil t) | 1090 | (write-region (point-min) (point-max) file nil 'nomessage nil t) |
| @@ -1087,6 +1099,55 @@ Noninteractively, return the name of the new file." | |||
| 1087 | (todo-show)) | 1099 | (todo-show)) |
| 1088 | file))) | 1100 | file))) |
| 1089 | 1101 | ||
| 1102 | (defun todo-delete-file () | ||
| 1103 | "Delete the current todo, archive or filtered items file. | ||
| 1104 | If the todo file has a corresponding archive file, or vice versa, | ||
| 1105 | prompt whether to delete that as well. Also kill the buffers | ||
| 1106 | visiting the deleted files." | ||
| 1107 | (interactive) | ||
| 1108 | (let* ((file1 (buffer-file-name)) | ||
| 1109 | (todo (eq major-mode 'todo-mode)) | ||
| 1110 | (archive (eq major-mode 'todo-archive-mode)) | ||
| 1111 | (filtered (eq major-mode 'todo-filtered-items-mode)) | ||
| 1112 | (file1-sn (todo-short-file-name file1)) | ||
| 1113 | (file2 (concat todo-directory file1-sn (cond (todo ".toda") | ||
| 1114 | (archive ".todo")))) | ||
| 1115 | (buf1 (current-buffer)) | ||
| 1116 | (buf2 (when file2 (find-buffer-visiting file2))) | ||
| 1117 | (prompt1 (concat "Delete " (cond (todo "todo") | ||
| 1118 | (archive "archive") | ||
| 1119 | (filtered "filtered items")) | ||
| 1120 | " file \"%s\"? ")) | ||
| 1121 | (prompt2 (concat "Also delete the corresponding " | ||
| 1122 | (cond (todo "archive") (archive "todo")) " file " | ||
| 1123 | (when buf2 "and kill the buffer visiting it? "))) | ||
| 1124 | (delete1 (yes-or-no-p (format prompt1 file1-sn))) | ||
| 1125 | (delete2 (when (and delete1 (or (file-exists-p file2) buf2)) | ||
| 1126 | (yes-or-no-p prompt2)))) | ||
| 1127 | (when delete1 | ||
| 1128 | (when (file-exists-p file1) (delete-file file1)) | ||
| 1129 | (setq todo-visited (delete file1 todo-visited)) | ||
| 1130 | (kill-buffer buf1) | ||
| 1131 | (when delete2 | ||
| 1132 | (when (file-exists-p file2) (delete-file file2)) | ||
| 1133 | (setq todo-visited (delete file2 todo-visited)) | ||
| 1134 | (and buf2 (kill-buffer buf2))) | ||
| 1135 | (setq todo-files (funcall todo-files-function) | ||
| 1136 | todo-archives (funcall todo-files-function t)) | ||
| 1137 | (when (or (string= file1-sn todo-default-todo-file) | ||
| 1138 | (and delete2 (string= file1-sn todo-default-todo-file))) | ||
| 1139 | (setq todo-default-todo-file (todo-short-file-name (car todo-files)))) | ||
| 1140 | (when (or (string= file1 todo-global-current-todo-file) | ||
| 1141 | (and delete2 (string= file2 todo-global-current-todo-file))) | ||
| 1142 | (setq todo-global-current-todo-file nil)) | ||
| 1143 | (todo-reevaluate-filelist-defcustoms) | ||
| 1144 | (message (concat (cond (todo "Todo") (archive "Archive")) " file \"%s\" " | ||
| 1145 | (when delete2 | ||
| 1146 | (concat "and its " | ||
| 1147 | (cond (todo "archive") (archive "todo")) | ||
| 1148 | " file ")) | ||
| 1149 | "deleted") file1-sn)))) | ||
| 1150 | |||
| 1090 | (defvar todo-edit-buffer "*Todo Edit*" | 1151 | (defvar todo-edit-buffer "*Todo Edit*" |
| 1091 | "Name of current buffer in Todo Edit mode.") | 1152 | "Name of current buffer in Todo Edit mode.") |
| 1092 | 1153 | ||
| @@ -1190,9 +1251,9 @@ category there as well." | |||
| 1190 | (save-excursion (todo-category-select))) | 1251 | (save-excursion (todo-category-select))) |
| 1191 | 1252 | ||
| 1192 | (defun todo-delete-category (&optional arg) | 1253 | (defun todo-delete-category (&optional arg) |
| 1193 | "Delete current todo category provided it is empty. | 1254 | "Delete current todo category provided it contains no items. |
| 1194 | With ARG non-nil delete the category unconditionally, | 1255 | With prefix ARG delete the category even if it does contain |
| 1195 | i.e. including all existing todo and done items." | 1256 | todo or done items." |
| 1196 | (interactive "P") | 1257 | (interactive "P") |
| 1197 | (let* ((file todo-current-todo-file) | 1258 | (let* ((file todo-current-todo-file) |
| 1198 | (cat (todo-current-category)) | 1259 | (cat (todo-current-category)) |
| @@ -1723,7 +1784,7 @@ the new item: | |||
| 1723 | the item accordingly." | 1784 | the item accordingly." |
| 1724 | ;; If invoked outside of Todo mode and there is not yet any Todo | 1785 | ;; If invoked outside of Todo mode and there is not yet any Todo |
| 1725 | ;; file, initialize one. | 1786 | ;; file, initialize one. |
| 1726 | (if (null todo-files) | 1787 | (if (null (funcall todo-files-function)) |
| 1727 | (todo-show) | 1788 | (todo-show) |
| 1728 | (let ((region (eq region-or-here 'region)) | 1789 | (let ((region (eq region-or-here 'region)) |
| 1729 | (here (eq region-or-here 'here))) | 1790 | (here (eq region-or-here 'here))) |
| @@ -2958,31 +3019,32 @@ first visit in a session displays the first category in the | |||
| 2958 | archive, subsequent visits return to the last category | 3019 | archive, subsequent visits return to the last category |
| 2959 | displayed." | 3020 | displayed." |
| 2960 | (interactive) | 3021 | (interactive) |
| 2961 | (let* ((cat (todo-current-category)) | 3022 | (if (null (funcall todo-files-function t)) |
| 2962 | (count (todo-get-count 'archived cat)) | 3023 | (message "There are no archive files") |
| 2963 | (archive (concat (file-name-sans-extension todo-current-todo-file) | 3024 | (let* ((cat (todo-current-category)) |
| 2964 | ".toda")) | 3025 | (count (todo-get-count 'archived cat)) |
| 2965 | place) | 3026 | (archive (concat (file-name-sans-extension todo-current-todo-file) |
| 2966 | (setq place (cond (ask 'other-archive) | 3027 | ".toda")) |
| 2967 | ((file-exists-p archive) 'this-archive) | 3028 | (place (cond (ask 'other-archive) |
| 2968 | (t (when (todo-y-or-n-p | 3029 | ((file-exists-p archive) 'this-archive) |
| 2969 | (concat "This file has no archive; " | 3030 | (t (when (todo-y-or-n-p |
| 2970 | "visit another archive? ")) | 3031 | (concat "This file has no archive; " |
| 2971 | 'other-archive)))) | 3032 | "visit another archive? ")) |
| 2972 | (when (eq place 'other-archive) | 3033 | 'other-archive))))) |
| 2973 | (setq archive (todo-read-file-name "Choose a todo archive: " t t))) | 3034 | (when (eq place 'other-archive) |
| 2974 | (when (and (eq place 'this-archive) (zerop count)) | 3035 | (setq archive (todo-read-file-name "Choose a todo archive: " t t))) |
| 2975 | (setq place (when (todo-y-or-n-p | 3036 | (when (and (eq place 'this-archive) (zerop count)) |
| 2976 | (concat "This category has no archived items;" | 3037 | (setq place (when (todo-y-or-n-p |
| 2977 | " visit archive anyway? ")) | 3038 | (concat "This category has no archived items;" |
| 2978 | 'other-cat))) | 3039 | " visit archive anyway? ")) |
| 2979 | (when place | 3040 | 'other-cat))) |
| 2980 | (set-window-buffer (selected-window) | 3041 | (when place |
| 2981 | (set-buffer (find-file-noselect archive))) | 3042 | (set-window-buffer (selected-window) |
| 2982 | (if (member place '(other-archive other-cat)) | 3043 | (set-buffer (find-file-noselect archive))) |
| 2983 | (setq todo-category-number 1) | 3044 | (if (member place '(other-archive other-cat)) |
| 2984 | (todo-category-number cat)) | 3045 | (setq todo-category-number 1) |
| 2985 | (todo-category-select)))) | 3046 | (todo-category-number cat)) |
| 3047 | (todo-category-select))))) | ||
| 2986 | 3048 | ||
| 2987 | (defun todo-choose-archive () | 3049 | (defun todo-choose-archive () |
| 2988 | "Choose an archive and visit it." | 3050 | "Choose an archive and visit it." |
| @@ -3010,9 +3072,7 @@ this category does not exist in the archive, it is created." | |||
| 3010 | (marked (assoc cat todo-categories-with-marks)) | 3072 | (marked (assoc cat todo-categories-with-marks)) |
| 3011 | (afile (concat (file-name-sans-extension | 3073 | (afile (concat (file-name-sans-extension |
| 3012 | todo-current-todo-file) ".toda")) | 3074 | todo-current-todo-file) ".toda")) |
| 3013 | (archive (if (file-exists-p afile) | 3075 | (archive (find-file-noselect afile t)) |
| 3014 | (find-file-noselect afile t) | ||
| 3015 | (get-buffer-create afile))) | ||
| 3016 | (item (and (todo-done-item-p) | 3076 | (item (and (todo-done-item-p) |
| 3017 | (concat (todo-item-string) "\n"))) | 3077 | (concat (todo-item-string) "\n"))) |
| 3018 | (count 0) | 3078 | (count 0) |
| @@ -3056,7 +3116,6 @@ this category does not exist in the archive, it is created." | |||
| 3056 | (if (not (or marked all item)) | 3116 | (if (not (or marked all item)) |
| 3057 | (throw 'end (message "Only done items can be archived")) | 3117 | (throw 'end (message "Only done items can be archived")) |
| 3058 | (with-current-buffer archive | 3118 | (with-current-buffer archive |
| 3059 | (unless buffer-file-name (erase-buffer)) | ||
| 3060 | (let (buffer-read-only) | 3119 | (let (buffer-read-only) |
| 3061 | (widen) | 3120 | (widen) |
| 3062 | (goto-char (point-min)) | 3121 | (goto-char (point-min)) |
| @@ -3076,11 +3135,13 @@ this category does not exist in the archive, it is created." | |||
| 3076 | (item))) | 3135 | (item))) |
| 3077 | (todo-update-count 'done (if (or marked all) count 1) cat) | 3136 | (todo-update-count 'done (if (or marked all) count 1) cat) |
| 3078 | (todo-update-categories-sexp) | 3137 | (todo-update-categories-sexp) |
| 3079 | ;; If archive is new, save to file now (using write-region in | 3138 | ;; If archive is new, save to file now (with |
| 3080 | ;; order not to get prompted for file to save to), to let | 3139 | ;; write-region to avoid prompt for file to save to) |
| 3081 | ;; auto-mode-alist take effect below. | 3140 | ;; to update todo-archives, and to let auto-mode-alist |
| 3082 | (unless buffer-file-name | 3141 | ;; take effect below on visiting the archive. |
| 3083 | (write-region nil nil afile) | 3142 | (unless (nth 7 (file-attributes afile)) |
| 3143 | (write-region nil nil afile t t) | ||
| 3144 | (setq todo-archives (funcall todo-files-function t)) | ||
| 3084 | (kill-buffer)))) | 3145 | (kill-buffer)))) |
| 3085 | (with-current-buffer tbuf | 3146 | (with-current-buffer tbuf |
| 3086 | (cond | 3147 | (cond |
| @@ -3286,19 +3347,24 @@ categories display according to priority." | |||
| 3286 | (defun todo-show-categories-table () | 3347 | (defun todo-show-categories-table () |
| 3287 | "Display a table of the current file's categories and item counts. | 3348 | "Display a table of the current file's categories and item counts. |
| 3288 | 3349 | ||
| 3289 | In the initial display the categories are numbered, indicating | 3350 | In the initial display the lines of the table are numbered, |
| 3290 | their current order for navigating by \\[todo-forward-category] | 3351 | indicating the current order of the categories when sequentially |
| 3291 | and \\[todo-backward-category]. You can permanently change the | 3352 | navigating through the todo file with `\\[todo-forward-category]' |
| 3292 | order of the category at point by typing | 3353 | and `\\[todo-backward-category]'. You can reorder the lines, and |
| 3293 | \\[todo-set-category-number], \\[todo-raise-category] or | 3354 | hence the category sequence, by typing `\\[todo-raise-category]' |
| 3294 | \\[todo-lower-category]. | 3355 | or `\\[todo-lower-category]' to raise or lower the category at |
| 3356 | point, or by typing `\\[todo-set-category-number]' and entering a | ||
| 3357 | number at the prompt or by typing `\\[todo-set-category-number]' | ||
| 3358 | with a numeric prefix. If you save the todo file after | ||
| 3359 | reordering the categories, the new order persists in subsequent | ||
| 3360 | Emacs sessions. | ||
| 3295 | 3361 | ||
| 3296 | The labels above the category names and item counts are buttons, | 3362 | The labels above the category names and item counts are buttons, |
| 3297 | and clicking these changes the display: sorted by category name | 3363 | and clicking these changes the display: sorted by category name |
| 3298 | or by the respective item counts (alternately descending or | 3364 | or by the respective item counts (alternately descending or |
| 3299 | ascending). In these displays the categories are not numbered | 3365 | ascending). In these displays the categories are not numbered |
| 3300 | and \\[todo-set-category-number], \\[todo-raise-category] and | 3366 | and `\\[todo-set-category-number]', `\\[todo-raise-category]' and |
| 3301 | \\[todo-lower-category] are disabled. (Programmatically, the | 3367 | `\\[todo-lower-category]' are disabled. (Programmatically, the |
| 3302 | sorting is triggered by passing a non-nil SORTKEY argument.) | 3368 | sorting is triggered by passing a non-nil SORTKEY argument.) |
| 3303 | 3369 | ||
| 3304 | In addition, the lines with the category names and item counts | 3370 | In addition, the lines with the category names and item counts |
| @@ -4019,15 +4085,15 @@ regexp items." | |||
| 4019 | "Buffer type string for `todo-filter-items'.") | 4085 | "Buffer type string for `todo-filter-items'.") |
| 4020 | 4086 | ||
| 4021 | (defun todo-filter-items (filter &optional new multifile) | 4087 | (defun todo-filter-items (filter &optional new multifile) |
| 4022 | "Display a cross-category list of items filtered by FILTER. | 4088 | "Display a list of items filtered by FILTER. |
| 4023 | The values of FILTER can be `top' for top priority items, a cons | 4089 | The values of FILTER can be `top' for top priority items, a cons |
| 4024 | of `top' and a number passed by the caller, `diary' for diary | 4090 | of `top' and a number passed by the caller, `diary' for diary |
| 4025 | items, or `regexp' for items matching a regular expression entered | 4091 | items, or `regexp' for items matching a regular expression |
| 4026 | by the user. The items can be from any categories in the current | 4092 | entered by the user. The items can come from any categories in |
| 4027 | todo file or, with non-nil MULTIFILE, from several files. If NEW | 4093 | the current todo file or, with non-nil MULTIFILE, from several |
| 4028 | is nil, visit an appropriate file containing the list of filtered | 4094 | files. If NEW is nil, visit an appropriate file containing the |
| 4029 | items; if there is no such file, or with non-nil NEW, build the | 4095 | list of filtered items; if there is no such file, or with non-nil |
| 4030 | list and display it. | 4096 | NEW, build the list and display it. |
| 4031 | 4097 | ||
| 4032 | See the documentation strings of the commands | 4098 | See the documentation strings of the commands |
| 4033 | `todo-filter-top-priorities', `todo-filter-diary-items', | 4099 | `todo-filter-top-priorities', `todo-filter-diary-items', |
| @@ -4699,14 +4765,57 @@ short todo archive or top priorities file name, respectively." | |||
| 4699 | ((eq type 'regexp) ".todr") | 4765 | ((eq type 'regexp) ".todr") |
| 4700 | (t ".todo")))))) | 4766 | (t ".todo")))))) |
| 4701 | 4767 | ||
| 4768 | (defun todo-check-file (file) | ||
| 4769 | "Check the state associated with FILE and update it if necessary. | ||
| 4770 | If FILE exists, return t. If it does not exist and there is no | ||
| 4771 | live buffer with its content, return nil; if there is such a | ||
| 4772 | buffer and the user tries to show it, ask whether to restore | ||
| 4773 | FILE, and if confirmed, do so and return t; else delete the | ||
| 4774 | buffer, clean up the state and return nil." | ||
| 4775 | (setq todo-files (funcall todo-files-function)) | ||
| 4776 | (setq todo-archives (funcall todo-files-function t)) | ||
| 4777 | (if (file-exists-p file) | ||
| 4778 | t | ||
| 4779 | (setq todo-visited (delete file todo-visited)) | ||
| 4780 | (let ((buf (find-buffer-visiting file))) | ||
| 4781 | (if (and buf | ||
| 4782 | (y-or-n-p | ||
| 4783 | (concat | ||
| 4784 | (format (concat "Todo file \"%s\" has been deleted but " | ||
| 4785 | "its content is still in a buffer!\n") | ||
| 4786 | (todo-short-file-name file)) | ||
| 4787 | "Save that buffer and restore the todo file? "))) | ||
| 4788 | (progn | ||
| 4789 | (with-current-buffer buf (save-buffer)) | ||
| 4790 | (setq todo-files (funcall todo-files-function)) | ||
| 4791 | (setq todo-archives (funcall todo-files-function t)) | ||
| 4792 | t) | ||
| 4793 | (let* ((files (append todo-files todo-archives)) | ||
| 4794 | (tctf todo-current-todo-file) | ||
| 4795 | (tgctf todo-global-current-todo-file) | ||
| 4796 | (tdtf (todo-absolute-file-name todo-default-todo-file))) | ||
| 4797 | (unless (or (not todo-current-todo-file) | ||
| 4798 | (member todo-current-todo-file files)) | ||
| 4799 | (setq todo-current-todo-file nil)) | ||
| 4800 | (unless (or (not todo-global-current-todo-file) | ||
| 4801 | (member todo-global-current-todo-file files)) | ||
| 4802 | (setq todo-global-current-todo-file nil)) | ||
| 4803 | (unless (or (not todo-default-todo-file) | ||
| 4804 | (member todo-default-todo-file files)) | ||
| 4805 | (setq todo-default-todo-file (todo-short-file-name | ||
| 4806 | (car todo-files)))) | ||
| 4807 | (todo-reevaluate-filelist-defcustoms) | ||
| 4808 | (when buf (kill-buffer buf)) | ||
| 4809 | nil))))) | ||
| 4810 | |||
| 4702 | (defun todo-category-number (cat) | 4811 | (defun todo-category-number (cat) |
| 4703 | "Return the number of category CAT in this todo file. | 4812 | "Return the number of category CAT in this todo file. |
| 4704 | The buffer-local variable `todo-category-number' holds this | 4813 | The buffer-local variable `todo-category-number' holds this |
| 4705 | number as its value." | 4814 | number as its value." |
| 4706 | (let ((categories (mapcar 'car todo-categories))) | 4815 | (let ((categories (mapcar 'car todo-categories))) |
| 4707 | (setq todo-category-number | 4816 | (setq todo-category-number |
| 4708 | ;; Increment by one, so that the highest priority category in Todo | 4817 | ;; Increment by one, so that the number of the first |
| 4709 | ;; Categories mode is numbered one rather than zero. | 4818 | ;; category is one rather than zero. |
| 4710 | (1+ (- (length categories) | 4819 | (1+ (- (length categories) |
| 4711 | (length (member cat categories))))))) | 4820 | (length (member cat categories))))))) |
| 4712 | 4821 | ||
| @@ -5384,7 +5493,27 @@ Each element of the list is a cons of a category name and the | |||
| 5384 | file or list of files (as short file names) it is in. The files | 5493 | file or list of files (as short file names) it is in. The files |
| 5385 | are either the current (or if there is none, the default) todo | 5494 | are either the current (or if there is none, the default) todo |
| 5386 | file plus the files listed in `todo-category-completions-files', | 5495 | file plus the files listed in `todo-category-completions-files', |
| 5387 | or, with non-nil ARCHIVE, the current archive file." | 5496 | or, with non-nil ARCHIVE, the current archive file. |
| 5497 | |||
| 5498 | Before calculating the completions, update the value of | ||
| 5499 | `todo-category-completions-files' in case any files named in it | ||
| 5500 | have been removed." | ||
| 5501 | (let (deleted) | ||
| 5502 | (dolist (f todo-category-completions-files) | ||
| 5503 | (unless (file-exists-p (todo-absolute-file-name f)) | ||
| 5504 | (setq todo-category-completions-files | ||
| 5505 | (delete f todo-category-completions-files)) | ||
| 5506 | (push f deleted))) | ||
| 5507 | (when deleted | ||
| 5508 | (let ((pl (> (length deleted) 1)) | ||
| 5509 | (names (mapconcat (lambda (f) (concat "\"" f "\"")) deleted ", "))) | ||
| 5510 | (message (concat "File" (if pl "s" "") " " names " ha" (if pl "ve" "s") | ||
| 5511 | " been deleted and removed from\n" | ||
| 5512 | "the list of category completion files"))) | ||
| 5513 | (todo-reevaluate-category-completions-files-defcustom) | ||
| 5514 | (custom-set-default 'todo-category-completions-files | ||
| 5515 | (symbol-value 'todo-category-completions-files)) | ||
| 5516 | (sleep-for 1.5))) | ||
| 5388 | (let* ((curfile (or todo-current-todo-file | 5517 | (let* ((curfile (or todo-current-todo-file |
| 5389 | (and todo-show-current-file | 5518 | (and todo-show-current-file |
| 5390 | todo-global-current-todo-file) | 5519 | todo-global-current-todo-file) |
| @@ -5435,6 +5564,7 @@ MUSTMATCH the name of an existing file must be chosen; | |||
| 5435 | otherwise, a new file name is allowed." | 5564 | otherwise, a new file name is allowed." |
| 5436 | (let* ((completion-ignore-case todo-completion-ignore-case) | 5565 | (let* ((completion-ignore-case todo-completion-ignore-case) |
| 5437 | (files (mapcar 'todo-short-file-name | 5566 | (files (mapcar 'todo-short-file-name |
| 5567 | ;; (funcall todo-files-function archive))) | ||
| 5438 | (if archive todo-archives todo-files))) | 5568 | (if archive todo-archives todo-files))) |
| 5439 | (file (completing-read prompt files nil mustmatch nil nil | 5569 | (file (completing-read prompt files nil mustmatch nil nil |
| 5440 | (if files | 5570 | (if files |
| @@ -5529,7 +5659,7 @@ categories from `todo-category-completions-files'." | |||
| 5529 | ;; Validate only against completion categories. | 5659 | ;; Validate only against completion categories. |
| 5530 | (let ((todo-categories categories)) | 5660 | (let ((todo-categories categories)) |
| 5531 | (setq cat (todo-validate-name cat 'category))) | 5661 | (setq cat (todo-validate-name cat 'category))) |
| 5532 | ;; When user enters a nonexistest category name by jumping or | 5662 | ;; When user enters a nonexistent category name by jumping or |
| 5533 | ;; moving, confirm that it should be added, then validate. | 5663 | ;; moving, confirm that it should be added, then validate. |
| 5534 | (unless add | 5664 | (unless add |
| 5535 | (if (todo-y-or-n-p (format "Add new category \"%s\" to file \"%s\"? " | 5665 | (if (todo-y-or-n-p (format "Add new category \"%s\" to file \"%s\"? " |
| @@ -5867,13 +5997,24 @@ the empty string (i.e., no time string)." | |||
| 5867 | 5997 | ||
| 5868 | (defun todo-reevaluate-default-file-defcustom () | 5998 | (defun todo-reevaluate-default-file-defcustom () |
| 5869 | "Reevaluate defcustom of `todo-default-todo-file'. | 5999 | "Reevaluate defcustom of `todo-default-todo-file'. |
| 5870 | Called after adding or deleting a todo file." | 6000 | Called after adding or deleting a todo file. If the value of |
| 5871 | (eval (defcustom todo-default-todo-file (car (funcall todo-files-function)) | 6001 | `todo-default-todo-file' before calling this function was |
| 5872 | "Todo file visited by first session invocation of `todo-show'." | 6002 | associated with an existing file, keep that value." |
| 5873 | :type `(radio ,@(mapcar (lambda (f) (list 'const f)) | 6003 | ;; (let ((curval todo-default-todo-file)) |
| 5874 | (mapcar 'todo-short-file-name | 6004 | (eval |
| 5875 | (funcall todo-files-function)))) | 6005 | (defcustom todo-default-todo-file (todo-short-file-name |
| 5876 | :group 'todo))) | 6006 | (car (funcall todo-files-function))) |
| 6007 | "Todo file visited by first session invocation of `todo-show'." | ||
| 6008 | :type (when todo-files | ||
| 6009 | `(radio ,@(mapcar (lambda (f) (list 'const f)) | ||
| 6010 | (mapcar 'todo-short-file-name | ||
| 6011 | (funcall todo-files-function))))) | ||
| 6012 | :group 'todo)) | ||
| 6013 | ;; (when (and curval (file-exists-p (todo-absolute-file-name curval))) | ||
| 6014 | ;; (custom-set-default 'todo-default-todo-file curval) | ||
| 6015 | ;; ;; (custom-reevaluate-setting 'todo-default-todo-file) | ||
| 6016 | ;; ))) | ||
| 6017 | ) | ||
| 5877 | 6018 | ||
| 5878 | (defun todo-reevaluate-category-completions-files-defcustom () | 6019 | (defun todo-reevaluate-category-completions-files-defcustom () |
| 5879 | "Reevaluate defcustom of `todo-category-completions-files'. | 6020 | "Reevaluate defcustom of `todo-category-completions-files'. |
| @@ -6060,6 +6201,7 @@ Filtered Items mode following todo (not done) items." | |||
| 6060 | ("Cu" todo-unmark-category) | 6201 | ("Cu" todo-unmark-category) |
| 6061 | ("Fh" todo-toggle-item-header) | 6202 | ("Fh" todo-toggle-item-header) |
| 6062 | ("h" todo-toggle-item-header) | 6203 | ("h" todo-toggle-item-header) |
| 6204 | ("Fk" todo-delete-file) | ||
| 6063 | ("Fe" todo-edit-file) | 6205 | ("Fe" todo-edit-file) |
| 6064 | ("FH" todo-toggle-item-highlighting) | 6206 | ("FH" todo-toggle-item-highlighting) |
| 6065 | ("H" todo-toggle-item-highlighting) | 6207 | ("H" todo-toggle-item-highlighting) |
| @@ -6226,12 +6368,13 @@ Filtered Items mode following todo (not done) items." | |||
| 6226 | 6368 | ||
| 6227 | (defun todo-show-current-file () | 6369 | (defun todo-show-current-file () |
| 6228 | "Visit current instead of default todo file with `todo-show'. | 6370 | "Visit current instead of default todo file with `todo-show'. |
| 6229 | This function is added to `pre-command-hook' when user option | 6371 | Added to `pre-command-hook' in Todo mode when user option |
| 6230 | `todo-show-current-file' is set to non-nil." | 6372 | `todo-show-current-file' is set to non-nil." |
| 6231 | (setq todo-global-current-todo-file todo-current-todo-file)) | 6373 | (setq todo-global-current-todo-file todo-current-todo-file)) |
| 6232 | 6374 | ||
| 6233 | (defun todo-display-as-todo-file () | 6375 | (defun todo-display-as-todo-file () |
| 6234 | "Show todo files correctly when visited from outside of Todo mode." | 6376 | "Show todo files correctly when visited from outside of Todo mode. |
| 6377 | Added to `find-file-hook' in Todo mode and Todo Archive mode." | ||
| 6235 | (and (member this-command todo-visit-files-commands) | 6378 | (and (member this-command todo-visit-files-commands) |
| 6236 | (= (- (point-max) (point-min)) (buffer-size)) | 6379 | (= (- (point-max) (point-min)) (buffer-size)) |
| 6237 | (member major-mode '(todo-mode todo-archive-mode)) | 6380 | (member major-mode '(todo-mode todo-archive-mode)) |
| @@ -6265,7 +6408,7 @@ This function is added to `kill-buffer-hook' in Todo mode." | |||
| 6265 | 6408 | ||
| 6266 | (defun todo-reset-and-enable-done-separator () | 6409 | (defun todo-reset-and-enable-done-separator () |
| 6267 | "Show resized done items separator overlay after window change. | 6410 | "Show resized done items separator overlay after window change. |
| 6268 | Added to `window-configuration-change-hook' in `todo-mode'." | 6411 | Added to `window-configuration-change-hook' in Todo mode." |
| 6269 | (when (= 1 (length todo-done-separator-string)) | 6412 | (when (= 1 (length todo-done-separator-string)) |
| 6270 | (let ((sep todo-done-separator)) | 6413 | (let ((sep todo-done-separator)) |
| 6271 | (setq todo-done-separator (todo-done-separator)) | 6414 | (setq todo-done-separator (todo-done-separator)) |