1 ;;; org-secretary.el --- Team management with org-mode
2 ;; Copyright (C) 2010 Juan Reyero
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
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)
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; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29 ;; This module implements helper functions for team management. It
30 ;; makes it easy to keep track of the work of several people. It
31 ;; keeps context (with whom and where you are) and allows you to use
32 ;; it to metadata to your notes, and to query the tasks associated
33 ;; with the people you are with and the place.
35 ;; See http://juanreyero.com/article/emacs/org-teams.html for a full
36 ;; explanation and configuration instructions.
41 ;; In short; your todos use the TODO keyword, your team's use TASK.
42 ;; Your org-todo-keywords should look something like this:
44 ;; (setq org-todo-keywords
45 ;; '((sequence "TODO(t)" "|" "DONE(d)" "CANCELLED(c)")
46 ;; (sequence "TASK(f)" "|" "DONE(d)")
47 ;; (sequence "MAYBE(m)" "|" "CANCELLED(c)")))
49 ;; It helps to distinguish them by color, like this:
51 ;; (setq org-todo-keyword-faces
52 ;; '(("TODO" . (:foreground "DarkOrange1" :weight bold))
53 ;; ("MAYBE" . (:foreground "sea green"))
54 ;; ("DONE" . (:foreground "light sea green"))
55 ;; ("CANCELLED" . (:foreground "forest green"))
56 ;; ("TASK" . (:foreground "blue"))))
58 ;; If you want to keep track of stuck projects you should tag your
59 ;; projects with :prj:, and define:
61 ;; (setq org-tags-exclude-from-inheritance '("prj")
62 ;; org-stuck-projects '("+prj/-MAYBE-DONE"
63 ;; ("TODO" "TASK") ()))
65 ;; Define a tag that marks TASK entries as yours:
67 ;; (setq org-sec-me "juanre")
69 ;; Finally, you add the special views to your org-agenda-custom-commands:
71 ;; (setq org-agenda-custom-commands
72 ;; '(("h" "Work todos" tags-todo
73 ;; "-personal-doat={.+}-dowith={.+}/!-TASK"
74 ;; ((org-agenda-todo-ignore-scheduled t)))
75 ;; ("H" "All work todos" tags-todo "-personal/!-TASK-MAYBE"
76 ;; ((org-agenda-todo-ignore-scheduled nil)))
77 ;; ("A" "Work todos with doat or dowith" tags-todo
78 ;; "-personal+doat={.+}|dowith={.+}/!-TASK"
79 ;; ((org-agenda-todo-ignore-scheduled nil)))
80 ;; ("j" "TODO dowith and TASK with"
81 ;; ((org-sec-with-view "TODO dowith")
82 ;; (org-sec-where-view "TODO doat")
83 ;; (org-sec-assigned-with-view "TASK with")
84 ;; (org-sec-stuck-with-view "STUCK with")))
85 ;; ("J" "Interactive TODO dowith and TASK with"
86 ;; ((org-sec-who-view "TODO dowith")))))
91 ;; Do C-c w to say with whom you are meeting (a space-separated list
92 ;; of names). Maybe do also C-c W to say where you are. Then do C-c a
94 ;; - Todo items defined with TODO (ie, mine) in which the
95 ;; =dowith= property matches any of the people with me.
96 ;; - Todo items defined with TODO in which the =doat= property
97 ;; matches my current location.
98 ;; - Todo items defined with TASK that are tagged with the name
99 ;; of any of the people with me (this is, assigned to them).
100 ;; - Stuck projects tagged with the name of the people with me.
102 ;; Use C-c j to add meta-data with the people with me, the
103 ;; location and the time to entries.
107 (defvar org-sec-me nil
108 "Tag that defines TASK todo entries associated to me")
110 (defvar org-sec-with nil
111 "Value of the :with: property when doing an
112 org-sec-tag-entry. Change it with org-sec-set-with,
113 set to C-c w. Defaults to org-sec-me")
115 (defvar org-sec-where
""
116 "Value of the :at: property when doing an
117 org-sec-tag-entry. Change it with org-sec-set-with,
120 (defvar org-sec-with-history
'()
121 "History list of :with: properties")
123 (defvar org-sec-where-history
'()
124 "History list of :where: properties")
126 (defun org-sec-set-with ()
127 "Changes the value of the org-sec-with variable for use in the
128 next call of org-sec-tag-entry. Leave it empty to default to
131 (setq org-sec-with
(let ((w (read-string "With: " nil
132 'org-sec-with-history
"")))
136 (global-set-key "\C-cw" 'org-sec-set-with
)
138 (defun org-sec-set-where ()
139 "Changes the value of the org-sec-where variable for use
140 in the next call of org-sec-tag-entry."
143 (read-string "Where: " nil
144 'org-sec-where-history
"")))
145 (global-set-key "\C-cW" 'org-sec-set-where
)
147 (defun org-sec-set-dowith ()
148 "Sets the value of the dowith property."
151 (read-string "Do with: "
152 nil
'org-sec-dowith-history
"")))
153 (unless (string= do-with
"")
154 (org-entry-put nil
"dowith" do-with
))))
155 (global-set-key "\C-cd" 'org-sec-set-dowith
)
157 (defun org-sec-set-doat ()
158 "Sets the value of the doat property."
160 (let ((do-at (read-string "Do at: "
161 nil
'org-sec-doat-history
"")))
162 (unless (string= do-at
"")
163 (org-entry-put nil
"doat" do-at
))))
164 (global-set-key "\C-cD" 'org-sec-set-doat
)
166 (defun org-sec-tag-entry ()
167 "Adds a :with: property with the value of org-sec-with if
168 defined, an :at: property with the value of org-sec-where
169 if defined, and an :on: property with the current time."
172 (org-entry-put nil
"on" (format-time-string
173 (org-time-stamp-format 'long
)
175 (unless (string= org-sec-where
"")
176 (org-entry-put nil
"at" org-sec-where
))
178 (org-entry-put nil
"with" org-sec-with
))))
179 (global-set-key "\C-cj" 'org-sec-tag-entry
)
181 (defun join (lst sep
&optional pre post
)
182 (mapconcat (function (lambda (x) (concat pre x post
))) lst sep
))
184 (defun org-sec-get-with ()
189 (defun org-sec-with-view (par &optional who
)
190 "Select tasks marked as dowith=who, where who
191 defaults to the value of org-sec-with."
192 (org-tags-view '(4) (join (split-string (if who
195 "|" "dowith=\"" "\"")))
197 (defun org-sec-where-view (par)
198 "Select tasks marked as doat=org-sec-where."
199 (org-tags-view '(4) (concat "doat={" org-sec-where
"}")))
201 (defun org-sec-assigned-with-view (par &optional who
)
202 "Select tasks assigned to who, by default org-sec-with."
204 (concat (join (split-string (if who
210 (defun org-sec-stuck-with-view (par &optional who
)
211 "Select stuck projects assigned to who, by default
213 (let ((org-stuck-projects
215 (join (split-string (if who
217 (org-sec-get-with))) "|")
219 ("TODO" "TASK") ())))
220 (org-agenda-list-stuck-projects)))
222 (defun org-sec-who-view (par)
223 "Builds agenda for a given user. Queried. "
224 (let ((who (read-string "Build todo for user/tag: "
226 (org-sec-with-view "TODO dowith" who
)
227 (org-sec-assigned-with-view "TASK with" who
)
228 (org-sec-stuck-with-view "STUCK with" who
)))
230 (provide 'org-secretary
)
232 ;;; org-secretary.el ends here