Fix Bug #11932.
[planner-el.git] / planner-cyclic.el
blob6996f22344222d090d2f9fb2fefaf8f12c14cfe8
1 ;;; planner-cyclic.el --- Cyclic task support for the Emacs Planner
3 ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
4 ;; Parts copyright (C) 2005, 2008 Sergey Vlasov (vsu AT altlinux.ru)
6 ;; Filename: planner-cyclic.el
7 ;; Author: Sacha Chua <sacha@free.net.ph>
8 ;; Description: Provide cyclic task support
9 ;; URL: http://www.wjsullivan.net/PlannerMode.html
10 ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21
12 ;; This file is part of Planner. It is not part of GNU Emacs.
14 ;; Planner is free software; you can redistribute it and/or modify it
15 ;; under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; any later version.
19 ;; Planner is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 ;; General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with Planner; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 ;; Boston, MA 02110-1301, USA.
29 ;;; Commentary:
31 ;; Place planner-cyclic.el in your load path and add this to your .emacs:
33 ;; (require 'planner-cyclic)
35 ;; Create a diary file named ~/.diary.cyclic-tasks
36 ;; (or the value of planner-cyclic-diary-file). Example:
38 ;; Tuesday #B0 _ Study Japanese
39 ;; Friday #B0 _ Study Japanese (JapaneseStudies)
41 ;; The first will be a plain task, the second will be linked.
43 ;; By default, planner-cyclic creates multiple tasks if you let tasks build up
44 ;; (that is, the next Tuesday rolls around and you _still_ haven't
45 ;; marked the task as done.) To turn off this behavior:
47 ;; (setq planner-cyclic-diary-nag nil)
49 ;;; Code:
51 (require 'planner)
52 (require 'diary-lib)
54 (defcustom planner-cyclic-diary-file "~/.diary.cyclic-tasks"
55 "Diary file containing cyclic tasks."
56 :type 'string
57 :group 'planner)
59 (defcustom planner-cyclic-diary-nag t
60 "If non-nil, create tasks even if there are procrastinated cyclic tasks."
61 :type 'boolean
62 :group 'planner)
64 (defcustom planner-cyclic-task-description-format "%s from %s"
65 "Format used by `planner-cyclic-generate-task' when creating a task.
66 This string must be a valid control string for `format'. First format
67 argument is the task description read from `planner-cyclic-diary-file',
68 second argument is the date string.
70 If this format is changed when you already have some cyclic tasks
71 created with the old format, `planner-cyclic-create-tasks-maybe' will
72 add the same tasks with the new format, unless you convert existing
73 tasks to the new format manually."
74 :type 'string
75 :group 'planner)
77 ;;; functions
79 (defun planner-cyclic-get-cyclic-tasks (date &optional no-of-days)
80 "For DATE, get the cyclic tasks."
81 (let ((date (if (stringp date)
82 (planner-filename-to-calendar-date date)
83 date)))
84 (delq nil
85 (mapcar (lambda (item)
86 (when (string-match "#[A-C].+" (elt item 1))
87 (match-string 0 (elt item 1))))
88 (planner-list-diary-entries planner-cyclic-diary-file
89 date 1)))))
91 (defun planner-cyclic-generate-task (date task-string)
92 "For DATE, generate a cyclic task based on TASK-STRING."
93 (let ((info (planner-task-info-from-string date task-string)))
94 (if info
95 (setcar (nthcdr 4 info)
96 (format planner-cyclic-task-description-format
97 (planner-task-description info)
98 date))
99 (message "Cannot parse task %s" task-string))
100 info))
102 (defun planner-cyclic-create-task-maybe (date task-string)
103 "For DATE, possibly create a task based on TASK-STRING."
104 (when (string-match planner-task-regexp task-string)
105 (let ((orig-task (planner-task-info-from-string date task-string))
106 (new-task (planner-cyclic-generate-task date task-string)))
107 (unless (planner-find-task new-task)
108 (when (or planner-cyclic-diary-nag (not (planner-find-task orig-task)))
109 (planner-create-task-from-info new-task nil nil nil nil nil date))))))
111 ;;;###autoload
112 (defun planner-cyclic-create-tasks-maybe ()
113 "Maybe create cyclic tasks.
114 This will only create tasks for future dates or today."
115 (interactive)
116 (when (and (planner-derived-mode-p 'planner-mode)
117 (planner-page-name)
118 (not muse-publishing-p)
119 (string-match planner-date-regexp (planner-page-name))
120 (or (string< (planner-today) (planner-page-name))
121 (string= (planner-today) (planner-page-name))))
122 (mapcar
123 (lambda (task-string)
124 (when task-string
125 (planner-cyclic-create-task-maybe (planner-page-name)
126 task-string)))
127 (planner-cyclic-get-cyclic-tasks (planner-page-name)))))
129 (add-hook 'planner-mode-hook 'planner-cyclic-create-tasks-maybe)
131 (provide 'planner-cyclic)
133 ;;; planner-cyclic.el ends here