summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2008-04-04 23:44:48 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2008-04-06 17:25:47 +0200
commit3ab4658e171d2d060670a800296ef74110ed4207 (patch)
tree9c8be847fb73d9061e476dd9bdff596111e5a14e
parentf87667c730f0a69c6be051f8742fccfb4c47fe0d (diff)
downloadorg-mode-3ab4658e171d2d060670a800296ef74110ed4207.tar.gz
Implemented showing a clock report in the agenda.
This is a new display mode in the agenda view. It appends a clock table to the daily/weekly agenda view that covers clocked time for the time span shown in the agenda, and also limited to the files that were used to create the current view.
-rw-r--r--.gitignore2
-rw-r--r--ChangeLog14
-rw-r--r--ORGWEBPAGE/Changes.org8
-rw-r--r--doc/org.texi8
-rw-r--r--lisp/org-agenda.el33
-rw-r--r--lisp/org-clock.el36
-rw-r--r--lisp/org-macs.el17
-rw-r--r--lisp/org.el12
8 files changed, 121 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
index 6dc4d8a..4d7c503 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,8 @@ tmp
*~
.DS_Store
+*#
+.#*
#
# Local variables:
diff --git a/ChangeLog b/ChangeLog
index ebb2ec1..090f0f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
+2008-04-06 Carsten Dominik <dominik@science.uva.nl>
+
+ * lisp/org-agenda.el (org-agenda-start-with-clockreport-mode): New
+ option.
+
+ * lisp/org-clock.el (org-dblock-write:clocktable): Request the
+ unrestricted list of files.
+ (org-get-clocktable): New function.
+ (org-dblock-write:clocktable): Make sure :tstart and :tend can not
+ only be strings but also integers (an absolute day number) and
+ lists (m d y).
+
2008-04-04 Carsten Dominik <dominik@science.uva.nl>
+ * lisp/org-agenda.el (org-agenda-clocktable-mode): New variable.
+
* doc/org.texi (Agenda commands): Document columns view in the
agenda.
diff --git a/ORGWEBPAGE/Changes.org b/ORGWEBPAGE/Changes.org
index cfb6833..8449ada 100644
--- a/ORGWEBPAGE/Changes.org
+++ b/ORGWEBPAGE/Changes.org
@@ -53,6 +53,14 @@
total time for each file will now also be listed. This was
a request from Bernt Hansen.
+*** Clockreport in the daily/weekly arenda
+
+ If you turn on clockreport mode with the "R" key in the
+ agenda, a clock table will be attached to the agenda, showing
+ the clock report for the file scope and time interval of the
+ agenda view. To turn this on permanently, configure the
+ variable =org-agenda-start-with-clockreport-mode=.
+
*** Selective tag inheritance
Inheritance of tags can now be limited to a subset of all
diff --git a/doc/org.texi b/doc/org.texi
index de2726b..aec0e70 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -5477,6 +5477,14 @@ previously used indirect buffer.
Toggle Logbook mode. In Logbook mode, entries that where marked DONE while
logging was on (variable @code{org-log-done}) are shown in the agenda,
as are entries that have been clocked on that day.
+@c
+@kindex R
+@item R
+Toggle Clockreport mode. In clockreport mode, the daily/weekly agenda will
+always show a table with the clocked times for the timespan and file scope
+covered by the current agenda view. The initial setting for this mode in new
+agenda buffers can be set with the variable
+@code{org-agenda-start-with-follow-mode}.
@tsubheading{Change display}
@cindex display changing, in agenda
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 9fd471d..6048d16 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -486,6 +486,11 @@ Needs to be set before org.el is loaded."
:group 'org-agenda-startup
:type 'boolean)
+(defcustom org-agenda-start-with-clockreport-mode nil
+ "The initial value of clockreport-mode in a newly created agenda window."
+ :group 'org-agenda-startup
+ :type 'boolean)
+
(defgroup org-agenda-windows nil
"Options concerning the windows used by the Agenda in Org Mode."
:tag "Org Agenda Windows"
@@ -922,6 +927,7 @@ works you probably want to add it to `org-agenda-custom-commands' for good."
(defvar org-agenda-menu) ; defined later in this file.
(defvar org-agenda-follow-mode nil)
+(defvar org-agenda-clockreport-mode nil)
(defvar org-agenda-show-log nil)
(defvar org-agenda-redo-command nil)
(defvar org-agenda-query-string nil)
@@ -956,6 +962,7 @@ The following commands are available:
buffer-substring-filters)))
(unless org-agenda-keep-modes
(setq org-agenda-follow-mode org-agenda-start-with-follow-mode
+ org-agenda-clockreport-mode org-agenda-start-with-clockreport-mode
org-agenda-show-log nil))
(easy-menu-change
'("Agenda") "Agenda Files"
@@ -1016,6 +1023,7 @@ The following commands are available:
(int-to-string (pop l)) 'digit-argument)))
(org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode)
+(org-defkey org-agenda-mode-map "R" 'org-agenda-clockreport-mode)
(org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
(org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
(org-defkey org-agenda-mode-map "G" 'org-agenda-toggle-time-grid)
@@ -1140,6 +1148,8 @@ The following commands are available:
"--"
["Show Logbook entries" org-agenda-log-mode
:style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
+ ["Show clock report" org-agenda-clockreport-mode
+ :style toggle :selected org-agenda-clockreport-mode :active (org-agenda-check-type nil 'agenda)]
["Include Diary" org-agenda-toggle-diary
:style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
["Use Time Grid" org-agenda-toggle-time-grid
@@ -2161,7 +2171,8 @@ given in `org-agenda-start-on-weekday'."
(day-numbers (list start))
(day-cnt 0)
(inhibit-redisplay (not debug-on-error))
- s e rtn rtnall file date d start-pos end-pos todayp nd)
+ s e rtn rtnall file date d start-pos end-pos todayp nd
+ clocktable-start clocktable-end)
(setq org-agenda-redo-command
(list 'org-agenda-list (list 'quote include-all) start-day ndays))
;; Make the list of days
@@ -2171,6 +2182,8 @@ given in `org-agenda-start-on-weekday'."
(push (1+ (car day-numbers)) day-numbers)
(setq ndays (1- ndays)))
(setq day-numbers (nreverse day-numbers))
+ (setq clocktable-start (car day-numbers)
+ clocktable-end (1+ (or (org-last day-numbers) 0)))
(org-prepare-agenda "Day/Week")
(org-set-local 'org-starting-day (car day-numbers))
(org-set-local 'org-include-all-loc include-all)
@@ -2254,6 +2267,11 @@ given in `org-agenda-start-on-weekday'."
"\n"))
(put-text-property s (1- (point)) 'day d)
(put-text-property s (1- (point)) 'org-day-cnt day-cnt))))
+ (when (and org-agenda-clockreport-mode clocktable-start)
+ (let ((org-agenda-files (org-agenda-files)))
+ ;; the above line is to ensure the restricted range!
+ (insert (org-get-clocktable :tstart clocktable-start
+ :tend clocktable-end :link t))))
(goto-char (point-min))
(org-fit-agenda-window)
(unless (and (pos-visible-in-window-p (point-min))
@@ -4102,6 +4120,16 @@ so that the date SD will be in that range."
(message "Follow mode is %s"
(if org-agenda-follow-mode "on" "off")))
+(defun org-agenda-clockreport-mode ()
+ "Toggle clocktable mode in an agenda buffer."
+ (interactive)
+ (org-agenda-check-type t 'agenda)
+ (setq org-agenda-clockreport-mode (not org-agenda-clockreport-mode))
+ (org-agenda-set-mode-name)
+ (org-agenda-redo)
+ (message "Clocktable mode is %s"
+ (if org-agenda-clockreport-mode "on" "off")))
+
(defun org-agenda-log-mode ()
"Toggle log mode in an agenda buffer."
(interactive)
@@ -4141,7 +4169,8 @@ so that the date SD will be in that range."
(if org-agenda-follow-mode " Follow" "")
(if org-agenda-include-diary " Diary" "")
(if org-agenda-use-time-grid " Grid" "")
- (if org-agenda-show-log " Log" "")))
+ (if org-agenda-show-log " Log" "")
+ (if org-agenda-clockreport-mode " Clock" "")))
(force-mode-line-update))
(defun org-agenda-post-command-hook ()
diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 4f3b7d6..33059e8 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -395,6 +395,29 @@ and is only done if the variable `org-clock-out-when-done' is not nil."
(add-hook 'org-after-todo-state-change-hook
'org-clock-out-if-current)
+;;;###autoload
+(defun org-get-clocktable (&rest props)
+ "Get a formatted clocktable with parameters according to PROPS.
+The table is created in a temporary buffer, fully formatted and
+fontified, and then returned."
+ ;; Set the defaults
+ (setq props (plist-put props :name "clocktable"))
+ (unless (plist-member props :maxlevel)
+ (setq props (plist-put props :maxlevel 2)))
+ (unless (plist-member props :link)
+ (setq props (plist-put props :link nil)))
+ (unless (plist-member props :scope)
+ (setq props (plist-put props :scope 'agenda)))
+ (with-temp-buffer
+ (org-mode)
+ (org-create-dblock props)
+ (org-update-dblock)
+ (font-lock-fontify-buffer)
+ (forward-line 2)
+ (buffer-substring (point) (progn
+ (re-search-forward "^#\\+END" nil t)
+ (point-at-bol)))))
+
(defun org-clock-report (&optional arg)
"Create a table containing a report about clocked time.
If the cursor is inside an existing clocktable block, then the table
@@ -557,7 +580,7 @@ the currently selected interval size."
(catch 'exit
(let* ((hlchars '((1 . "*") (2 . "/")))
(ins (make-marker))
- (total-time nil)
+ (total-time 0)
(scope (plist-get params :scope))
(tostring (plist-get params :tostring))
(multifile (plist-get params :multifile))
@@ -577,6 +600,13 @@ the currently selected interval size."
(when block
(setq cc (org-clock-special-range block nil t)
ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
+ (when (integerp ts) (setq ts (calendar-gregorian-from-absolute ts)))
+ (when (integerp te) (setq te (calendar-gregorian-from-absolute te)))
+ (when (and ts (listp ts))
+ (setq ts (format "%4d-%02d-%02d" (nth 2 ts) (car ts) (nth 1 ts))))
+ (when (and te (listp te))
+ (setq te (format "%4d-%02d-%02d" (nth 2 te) (car te) (nth 1 te))))
+ ;; Now the times are strings we can parse.
(if ts (setq ts (time-to-seconds
(apply 'encode-time (org-parse-time-string ts)))))
(if te (setq te (time-to-seconds
@@ -604,7 +634,7 @@ the currently selected interval size."
(throw 'exit nil))))
(org-narrow-to-subtree))
((or (listp scope) (eq scope 'agenda))
- (let* ((files (if (listp scope) scope (org-agenda-files)))
+ (let* ((files (if (listp scope) scope (org-agenda-files t)))
(scope 'agenda)
(p1 (copy-sequence params))
file)
@@ -677,7 +707,7 @@ the currently selected interval size."
(if (eq scope 'agenda) "|" "")
"|"
"*Total time*| *"
- (org-minutes-to-hours total-time)
+ (org-minutes-to-hours (or total-time 0))
"*|\n|-\n")
(setq tbl (delq nil tbl))
(if (and (stringp (car tbl)) (> (length (car tbl)) 1)
diff --git a/lisp/org-macs.el b/lisp/org-macs.el
index b8337db..23122b0 100644
--- a/lisp/org-macs.el
+++ b/lisp/org-macs.el
@@ -27,12 +27,13 @@
;;
;;; Commentary:
-;; This file contains macro definitions, defsubst definitions, and
-;; oder stuff needed for compilation and top-level forms in Org-mode.
+;; This file contains macro definitions, defsubst definitions, other
+;; stuff needed for compilation and top-level forms in Org-mode, as well
+;; lots of small functions that are not org-mode specific but simply
+;; generally useful stuff.
;;; Code:
-
(defmacro org-bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
@@ -212,6 +213,16 @@ we turn off invisibility temporarily. Use this in a `let' form."
(goto-char (point-at-bol))
(looking-at re)))
+(defun org-plist-delete (plist property)
+ "Delete PROPERTY from PLIST.
+This is in contrast to merely setting it to 0."
+ (let (p)
+ (while plist
+ (if (not (eq property (car plist)))
+ (setq p (plist-put p (car plist) (nth 1 plist))))
+ (setq plist (cddr plist)))
+ p))
+
(provide 'org-macs)
;;; org-macs.el ends here
diff --git a/lisp/org.el b/lisp/org.el
index 0a0233c..5529ec2 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -2831,7 +2831,8 @@ org-remember-apply-template org-remember org-remember-handler)))
'(org-clock-in org-clock-out org-clock-cancel
org-clock-goto org-clock-sum org-clock-display
org-remove-clock-overlays org-clock-report
- org-clocktable-shift org-dblock-write:clocktable)))
+ org-clocktable-shift org-dblock-write:clocktable
+ org-get-clocktable)))
(defun org-clock-update-time-maybe ()
"If this is a CLOCK line, update it and return t.
@@ -15119,3 +15120,12 @@ Still experimental, may disappear in the future."
;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
;;; org.el ends here
+(defun org-plist-delete (plist property)
+ "Delete PROPERTY from PLIST.
+This is in contrast to merely setting it to 0."
+ (let (p)
+ (while plist
+ (if (not (eq property (car plist)))
+ (setq p (plist-put p (car plist) (nth 1 plist))))
+ (setq plist (cddr plist)))
+ p))