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.
This commit is contained in:
Carsten Dominik 2008-04-04 23:44:48 +02:00
parent f87667c730
commit 3ab4658e17
8 changed files with 121 additions and 9 deletions

2
.gitignore vendored
View File

@ -42,6 +42,8 @@ tmp
*~ *~
.DS_Store .DS_Store
*#
.#*
# #
# Local variables: # Local variables:

View File

@ -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> 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 * doc/org.texi (Agenda commands): Document columns view in the
agenda. agenda.

View File

@ -53,6 +53,14 @@
total time for each file will now also be listed. This was total time for each file will now also be listed. This was
a request from Bernt Hansen. 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 *** Selective tag inheritance
Inheritance of tags can now be limited to a subset of all Inheritance of tags can now be limited to a subset of all

View File

@ -5477,6 +5477,14 @@ previously used indirect buffer.
Toggle Logbook mode. In Logbook mode, entries that where marked DONE while 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, logging was on (variable @code{org-log-done}) are shown in the agenda,
as are entries that have been clocked on that day. 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} @tsubheading{Change display}
@cindex display changing, in agenda @cindex display changing, in agenda

View File

@ -486,6 +486,11 @@ Needs to be set before org.el is loaded."
:group 'org-agenda-startup :group 'org-agenda-startup
:type 'boolean) :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 (defgroup org-agenda-windows nil
"Options concerning the windows used by the Agenda in Org Mode." "Options concerning the windows used by the Agenda in Org Mode."
:tag "Org Agenda Windows" :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-menu) ; defined later in this file.
(defvar org-agenda-follow-mode nil) (defvar org-agenda-follow-mode nil)
(defvar org-agenda-clockreport-mode nil)
(defvar org-agenda-show-log nil) (defvar org-agenda-show-log nil)
(defvar org-agenda-redo-command nil) (defvar org-agenda-redo-command nil)
(defvar org-agenda-query-string nil) (defvar org-agenda-query-string nil)
@ -956,6 +962,7 @@ The following commands are available:
buffer-substring-filters))) buffer-substring-filters)))
(unless org-agenda-keep-modes (unless org-agenda-keep-modes
(setq org-agenda-follow-mode org-agenda-start-with-follow-mode (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)) org-agenda-show-log nil))
(easy-menu-change (easy-menu-change
'("Agenda") "Agenda Files" '("Agenda") "Agenda Files"
@ -1016,6 +1023,7 @@ The following commands are available:
(int-to-string (pop l)) 'digit-argument))) (int-to-string (pop l)) 'digit-argument)))
(org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode) (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 "l" 'org-agenda-log-mode)
(org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary) (org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
(org-defkey org-agenda-mode-map "G" 'org-agenda-toggle-time-grid) (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 ["Show Logbook entries" org-agenda-log-mode
:style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)] :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 ["Include Diary" org-agenda-toggle-diary
:style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)] :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
["Use Time Grid" org-agenda-toggle-time-grid ["Use Time Grid" org-agenda-toggle-time-grid
@ -2161,7 +2171,8 @@ given in `org-agenda-start-on-weekday'."
(day-numbers (list start)) (day-numbers (list start))
(day-cnt 0) (day-cnt 0)
(inhibit-redisplay (not debug-on-error)) (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 (setq org-agenda-redo-command
(list 'org-agenda-list (list 'quote include-all) start-day ndays)) (list 'org-agenda-list (list 'quote include-all) start-day ndays))
;; Make the list of days ;; Make the list of days
@ -2171,6 +2182,8 @@ given in `org-agenda-start-on-weekday'."
(push (1+ (car day-numbers)) day-numbers) (push (1+ (car day-numbers)) day-numbers)
(setq ndays (1- ndays))) (setq ndays (1- ndays)))
(setq day-numbers (nreverse day-numbers)) (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-prepare-agenda "Day/Week")
(org-set-local 'org-starting-day (car day-numbers)) (org-set-local 'org-starting-day (car day-numbers))
(org-set-local 'org-include-all-loc include-all) (org-set-local 'org-include-all-loc include-all)
@ -2254,6 +2267,11 @@ given in `org-agenda-start-on-weekday'."
"\n")) "\n"))
(put-text-property s (1- (point)) 'day d) (put-text-property s (1- (point)) 'day d)
(put-text-property s (1- (point)) 'org-day-cnt day-cnt)))) (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)) (goto-char (point-min))
(org-fit-agenda-window) (org-fit-agenda-window)
(unless (and (pos-visible-in-window-p (point-min)) (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" (message "Follow mode is %s"
(if org-agenda-follow-mode "on" "off"))) (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 () (defun org-agenda-log-mode ()
"Toggle log mode in an agenda buffer." "Toggle log mode in an agenda buffer."
(interactive) (interactive)
@ -4141,7 +4169,8 @@ so that the date SD will be in that range."
(if org-agenda-follow-mode " Follow" "") (if org-agenda-follow-mode " Follow" "")
(if org-agenda-include-diary " Diary" "") (if org-agenda-include-diary " Diary" "")
(if org-agenda-use-time-grid " Grid" "") (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)) (force-mode-line-update))
(defun org-agenda-post-command-hook () (defun org-agenda-post-command-hook ()

View File

@ -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 (add-hook 'org-after-todo-state-change-hook
'org-clock-out-if-current) '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) (defun org-clock-report (&optional arg)
"Create a table containing a report about clocked time. "Create a table containing a report about clocked time.
If the cursor is inside an existing clocktable block, then the table If the cursor is inside an existing clocktable block, then the table
@ -557,7 +580,7 @@ the currently selected interval size."
(catch 'exit (catch 'exit
(let* ((hlchars '((1 . "*") (2 . "/"))) (let* ((hlchars '((1 . "*") (2 . "/")))
(ins (make-marker)) (ins (make-marker))
(total-time nil) (total-time 0)
(scope (plist-get params :scope)) (scope (plist-get params :scope))
(tostring (plist-get params :tostring)) (tostring (plist-get params :tostring))
(multifile (plist-get params :multifile)) (multifile (plist-get params :multifile))
@ -577,6 +600,13 @@ the currently selected interval size."
(when block (when block
(setq cc (org-clock-special-range block nil t) (setq cc (org-clock-special-range block nil t)
ts (car cc) te (nth 1 cc) range-text (nth 2 cc))) 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 (if ts (setq ts (time-to-seconds
(apply 'encode-time (org-parse-time-string ts))))) (apply 'encode-time (org-parse-time-string ts)))))
(if te (setq te (time-to-seconds (if te (setq te (time-to-seconds
@ -604,7 +634,7 @@ the currently selected interval size."
(throw 'exit nil)))) (throw 'exit nil))))
(org-narrow-to-subtree)) (org-narrow-to-subtree))
((or (listp scope) (eq scope 'agenda)) ((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) (scope 'agenda)
(p1 (copy-sequence params)) (p1 (copy-sequence params))
file) file)
@ -677,7 +707,7 @@ the currently selected interval size."
(if (eq scope 'agenda) "|" "") (if (eq scope 'agenda) "|" "")
"|" "|"
"*Total time*| *" "*Total time*| *"
(org-minutes-to-hours total-time) (org-minutes-to-hours (or total-time 0))
"*|\n|-\n") "*|\n|-\n")
(setq tbl (delq nil tbl)) (setq tbl (delq nil tbl))
(if (and (stringp (car tbl)) (> (length (car tbl)) 1) (if (and (stringp (car tbl)) (> (length (car tbl)) 1)

View File

@ -27,12 +27,13 @@
;; ;;
;;; Commentary: ;;; Commentary:
;; This file contains macro definitions, defsubst definitions, and ;; This file contains macro definitions, defsubst definitions, other
;; oder stuff needed for compilation and top-level forms in Org-mode. ;; 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: ;;; Code:
(defmacro org-bound-and-true-p (var) (defmacro org-bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil." "Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var)) `(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)) (goto-char (point-at-bol))
(looking-at re))) (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) (provide 'org-macs)
;;; org-macs.el ends here ;;; org-macs.el ends here

View File

@ -2831,7 +2831,8 @@ org-remember-apply-template org-remember org-remember-handler)))
'(org-clock-in org-clock-out org-clock-cancel '(org-clock-in org-clock-out org-clock-cancel
org-clock-goto org-clock-sum org-clock-display org-clock-goto org-clock-sum org-clock-display
org-remove-clock-overlays org-clock-report 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 () (defun org-clock-update-time-maybe ()
"If this is a CLOCK line, update it and return t. "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 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
;;; org.el ends here ;;; 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))