1
0
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-12-31 11:13:59 +00:00

Implement table formulas for clocktables.

Org-mode produces summaries of clocked items in the form of Org-mode
tables.  This patch implements the possibility to define formulas that
should be applied to the clock tables, in order to do additional
analysis.

Formulas for clock tables are supported in two ways.

First, a formula can simply be added by hand to a table.  Part of this
patch makes sure that, when the previous version of the table contains
a #+TBLFM: line, it will be copied to the new version.

Secondly, the clocktable definition allows a new parameter
`:formula'.  The string value of this parameter will be installed as
the formula line for the table.  If a formula parameter is given, it
will overrule any previous formula line.

As a special case, using the symbol `%' as the formula will install a
formula that will compute the fraction of total time that was spent in
a subtree.

In both cases, the formulas will be immediately evaluated after the
table has been created.
This commit is contained in:
Carsten Dominik 2008-11-10 20:57:48 +01:00
parent c52b9af3a8
commit e41a0d9608
4 changed files with 68 additions and 1 deletions

View File

@ -1,3 +1,8 @@
2008-11-10 Carsten Dominik <carsten.dominik@gmail.com>
* org.texi (Clocking work time): Document the :formula property of
clock tables.
2008-11-09 Carsten Dominik <carsten.dominik@gmail.com>
* org.texi (Agenda commands): Document the double-prefix version

View File

@ -4830,6 +4830,10 @@ new table. The @samp{BEGIN} line can specify options:
:step @r{@code{week} or @code{day}, to split the table into chunks.}
@r{To use this, @code{:block} or @code{:tstart}, @code{:tend} are needed.}
:link @r{Link the item headlines in the table to their origins}
:formula @r{Content of a @code{#+TBLFM} line to be added and evaluated.}
@r{As a special case, @samp{:formula %} adds column with % time.}
@r{If you do not specify a formula here, any existing formula}
@r{below the clock table will survive updates and be evaluated.}
@end example
So to get a clock summary of the current level 1 tree, for the current
day, you could write
@ -4845,6 +4849,11 @@ only to fit it onto the manual.}
:tend "<2006-08-10 Thu 12:00>"
#+END: clocktable
@end example
A summary of the current subtree with % times would be
@example
#+BEGIN: clocktable :scope subtree :link t :formula %
#+END: clocktable
@end example
@kindex C-c C-c
@item C-c C-c
@kindex C-c C-x C-u

View File

@ -1,5 +1,7 @@
2008-11-10 Carsten Dominik <carsten.dominik@gmail.com>
* org-clock.el (org-clock-time%): New function.
* org.el (org-entry-get, org-entry-delete): Use safer regexps to
retrieve property values.

View File

@ -819,7 +819,7 @@ the currently selected interval size."
(te (plist-get params :tend))
(block (plist-get params :block))
(link (plist-get params :link))
ipos time p level hlc hdl
ipos time p level hlc hdl content recalc formula pcol
cc beg end pos tbl tbl1 range-text rm-file-column scope-is-list)
(setq org-clock-file-total-minutes nil)
(when step
@ -959,9 +959,37 @@ the currently selected interval size."
'identity (delq nil tbl)
(if scope-is-list "\n|-\n" "\n")))
(backward-delete-char 1)
(if (setq formula (plist-get params :formula))
(cond
((eq formula '%)
(setq pcol (+ (if scope-is-list 1 0) maxlevel 3))
(insert
(format
"\n#+TBLFM: $%d='(org-clock-time%% @%d$%d $%d..$%d);%%.1f"
pcol
2
(+ 3 (if scope-is-list 1 0))
(+ (if scope-is-list 1 0) 3)
(1- pcol)))
(setq recalc t))
((stringp formula)
(insert "\n#+TBLFM: " formula)
(setq recalc t))
(t (error "invalid formula in clocktable")))
;; Should we rescue an old formula?
(when (stringp (setq content (plist-get params :content)))
(when (string-match "^\\(#\\+TBLFM:.*\\)" content)
(setq recalc t)
(insert "\n" (match-string 1 (plist-get params :content)))
(beginning-of-line 0))))
(goto-char ipos)
(skip-chars-forward "^|")
(org-table-align)
(when recalc
(if (eq formula '%)
(save-excursion (org-table-goto-column pcol nil 'force)
(insert "%")))
(org-table-recalculate 'all))
(when rm-file-column
(forward-char 1)
(org-table-delete-column)))))))
@ -1010,6 +1038,29 @@ the currently selected interval size."
lines)
"\n"))))
(defun org-clock-time% (total &rest strings)
"Compute a time fraction in percent.
TOTAL s a time string like 10:21 specifying the total times.
STRINGS is a list of strings that should be checked for a time.
The first string that does have a time will be used.
This function is made for clock tables."
(let ((re "\\([0-9]+\\):\\([0-9]+\\)")
tot s)
(save-match-data
(catch 'exit
(if (not (string-match re total))
(throw 'exit 0.)
(setq tot (+ (string-to-number (match-string 2 total))
(* 60 (string-to-number (match-string 1 total)))))
(if (= tot 0.) (throw 'exit 0.)))
(while (setq s (pop strings))
(if (string-match "\\([0-9]+\\):\\([0-9]+\\)" s)
(throw 'exit
(/ (* 100.0 (+ (string-to-number (match-string 2 s))
(* 60 (string-to-number (match-string 1 s)))))
tot))))
0))))
(defun org-clock-save ()
"Persist various clock-related data to disk"
(with-current-buffer (find-file (expand-file-name org-clock-persist-file))