1 ;;; planner-deadline.el --- Deadlines for planner.el
3 ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
4 ;; Parts copyright (C) 2004, 2005, 2008 Dryice Dong Liu <dryice AT liu.com.cn>
5 ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center
7 ;; Author: Sandra Jean Chua (Sacha) <sacha AT free.net.ph>
8 ;; URL: http://www.wjsullivan.net/PlannerMode.html
10 ;; This file is part of Planner. It is not part of GNU Emacs.
12 ;; Planner is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; Planner is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with Planner; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; With the default setup, make your tasks of the form
31 ;; #A0 _ Some task {{Deadline: 2004.09.12}}
33 ;; Note: There must be at least one space after the colon.
35 ;; Run M-x planner-deadline-update to update the task descriptions.
41 ;;; USER VARIABLES -----------------------------------------------------------
43 (defgroup planner-deadline nil
44 "Deadline reports for planner.el."
45 :prefix
"planner-deadline"
48 (defcustom planner-deadline-change-hook
'(planner-deadline-update)
49 "Functions to run after `planner-deadline-change'.
50 Point will be on the same line as the task."
52 :options
'(planner-deadline-update)
53 :group
'planner-deadline
)
55 (defcustom planner-deadline-regexp
"\\({{Deadline:\\s-+\\([0-9]+[\\.\\-][0-9]+[\\.\\-][0-9]+\\)[^}]*}}\\)"
56 "Regular expression for deadline data.
57 The special deadline string should be regexp group 1. The
58 date (YYYY.MM.DD) should be regexp group 2."
60 :group
'planner-deadline
)
62 (defun planner-deadline-get-deadline-from-string (string)
63 "Return the deadline in STRING."
65 (if (string-match planner-deadline-regexp string
)
66 (planner-match-string-no-properties 2 string
)
69 (defun planner-deadline-get-current-deadline ()
70 "Return the deadline of the current task."
71 (planner-deadline-get-deadline-from-string
72 (buffer-substring (planner-line-beginning-position)
73 (planner-line-end-position))))
75 (defun planner-deadline-days-left (deadline date
)
76 "Return how many days are left for DEADLINE with effective DATE."
78 (date (if (listp date
) (planner-task-date date
) date
)))
81 (- (calendar-absolute-from-gregorian
82 (planner-filename-to-calendar-date
84 (calendar-absolute-from-gregorian
85 (planner-filename-to-calendar-date
88 (if (not planner-use-day-pages
)
89 (planner-date-to-filename (decode-time (current-time)))
90 (if (string-match planner-date-regexp
(planner-page-name))
94 (- (calendar-absolute-from-gregorian
95 (planner-filename-to-calendar-date
97 (calendar-absolute-from-gregorian
98 (planner-filename-to-calendar-date
102 (defun planner-deadline-calculate-string (deadline &optional date
)
103 "Return a deadline string for DEADLINE and effective DATE."
104 (let ((diff (planner-deadline-days-left deadline date
)))
105 (concat "{{Deadline: "
109 ((< diff
0) (format "%d %s *OVERDUE*"
111 (if (= diff -
1) "day"
113 ((= diff
0) "*TODAY*")
114 (t (format "%d %s" diff
121 (defun planner-deadline-update ()
122 "Replace the text for all tasks with deadlines.
123 By default, deadlines are of the form {{Deadline: yyyy.mm.dd}}.
124 See `planner-deadline-regexp' for details."
126 (with-planner-update-setup
127 (goto-char (point-min))
128 (while (re-search-forward planner-deadline-regexp nil t
)
129 (let* ((deadline (match-string 2))
130 (task-info (save-match-data (planner-current-task-info)))
131 (status (planner-task-status task-info
))
136 (unless (or (equal status
"X")
138 (setq new
(planner-deadline-calculate-string
139 deadline task-info
)))
140 (setq new
(planner-deadline-calculate-string deadline nil
))))
143 (when (string-match planner-deadline-regexp
144 (planner-task-description task-info
))
145 (planner-edit-task-description
146 (replace-match new t t
(planner-task-description task-info
))))
147 (replace-match new t t
)
148 (when (planner-current-note-info) (planner-update-note))))
149 (goto-char (1+ end
))))))
152 (defun planner-deadline-change (date)
153 "Change the deadline of current task to DATE.
154 If DATE is nil, prompt for it."
155 (interactive (list (planner-read-date nil t
)))
156 (let* ((info (planner-current-task-info))
157 (description (planner-task-description info
)))
159 (when (string-match (concat "\\s-*" planner-deadline-regexp
)
161 (setq description
(replace-match "" t t description
)))
162 (planner-edit-task-description (concat description
166 (run-hooks 'planner-deadline-change-hook
))))
169 (defalias 'planner-deadline-add
'planner-deadline-change
)
172 (defun planner-deadline-remove ()
173 "Remove the deadline of the current task."
175 (let* ((info (planner-current-task-info))
176 (description (planner-task-description info
)))
177 (when (string-match (concat "\\s-*" planner-deadline-regexp
)
179 (setq description
(replace-match "" t t description
))
180 (planner-edit-task-description description
))))
182 ;; Insinuate planner-deadline-update into planner-goto-hook
183 (add-to-list 'planner-goto-hook
'planner-deadline-update
)
185 (provide 'planner-deadline
)
187 ;;; planner-deadline.el ends here