org-secretary.el (8505B)
1 ;;; org-secretary.el --- Team management with org-mode 2 ;; Copyright (C) 2010-2014, 2021 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 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. 20 21 ;; You should have received a copy of the GNU General Public License 22 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 23 ;; 24 ;;; Commentary: 25 ;; 26 ;; This module implements helper functions for team management. It 27 ;; makes it easy to keep track of the work of several people. It 28 ;; keeps context (with whom and where you are) and allows you to use 29 ;; it to metadata to your notes, and to query the tasks associated 30 ;; with the people you are with and the place. 31 ;; 32 ;; See http://juanreyero.com/article/emacs/org-teams.html for a full 33 ;; explanation and configuration instructions. 34 ;; 35 ;;; Configuration 36 ;;;;;;;;;;;;;;;;; 37 ;; 38 ;; In short; your todos use the TODO keyword, your team's use TASK. 39 ;; Your org-todo-keywords should look something like this: 40 ;; 41 ;; (setq org-todo-keywords 42 ;; '((sequence "TODO(t)" "|" "DONE(d)" "CANCELLED(c)") 43 ;; (sequence "TASK(f)" "|" "DONE(d)") 44 ;; (sequence "MAYBE(m)" "|" "CANCELLED(c)"))) 45 ;; 46 ;; It helps to distinguish them by color, like this: 47 ;; 48 ;; (setq org-todo-keyword-faces 49 ;; '(("TODO" . (:foreground "DarkOrange1" :weight bold)) 50 ;; ("MAYBE" . (:foreground "sea green")) 51 ;; ("DONE" . (:foreground "light sea green")) 52 ;; ("CANCELLED" . (:foreground "forest green")) 53 ;; ("TASK" . (:foreground "blue")))) 54 ;; 55 ;; If you want to keep track of stuck projects you should tag your 56 ;; projects with :prj:, and define: 57 ;; 58 ;; (setq org-tags-exclude-from-inheritance '("prj") 59 ;; org-stuck-projects '("+prj/-MAYBE-DONE" 60 ;; ("TODO" "TASK") ())) 61 ;; 62 ;; Define a tag that marks TASK entries as yours: 63 ;; 64 ;; (setq org-sec-me "juanre") 65 ;; 66 ;; Finally, you add the special views to your org-agenda-custom-commands: 67 ;; 68 ;; (setq org-agenda-custom-commands 69 ;; '(("h" "Work todos" tags-todo 70 ;; "-personal-doat={.+}-dowith={.+}/!-TASK" 71 ;; ((org-agenda-todo-ignore-scheduled t))) 72 ;; ("H" "All work todos" tags-todo "-personal/!-TASK-MAYBE" 73 ;; ((org-agenda-todo-ignore-scheduled nil))) 74 ;; ("A" "Work todos with doat or dowith" tags-todo 75 ;; "-personal+doat={.+}|dowith={.+}/!-TASK" 76 ;; ((org-agenda-todo-ignore-scheduled nil))) 77 ;; ("j" "TODO dowith and TASK with" 78 ;; ((org-sec-with-view "TODO dowith") 79 ;; (org-sec-where-view "TODO doat") 80 ;; (org-sec-assigned-with-view "TASK with") 81 ;; (org-sec-stuck-with-view "STUCK with"))) 82 ;; ("J" "Interactive TODO dowith and TASK with" 83 ;; ((org-sec-who-view "TODO dowith"))))) 84 ;; 85 ;;; Usage 86 ;;;;;;;;; 87 ;; 88 ;; Do C-c w to say with whom you are meeting (a space-separated list 89 ;; of names). Maybe do also C-c W to say where you are. Then do C-c a 90 ;; j to see: 91 ;; - Todo items defined with TODO (ie, mine) in which the 92 ;; =dowith= property matches any of the people with me. 93 ;; - Todo items defined with TODO in which the =doat= property 94 ;; matches my current location. 95 ;; - Todo items defined with TASK that are tagged with the name 96 ;; of any of the people with me (this is, assigned to them). 97 ;; - Stuck projects tagged with the name of the people with me. 98 ;; 99 ;; Use C-c j to add meta-data with the people with me, the 100 ;; location and the time to entries. 101 102 (require 'org) 103 104 (defvar org-sec-me nil 105 "Tag that defines TASK todo entries associated to me") 106 107 (defvar org-sec-with nil 108 "Value of the :with: property when doing an 109 org-sec-tag-entry. Change it with org-sec-set-with, 110 set to C-c w. Defaults to org-sec-me") 111 112 (defvar org-sec-where "" 113 "Value of the :at: property when doing an 114 org-sec-tag-entry. Change it with org-sec-set-with, 115 set to C-c W") 116 117 (defvar org-sec-with-history '() 118 "History list of :with: properties") 119 120 (defvar org-sec-where-history '() 121 "History list of :where: properties") 122 123 (defun org-sec-set-with () 124 "Changes the value of the org-sec-with variable for use in the 125 next call of org-sec-tag-entry. Leave it empty to default to 126 org-sec-me (you)." 127 (interactive) 128 (setq org-sec-with (let ((w (read-string "With: " nil 129 'org-sec-with-history ""))) 130 (if (string= w "") 131 nil 132 w)))) 133 (global-set-key "\C-cw" 'org-sec-set-with) 134 135 (defun org-sec-set-where () 136 "Changes the value of the org-sec-where variable for use 137 in the next call of org-sec-tag-entry." 138 (interactive) 139 (setq org-sec-where 140 (read-string "Where: " nil 141 'org-sec-where-history ""))) 142 (global-set-key "\C-cW" 'org-sec-set-where) 143 144 (defun org-sec-set-dowith () 145 "Sets the value of the dowith property." 146 (interactive) 147 (let ((do-with 148 (read-string "Do with: " 149 nil 'org-sec-dowith-history ""))) 150 (unless (string= do-with "") 151 (org-entry-put nil "dowith" do-with)))) 152 (global-set-key "\C-cd" 'org-sec-set-dowith) 153 154 (defun org-sec-set-doat () 155 "Sets the value of the doat property." 156 (interactive) 157 (let ((do-at (read-string "Do at: " 158 nil 'org-sec-doat-history ""))) 159 (unless (string= do-at "") 160 (org-entry-put nil "doat" do-at)))) 161 (global-set-key "\C-cD" 'org-sec-set-doat) 162 163 (defun org-sec-tag-entry () 164 "Adds a :with: property with the value of org-sec-with if 165 defined, an :at: property with the value of org-sec-where 166 if defined, and an :on: property with the current time." 167 (interactive) 168 (save-excursion 169 (org-entry-put nil "on" (format-time-string 170 (org-time-stamp-format 'long) 171 (current-time))) 172 (unless (string= org-sec-where "") 173 (org-entry-put nil "at" org-sec-where)) 174 (if org-sec-with 175 (org-entry-put nil "with" org-sec-with)))) 176 (global-set-key "\C-cj" 'org-sec-tag-entry) 177 178 (defun join (lst sep &optional pre post) 179 (mapconcat (lambda (x) (concat pre x post)) lst sep)) 180 181 (defun org-sec-get-with () 182 (if org-sec-with 183 org-sec-with 184 org-sec-me)) 185 186 (defun org-sec-with-view (par &optional who) 187 "Select tasks marked as dowith=who, where who 188 defaults to the value of org-sec-with." 189 (org-tags-view '(4) (join (split-string (if who 190 who 191 (org-sec-get-with))) 192 "|" "dowith=\"" "\""))) 193 194 (defun org-sec-where-view (par) 195 "Select tasks marked as doat=org-sec-where." 196 (org-tags-view '(4) (concat "doat={" org-sec-where "}"))) 197 198 (defun org-sec-assigned-with-view (par &optional who) 199 "Select tasks assigned to who, by default org-sec-with." 200 (org-tags-view '(4) 201 (concat (join (split-string (if who 202 who 203 (org-sec-get-with))) 204 "|") 205 "/TASK"))) 206 207 (defun org-sec-stuck-with-view (par &optional who) 208 "Select stuck projects assigned to who, by default 209 org-sec-with." 210 (let ((org-stuck-projects 211 `(,(concat "+prj+" 212 (join (split-string (if who 213 who 214 (org-sec-get-with))) "|") 215 "/-MAYBE-DONE") 216 ("TODO" "TASK") ()))) 217 (org-agenda-list-stuck-projects))) 218 219 (defun org-sec-who-view (par) 220 "Builds agenda for a given user. Queried. " 221 (let ((who (read-string "Build todo for user/tag: " 222 "" "" ""))) 223 (org-sec-with-view "TODO dowith" who) 224 (org-sec-assigned-with-view "TASK with" who) 225 (org-sec-stuck-with-view "STUCK with" who))) 226 227 (provide 'org-secretary) 228 229 ;;; org-secretary.el ends here