Merge branch 'maint'
[org-mode.git] / contrib / lisp / org-secretary.el
blobbabfb753908f57ecf92aa528063cbae22ee410dc
1 ;;; org-secretary.el --- Team management with org-mode
2 ;; Copyright (C) 2010-2014 Juan Reyero
3 ;;
4 ;; Author: Juan Reyero <juan _at_ juanreyero _dot_ com>
5 ;; Keywords: outlines, tasks, team, management
6 ;; Homepage: http://juanreyero.com/article/emacs/org-teams.html
7 ;; Version: 0.02
8 ;;
9 ;; This file is not part of GNU Emacs.
11 ;; This file is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
16 ;; THis file is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 ;;; Commentary:
27 ;; This module implements helper functions for team management. It
28 ;; makes it easy to keep track of the work of several people. It
29 ;; keeps context (with whom and where you are) and allows you to use
30 ;; it to metadata to your notes, and to query the tasks associated
31 ;; with the people you are with and the place.
33 ;; See http://juanreyero.com/article/emacs/org-teams.html for a full
34 ;; explanation and configuration instructions.
36 ;;; Configuration
37 ;;;;;;;;;;;;;;;;;
39 ;; In short; your todos use the TODO keyword, your team's use TASK.
40 ;; Your org-todo-keywords should look something like this:
42 ;; (setq org-todo-keywords
43 ;; '((sequence "TODO(t)" "|" "DONE(d)" "CANCELLED(c)")
44 ;; (sequence "TASK(f)" "|" "DONE(d)")
45 ;; (sequence "MAYBE(m)" "|" "CANCELLED(c)")))
47 ;; It helps to distinguish them by color, like this:
49 ;; (setq org-todo-keyword-faces
50 ;; '(("TODO" . (:foreground "DarkOrange1" :weight bold))
51 ;; ("MAYBE" . (:foreground "sea green"))
52 ;; ("DONE" . (:foreground "light sea green"))
53 ;; ("CANCELLED" . (:foreground "forest green"))
54 ;; ("TASK" . (:foreground "blue"))))
56 ;; If you want to keep track of stuck projects you should tag your
57 ;; projects with :prj:, and define:
59 ;; (setq org-tags-exclude-from-inheritance '("prj")
60 ;; org-stuck-projects '("+prj/-MAYBE-DONE"
61 ;; ("TODO" "TASK") ()))
63 ;; Define a tag that marks TASK entries as yours:
65 ;; (setq org-sec-me "juanre")
67 ;; Finally, you add the special views to your org-agenda-custom-commands:
69 ;; (setq org-agenda-custom-commands
70 ;; '(("h" "Work todos" tags-todo
71 ;; "-personal-doat={.+}-dowith={.+}/!-TASK"
72 ;; ((org-agenda-todo-ignore-scheduled t)))
73 ;; ("H" "All work todos" tags-todo "-personal/!-TASK-MAYBE"
74 ;; ((org-agenda-todo-ignore-scheduled nil)))
75 ;; ("A" "Work todos with doat or dowith" tags-todo
76 ;; "-personal+doat={.+}|dowith={.+}/!-TASK"
77 ;; ((org-agenda-todo-ignore-scheduled nil)))
78 ;; ("j" "TODO dowith and TASK with"
79 ;; ((org-sec-with-view "TODO dowith")
80 ;; (org-sec-where-view "TODO doat")
81 ;; (org-sec-assigned-with-view "TASK with")
82 ;; (org-sec-stuck-with-view "STUCK with")))
83 ;; ("J" "Interactive TODO dowith and TASK with"
84 ;; ((org-sec-who-view "TODO dowith")))))
86 ;;; Usage
87 ;;;;;;;;;
89 ;; Do C-c w to say with whom you are meeting (a space-separated list
90 ;; of names). Maybe do also C-c W to say where you are. Then do C-c a
91 ;; j to see:
92 ;; - Todo items defined with TODO (ie, mine) in which the
93 ;; =dowith= property matches any of the people with me.
94 ;; - Todo items defined with TODO in which the =doat= property
95 ;; matches my current location.
96 ;; - Todo items defined with TASK that are tagged with the name
97 ;; of any of the people with me (this is, assigned to them).
98 ;; - Stuck projects tagged with the name of the people with me.
100 ;; Use C-c j to add meta-data with the people with me, the
101 ;; location and the time to entries.
103 (require 'org)
105 (defvar org-sec-me nil
106 "Tag that defines TASK todo entries associated to me")
108 (defvar org-sec-with nil
109 "Value of the :with: property when doing an
110 org-sec-tag-entry. Change it with org-sec-set-with,
111 set to C-c w. Defaults to org-sec-me")
113 (defvar org-sec-where ""
114 "Value of the :at: property when doing an
115 org-sec-tag-entry. Change it with org-sec-set-with,
116 set to C-c W")
118 (defvar org-sec-with-history '()
119 "History list of :with: properties")
121 (defvar org-sec-where-history '()
122 "History list of :where: properties")
124 (defun org-sec-set-with ()
125 "Changes the value of the org-sec-with variable for use in the
126 next call of org-sec-tag-entry. Leave it empty to default to
127 org-sec-me (you)."
128 (interactive)
129 (setq org-sec-with (let ((w (read-string "With: " nil
130 'org-sec-with-history "")))
131 (if (string= w "")
133 w))))
134 (global-set-key "\C-cw" 'org-sec-set-with)
136 (defun org-sec-set-where ()
137 "Changes the value of the org-sec-where variable for use
138 in the next call of org-sec-tag-entry."
139 (interactive)
140 (setq org-sec-where
141 (read-string "Where: " nil
142 'org-sec-where-history "")))
143 (global-set-key "\C-cW" 'org-sec-set-where)
145 (defun org-sec-set-dowith ()
146 "Sets the value of the dowith property."
147 (interactive)
148 (let ((do-with
149 (read-string "Do with: "
150 nil 'org-sec-dowith-history "")))
151 (unless (string= do-with "")
152 (org-entry-put nil "dowith" do-with))))
153 (global-set-key "\C-cd" 'org-sec-set-dowith)
155 (defun org-sec-set-doat ()
156 "Sets the value of the doat property."
157 (interactive)
158 (let ((do-at (read-string "Do at: "
159 nil 'org-sec-doat-history "")))
160 (unless (string= do-at "")
161 (org-entry-put nil "doat" do-at))))
162 (global-set-key "\C-cD" 'org-sec-set-doat)
164 (defun org-sec-tag-entry ()
165 "Adds a :with: property with the value of org-sec-with if
166 defined, an :at: property with the value of org-sec-where
167 if defined, and an :on: property with the current time."
168 (interactive)
169 (save-excursion
170 (org-entry-put nil "on" (format-time-string
171 (org-time-stamp-format 'long)
172 (current-time)))
173 (unless (string= org-sec-where "")
174 (org-entry-put nil "at" org-sec-where))
175 (if org-sec-with
176 (org-entry-put nil "with" org-sec-with))))
177 (global-set-key "\C-cj" 'org-sec-tag-entry)
179 (defun join (lst sep &optional pre post)
180 (mapconcat (function (lambda (x) (concat pre x post))) lst sep))
182 (defun org-sec-get-with ()
183 (if org-sec-with
184 org-sec-with
185 org-sec-me))
187 (defun org-sec-with-view (par &optional who)
188 "Select tasks marked as dowith=who, where who
189 defaults to the value of org-sec-with."
190 (org-tags-view '(4) (join (split-string (if who
192 (org-sec-get-with)))
193 "|" "dowith=\"" "\"")))
195 (defun org-sec-where-view (par)
196 "Select tasks marked as doat=org-sec-where."
197 (org-tags-view '(4) (concat "doat={" org-sec-where "}")))
199 (defun org-sec-assigned-with-view (par &optional who)
200 "Select tasks assigned to who, by default org-sec-with."
201 (org-tags-view '(4)
202 (concat (join (split-string (if who
204 (org-sec-get-with)))
205 "|")
206 "/TASK")))
208 (defun org-sec-stuck-with-view (par &optional who)
209 "Select stuck projects assigned to who, by default
210 org-sec-with."
211 (let ((org-stuck-projects
212 `(,(concat "+prj+"
213 (join (split-string (if who
215 (org-sec-get-with))) "|")
216 "/-MAYBE-DONE")
217 ("TODO" "TASK") ())))
218 (org-agenda-list-stuck-projects)))
220 (defun org-sec-who-view (par)
221 "Builds agenda for a given user. Queried. "
222 (let ((who (read-string "Build todo for user/tag: "
223 "" "" "")))
224 (org-sec-with-view "TODO dowith" who)
225 (org-sec-assigned-with-view "TASK with" who)
226 (org-sec-stuck-with-view "STUCK with" who)))
228 (provide 'org-secretary)
230 ;;; org-secretary.el ends here