org-secretary.el 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. ;;; org-secretary.el --- Team management with org-mode
  2. ;; Copyright (C) 2010-2012 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.
  10. ;;
  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.
  15. ;; THis file is distributed in the hope that it will be useful,
  16. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ;; GNU General Public License for more details.
  19. ;; You should have received a copy of the GNU General Public License
  20. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  21. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. ;; Boston, MA 02110-1301, USA.
  23. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  24. ;;
  25. ;;; Commentary:
  26. ;;
  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.
  32. ;;
  33. ;; See http://juanreyero.com/article/emacs/org-teams.html for a full
  34. ;; explanation and configuration instructions.
  35. ;;
  36. ;;; Configuration
  37. ;;;;;;;;;;;;;;;;;
  38. ;;
  39. ;; In short; your todos use the TODO keyword, your team's use TASK.
  40. ;; Your org-todo-keywords should look something like this:
  41. ;;
  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)")))
  46. ;;
  47. ;; It helps to distinguish them by color, like this:
  48. ;;
  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"))))
  55. ;;
  56. ;; If you want to keep track of stuck projects you should tag your
  57. ;; projects with :prj:, and define:
  58. ;;
  59. ;; (setq org-tags-exclude-from-inheritance '("prj")
  60. ;; org-stuck-projects '("+prj/-MAYBE-DONE"
  61. ;; ("TODO" "TASK") ()))
  62. ;;
  63. ;; Define a tag that marks TASK entries as yours:
  64. ;;
  65. ;; (setq org-sec-me "juanre")
  66. ;;
  67. ;; Finally, you add the special views to your org-agenda-custom-commands:
  68. ;;
  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")))))
  85. ;;
  86. ;;; Usage
  87. ;;;;;;;;;
  88. ;;
  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.
  99. ;;
  100. ;; Use C-c j to add meta-data with the people with me, the
  101. ;; location and the time to entries.
  102. (require 'org)
  103. (defvar org-sec-me nil
  104. "Tag that defines TASK todo entries associated to me")
  105. (defvar org-sec-with nil
  106. "Value of the :with: property when doing an
  107. org-sec-tag-entry. Change it with org-sec-set-with,
  108. set to C-c w. Defaults to org-sec-me")
  109. (defvar org-sec-where ""
  110. "Value of the :at: property when doing an
  111. org-sec-tag-entry. Change it with org-sec-set-with,
  112. set to C-c W")
  113. (defvar org-sec-with-history '()
  114. "History list of :with: properties")
  115. (defvar org-sec-where-history '()
  116. "History list of :where: properties")
  117. (defun org-sec-set-with ()
  118. "Changes the value of the org-sec-with variable for use in the
  119. next call of org-sec-tag-entry. Leave it empty to default to
  120. org-sec-me (you)."
  121. (interactive)
  122. (setq org-sec-with (let ((w (read-string "With: " nil
  123. 'org-sec-with-history "")))
  124. (if (string= w "")
  125. nil
  126. w))))
  127. (global-set-key "\C-cw" 'org-sec-set-with)
  128. (defun org-sec-set-where ()
  129. "Changes the value of the org-sec-where variable for use
  130. in the next call of org-sec-tag-entry."
  131. (interactive)
  132. (setq org-sec-where
  133. (read-string "Where: " nil
  134. 'org-sec-where-history "")))
  135. (global-set-key "\C-cW" 'org-sec-set-where)
  136. (defun org-sec-set-dowith ()
  137. "Sets the value of the dowith property."
  138. (interactive)
  139. (let ((do-with
  140. (read-string "Do with: "
  141. nil 'org-sec-dowith-history "")))
  142. (unless (string= do-with "")
  143. (org-entry-put nil "dowith" do-with))))
  144. (global-set-key "\C-cd" 'org-sec-set-dowith)
  145. (defun org-sec-set-doat ()
  146. "Sets the value of the doat property."
  147. (interactive)
  148. (let ((do-at (read-string "Do at: "
  149. nil 'org-sec-doat-history "")))
  150. (unless (string= do-at "")
  151. (org-entry-put nil "doat" do-at))))
  152. (global-set-key "\C-cD" 'org-sec-set-doat)
  153. (defun org-sec-tag-entry ()
  154. "Adds a :with: property with the value of org-sec-with if
  155. defined, an :at: property with the value of org-sec-where
  156. if defined, and an :on: property with the current time."
  157. (interactive)
  158. (save-excursion
  159. (org-entry-put nil "on" (format-time-string
  160. (org-time-stamp-format 'long)
  161. (current-time)))
  162. (unless (string= org-sec-where "")
  163. (org-entry-put nil "at" org-sec-where))
  164. (if org-sec-with
  165. (org-entry-put nil "with" org-sec-with))))
  166. (global-set-key "\C-cj" 'org-sec-tag-entry)
  167. (defun join (lst sep &optional pre post)
  168. (mapconcat (function (lambda (x) (concat pre x post))) lst sep))
  169. (defun org-sec-get-with ()
  170. (if org-sec-with
  171. org-sec-with
  172. org-sec-me))
  173. (defun org-sec-with-view (par &optional who)
  174. "Select tasks marked as dowith=who, where who
  175. defaults to the value of org-sec-with."
  176. (org-tags-view '(4) (join (split-string (if who
  177. who
  178. (org-sec-get-with)))
  179. "|" "dowith=\"" "\"")))
  180. (defun org-sec-where-view (par)
  181. "Select tasks marked as doat=org-sec-where."
  182. (org-tags-view '(4) (concat "doat={" org-sec-where "}")))
  183. (defun org-sec-assigned-with-view (par &optional who)
  184. "Select tasks assigned to who, by default org-sec-with."
  185. (org-tags-view '(4)
  186. (concat (join (split-string (if who
  187. who
  188. (org-sec-get-with)))
  189. "|")
  190. "/TASK")))
  191. (defun org-sec-stuck-with-view (par &optional who)
  192. "Select stuck projects assigned to who, by default
  193. org-sec-with."
  194. (let ((org-stuck-projects
  195. `(,(concat "+prj+"
  196. (join (split-string (if who
  197. who
  198. (org-sec-get-with))) "|")
  199. "/-MAYBE-DONE")
  200. ("TODO" "TASK") ())))
  201. (org-agenda-list-stuck-projects)))
  202. (defun org-sec-who-view (par)
  203. "Builds agenda for a given user. Queried. "
  204. (let ((who (read-string "Build todo for user/tag: "
  205. "" "" "")))
  206. (org-sec-with-view "TODO dowith" who)
  207. (org-sec-assigned-with-view "TASK with" who)
  208. (org-sec-stuck-with-view "STUCK with" who)))
  209. (provide 'org-secretary)
  210. ;;; org-secretary.el ends here