2010-01-13 06:51:30 -05:00
|
|
|
;;; org-secretary.el --- Team management with org-mode
|
2013-01-01 10:04:24 -05:00
|
|
|
;; Copyright (C) 2010-2013 Juan Reyero
|
2010-01-13 06:51:30 -05:00
|
|
|
;;
|
|
|
|
;; Author: Juan Reyero <juan _at_ juanreyero _dot_ com>
|
|
|
|
;; Keywords: outlines, tasks, team, management
|
|
|
|
;; Homepage: http://juanreyero.com/article/emacs/org-teams.html
|
|
|
|
;; Version: 0.02
|
|
|
|
;;
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;;
|
|
|
|
;; This file is free software; you can redistribute it and/or modify
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
;; any later version.
|
|
|
|
|
|
|
|
;; THis file is distributed in the hope that it will be useful,
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
|
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
;; Boston, MA 02110-1301, USA.
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;;; Commentary:
|
|
|
|
;;
|
|
|
|
;; This module implements helper functions for team management. It
|
|
|
|
;; makes it easy to keep track of the work of several people. It
|
|
|
|
;; keeps context (with whom and where you are) and allows you to use
|
|
|
|
;; it to metadata to your notes, and to query the tasks associated
|
|
|
|
;; with the people you are with and the place.
|
|
|
|
;;
|
|
|
|
;; See http://juanreyero.com/article/emacs/org-teams.html for a full
|
|
|
|
;; explanation and configuration instructions.
|
|
|
|
;;
|
|
|
|
;;; Configuration
|
|
|
|
;;;;;;;;;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;; In short; your todos use the TODO keyword, your team's use TASK.
|
|
|
|
;; Your org-todo-keywords should look something like this:
|
|
|
|
;;
|
|
|
|
;; (setq org-todo-keywords
|
|
|
|
;; '((sequence "TODO(t)" "|" "DONE(d)" "CANCELLED(c)")
|
|
|
|
;; (sequence "TASK(f)" "|" "DONE(d)")
|
|
|
|
;; (sequence "MAYBE(m)" "|" "CANCELLED(c)")))
|
|
|
|
;;
|
|
|
|
;; It helps to distinguish them by color, like this:
|
|
|
|
;;
|
|
|
|
;; (setq org-todo-keyword-faces
|
|
|
|
;; '(("TODO" . (:foreground "DarkOrange1" :weight bold))
|
|
|
|
;; ("MAYBE" . (:foreground "sea green"))
|
|
|
|
;; ("DONE" . (:foreground "light sea green"))
|
|
|
|
;; ("CANCELLED" . (:foreground "forest green"))
|
|
|
|
;; ("TASK" . (:foreground "blue"))))
|
|
|
|
;;
|
|
|
|
;; If you want to keep track of stuck projects you should tag your
|
|
|
|
;; projects with :prj:, and define:
|
|
|
|
;;
|
|
|
|
;; (setq org-tags-exclude-from-inheritance '("prj")
|
|
|
|
;; org-stuck-projects '("+prj/-MAYBE-DONE"
|
|
|
|
;; ("TODO" "TASK") ()))
|
|
|
|
;;
|
|
|
|
;; Define a tag that marks TASK entries as yours:
|
|
|
|
;;
|
|
|
|
;; (setq org-sec-me "juanre")
|
|
|
|
;;
|
|
|
|
;; Finally, you add the special views to your org-agenda-custom-commands:
|
|
|
|
;;
|
|
|
|
;; (setq org-agenda-custom-commands
|
|
|
|
;; '(("h" "Work todos" tags-todo
|
|
|
|
;; "-personal-doat={.+}-dowith={.+}/!-TASK"
|
|
|
|
;; ((org-agenda-todo-ignore-scheduled t)))
|
|
|
|
;; ("H" "All work todos" tags-todo "-personal/!-TASK-MAYBE"
|
|
|
|
;; ((org-agenda-todo-ignore-scheduled nil)))
|
|
|
|
;; ("A" "Work todos with doat or dowith" tags-todo
|
|
|
|
;; "-personal+doat={.+}|dowith={.+}/!-TASK"
|
|
|
|
;; ((org-agenda-todo-ignore-scheduled nil)))
|
|
|
|
;; ("j" "TODO dowith and TASK with"
|
|
|
|
;; ((org-sec-with-view "TODO dowith")
|
|
|
|
;; (org-sec-where-view "TODO doat")
|
|
|
|
;; (org-sec-assigned-with-view "TASK with")
|
|
|
|
;; (org-sec-stuck-with-view "STUCK with")))
|
|
|
|
;; ("J" "Interactive TODO dowith and TASK with"
|
|
|
|
;; ((org-sec-who-view "TODO dowith")))))
|
|
|
|
;;
|
|
|
|
;;; Usage
|
|
|
|
;;;;;;;;;
|
|
|
|
;;
|
|
|
|
;; Do C-c w to say with whom you are meeting (a space-separated list
|
|
|
|
;; of names). Maybe do also C-c W to say where you are. Then do C-c a
|
|
|
|
;; j to see:
|
|
|
|
;; - Todo items defined with TODO (ie, mine) in which the
|
|
|
|
;; =dowith= property matches any of the people with me.
|
|
|
|
;; - Todo items defined with TODO in which the =doat= property
|
|
|
|
;; matches my current location.
|
|
|
|
;; - Todo items defined with TASK that are tagged with the name
|
|
|
|
;; of any of the people with me (this is, assigned to them).
|
|
|
|
;; - Stuck projects tagged with the name of the people with me.
|
|
|
|
;;
|
|
|
|
;; Use C-c j to add meta-data with the people with me, the
|
|
|
|
;; location and the time to entries.
|
|
|
|
|
|
|
|
(require 'org)
|
|
|
|
|
|
|
|
(defvar org-sec-me nil
|
|
|
|
"Tag that defines TASK todo entries associated to me")
|
|
|
|
|
|
|
|
(defvar org-sec-with nil
|
|
|
|
"Value of the :with: property when doing an
|
|
|
|
org-sec-tag-entry. Change it with org-sec-set-with,
|
|
|
|
set to C-c w. Defaults to org-sec-me")
|
|
|
|
|
|
|
|
(defvar org-sec-where ""
|
|
|
|
"Value of the :at: property when doing an
|
|
|
|
org-sec-tag-entry. Change it with org-sec-set-with,
|
|
|
|
set to C-c W")
|
|
|
|
|
|
|
|
(defvar org-sec-with-history '()
|
|
|
|
"History list of :with: properties")
|
|
|
|
|
|
|
|
(defvar org-sec-where-history '()
|
|
|
|
"History list of :where: properties")
|
|
|
|
|
|
|
|
(defun org-sec-set-with ()
|
|
|
|
"Changes the value of the org-sec-with variable for use in the
|
|
|
|
next call of org-sec-tag-entry. Leave it empty to default to
|
|
|
|
org-sec-me (you)."
|
|
|
|
(interactive)
|
|
|
|
(setq org-sec-with (let ((w (read-string "With: " nil
|
|
|
|
'org-sec-with-history "")))
|
|
|
|
(if (string= w "")
|
|
|
|
nil
|
|
|
|
w))))
|
|
|
|
(global-set-key "\C-cw" 'org-sec-set-with)
|
|
|
|
|
|
|
|
(defun org-sec-set-where ()
|
|
|
|
"Changes the value of the org-sec-where variable for use
|
|
|
|
in the next call of org-sec-tag-entry."
|
|
|
|
(interactive)
|
|
|
|
(setq org-sec-where
|
|
|
|
(read-string "Where: " nil
|
|
|
|
'org-sec-where-history "")))
|
|
|
|
(global-set-key "\C-cW" 'org-sec-set-where)
|
|
|
|
|
|
|
|
(defun org-sec-set-dowith ()
|
|
|
|
"Sets the value of the dowith property."
|
|
|
|
(interactive)
|
|
|
|
(let ((do-with
|
|
|
|
(read-string "Do with: "
|
|
|
|
nil 'org-sec-dowith-history "")))
|
|
|
|
(unless (string= do-with "")
|
|
|
|
(org-entry-put nil "dowith" do-with))))
|
|
|
|
(global-set-key "\C-cd" 'org-sec-set-dowith)
|
|
|
|
|
|
|
|
(defun org-sec-set-doat ()
|
|
|
|
"Sets the value of the doat property."
|
|
|
|
(interactive)
|
|
|
|
(let ((do-at (read-string "Do at: "
|
|
|
|
nil 'org-sec-doat-history "")))
|
|
|
|
(unless (string= do-at "")
|
|
|
|
(org-entry-put nil "doat" do-at))))
|
|
|
|
(global-set-key "\C-cD" 'org-sec-set-doat)
|
|
|
|
|
|
|
|
(defun org-sec-tag-entry ()
|
|
|
|
"Adds a :with: property with the value of org-sec-with if
|
|
|
|
defined, an :at: property with the value of org-sec-where
|
|
|
|
if defined, and an :on: property with the current time."
|
|
|
|
(interactive)
|
|
|
|
(save-excursion
|
|
|
|
(org-entry-put nil "on" (format-time-string
|
|
|
|
(org-time-stamp-format 'long)
|
|
|
|
(current-time)))
|
|
|
|
(unless (string= org-sec-where "")
|
|
|
|
(org-entry-put nil "at" org-sec-where))
|
|
|
|
(if org-sec-with
|
|
|
|
(org-entry-put nil "with" org-sec-with))))
|
|
|
|
(global-set-key "\C-cj" 'org-sec-tag-entry)
|
|
|
|
|
|
|
|
(defun join (lst sep &optional pre post)
|
|
|
|
(mapconcat (function (lambda (x) (concat pre x post))) lst sep))
|
|
|
|
|
|
|
|
(defun org-sec-get-with ()
|
|
|
|
(if org-sec-with
|
|
|
|
org-sec-with
|
|
|
|
org-sec-me))
|
|
|
|
|
|
|
|
(defun org-sec-with-view (par &optional who)
|
|
|
|
"Select tasks marked as dowith=who, where who
|
|
|
|
defaults to the value of org-sec-with."
|
|
|
|
(org-tags-view '(4) (join (split-string (if who
|
|
|
|
who
|
|
|
|
(org-sec-get-with)))
|
|
|
|
"|" "dowith=\"" "\"")))
|
|
|
|
|
|
|
|
(defun org-sec-where-view (par)
|
|
|
|
"Select tasks marked as doat=org-sec-where."
|
|
|
|
(org-tags-view '(4) (concat "doat={" org-sec-where "}")))
|
|
|
|
|
|
|
|
(defun org-sec-assigned-with-view (par &optional who)
|
|
|
|
"Select tasks assigned to who, by default org-sec-with."
|
|
|
|
(org-tags-view '(4)
|
|
|
|
(concat (join (split-string (if who
|
|
|
|
who
|
|
|
|
(org-sec-get-with)))
|
|
|
|
"|")
|
|
|
|
"/TASK")))
|
|
|
|
|
|
|
|
(defun org-sec-stuck-with-view (par &optional who)
|
|
|
|
"Select stuck projects assigned to who, by default
|
|
|
|
org-sec-with."
|
|
|
|
(let ((org-stuck-projects
|
|
|
|
`(,(concat "+prj+"
|
|
|
|
(join (split-string (if who
|
|
|
|
who
|
|
|
|
(org-sec-get-with))) "|")
|
|
|
|
"/-MAYBE-DONE")
|
|
|
|
("TODO" "TASK") ())))
|
|
|
|
(org-agenda-list-stuck-projects)))
|
|
|
|
|
|
|
|
(defun org-sec-who-view (par)
|
|
|
|
"Builds agenda for a given user. Queried. "
|
|
|
|
(let ((who (read-string "Build todo for user/tag: "
|
|
|
|
"" "" "")))
|
|
|
|
(org-sec-with-view "TODO dowith" who)
|
|
|
|
(org-sec-assigned-with-view "TASK with" who)
|
|
|
|
(org-sec-stuck-with-view "STUCK with" who)))
|
|
|
|
|
|
|
|
(provide 'org-secretary)
|
|
|
|
|
|
|
|
;;; org-secretary.el ends here
|