Update ChangeLog.
[planner-el.git] / planner-deadline.el
blob2798741ed340ab203b5ae277e1d95d79f329438b
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)
15 ;; any later version.
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.
27 ;;; Commentary:
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.
37 (require 'planner)
39 ;;; Code:
41 ;;; USER VARIABLES -----------------------------------------------------------
43 (defgroup planner-deadline nil
44 "Deadline reports for planner.el."
45 :prefix "planner-deadline"
46 :group 'planner)
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."
51 :type 'hook
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."
59 :type 'regexp
60 :group 'planner-deadline)
62 (defun planner-deadline-get-deadline-from-string (string)
63 "Return the deadline in STRING."
64 (save-match-data
65 (if (string-match planner-deadline-regexp string)
66 (planner-match-string-no-properties 2 string)
67 nil)))
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."
77 (let (diff
78 (date (if (listp date) (planner-task-date date) date)))
79 (if date
80 (setq diff
81 (- (calendar-absolute-from-gregorian
82 (planner-filename-to-calendar-date
83 deadline))
84 (calendar-absolute-from-gregorian
85 (planner-filename-to-calendar-date
86 date))))
87 (setq 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))
91 (planner-page-name)
92 (planner-today)))))
93 (setq diff
94 (- (calendar-absolute-from-gregorian
95 (planner-filename-to-calendar-date
96 deadline))
97 (calendar-absolute-from-gregorian
98 (planner-filename-to-calendar-date
99 date))))
100 diff))
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: "
106 deadline
107 " - "
108 (cond
109 ((< diff 0) (format "%d %s *OVERDUE*"
110 (- diff)
111 (if (= diff -1) "day"
112 "days")))
113 ((= diff 0) "*TODAY*")
114 (t (format "%d %s" diff
115 (if (= diff 1)
116 "day"
117 "days"))))
118 "}}")))
120 ;;;###autoload
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."
125 (interactive)
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))
132 (end (match-end 0))
133 new)
134 (save-match-data
135 (if task-info
136 (unless (or (equal status "X")
137 (equal status "C"))
138 (setq new (planner-deadline-calculate-string
139 deadline task-info)))
140 (setq new (planner-deadline-calculate-string deadline nil))))
141 (when new
142 (if task-info
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))))))
151 ;;;###autoload
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)))
158 (when date
159 (when (string-match (concat "\\s-*" planner-deadline-regexp)
160 description)
161 (setq description (replace-match "" t t description)))
162 (planner-edit-task-description (concat description
163 " {{Deadline: "
164 date
165 "}}"))
166 (run-hooks 'planner-deadline-change-hook))))
168 ;;;###autoload
169 (defalias 'planner-deadline-add 'planner-deadline-change)
171 ;;;###autoload
172 (defun planner-deadline-remove ()
173 "Remove the deadline of the current task."
174 (interactive)
175 (let* ((info (planner-current-task-info))
176 (description (planner-task-description info)))
177 (when (string-match (concat "\\s-*" planner-deadline-regexp)
178 description)
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