mirror of
https://github.com/SqrtMinusOne/org-clock-agg.git
synced 2025-12-10 14:03:02 +03:00
org-clock-agg: fix docstrings
This commit is contained in:
parent
3de2c9bf2e
commit
f7cd533a29
1 changed files with 154 additions and 140 deletions
294
org-clock-agg.el
294
org-clock-agg.el
|
|
@ -25,12 +25,12 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; Aggregate org-clock records and show the results in an interactive
|
;; Aggregate org-clock records and display the results in an
|
||||||
;; buffer. The records are grouped by predicates such as file name,
|
;; interactive buffer. org-clock records are grouped by predicates
|
||||||
;; their outline path in the file, etc. Each record is placed in a
|
;; such as file name, their outline path in the file, etc. Each
|
||||||
;; tree strcture; each node of the tree shows the total time spent in
|
;; record is placed in a tree structure; each node of the tree shows
|
||||||
;; that node and its children. The top-level node shows the total
|
;; the total time spent in that node and its children. The top-level
|
||||||
;; time spent in all records found by the query.
|
;; node shows the total time spent in all records found by the query.
|
||||||
;;
|
;;
|
||||||
;; `org-clock-agg' is the main entrypoint. It can be run interactively
|
;; `org-clock-agg' is the main entrypoint. It can be run interactively
|
||||||
;; or from elisp code. See the docstring for details.
|
;; or from elisp code. See the docstring for details.
|
||||||
|
|
@ -56,41 +56,47 @@
|
||||||
(defcustom org-clock-agg-duration-format "%h:%.2m"
|
(defcustom org-clock-agg-duration-format "%h:%.2m"
|
||||||
"Format string for durations in `org-clock-agg' views.
|
"Format string for durations in `org-clock-agg' views.
|
||||||
|
|
||||||
See `format-seconds' for the list of available format specifiers."
|
Refer to `format-seconds' for the available format specifiers."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-files-preset nil
|
(defcustom org-clock-agg-files-preset nil
|
||||||
"Presets for the \"files\" parameter in org-clock-agg views."
|
"Presets for the \"files\" parameter in `org-clock-agg' views."
|
||||||
:type '(alist :key-type string :value-type (repeat string))
|
:type '(alist :key-type string :value-type (repeat string))
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-day-format "%Y-%m-%d, %a"
|
(defcustom org-clock-agg-day-format "%Y-%m-%d, %a"
|
||||||
"Format string for days in `org-clock-agg' views.
|
"Format string for days in `org-clock-agg' views.
|
||||||
|
|
||||||
See `format-time-string' for the list of available format specifiers."
|
Refer to `format-time-string' for the available format
|
||||||
|
specifiers."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-week-format "%Y-%W"
|
(defcustom org-clock-agg-week-format "%Y-%W"
|
||||||
"Format string for weeks in `org-clock-agg' views.
|
"Format string for weeks in `org-clock-agg' views.
|
||||||
|
|
||||||
See `format-time-string' for the list of available format specifiers."
|
Refer to `format-time-string' for the list of available format
|
||||||
|
specifiers."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-month-format "%Y-%m"
|
(defcustom org-clock-agg-month-format "%Y-%m"
|
||||||
"Format string for months in `org-clock-agg' views.
|
"Format string for months in `org-clock-agg' views.
|
||||||
|
|
||||||
See `format-time-string' for the list of available format specifiers."
|
Refer to `format-time-string' for the list of available format
|
||||||
|
specifiers."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-properties nil
|
(defcustom org-clock-agg-properties nil
|
||||||
"Org properties to include in `org-clock-agg' views.
|
"Org properties to include in `org-clock-agg' views.
|
||||||
|
|
||||||
Either set this interactively or reset the `org-ql-cache' variable
|
The value of this variable should be a list of strings.
|
||||||
manually after setting."
|
|
||||||
|
Set this interactively or manually reset `org-ql-cache' and
|
||||||
|
`org-ql-node-value-cache' after modification."
|
||||||
|
|
||||||
:type '(repeat string)
|
:type '(repeat string)
|
||||||
:group 'org-clock-agg
|
:group 'org-clock-agg
|
||||||
:set (lambda (&rest _)
|
:set (lambda (&rest _)
|
||||||
|
|
@ -98,37 +104,36 @@ manually after setting."
|
||||||
(setq org-ql-node-value-cache (make-hash-table :weakness 'key))))
|
(setq org-ql-node-value-cache (make-hash-table :weakness 'key))))
|
||||||
|
|
||||||
(defcustom org-clock-agg-node-title-width-delta 40
|
(defcustom org-clock-agg-node-title-width-delta 40
|
||||||
"How many characters to take away from the node title.
|
"How many characters to truncate from the node title.
|
||||||
|
|
||||||
See `org-clock-agg-node-format' on how to set this."
|
Refer to `org-clock-agg-node-format' for instructions on configuring
|
||||||
|
this."
|
||||||
:type 'integer
|
:type 'integer
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defcustom org-clock-agg-node-format "%-%(+ title-width)t %20c %8z"
|
(defcustom org-clock-agg-node-format "%-%(+ title-width)t %20c %8z"
|
||||||
"Format string for node title in `org-clock-agg' views.
|
"Format string for the node title in `org-clock-agg' views.
|
||||||
|
|
||||||
The following format specifiers are available:
|
The following format specifiers are available:
|
||||||
- %t - node title with the level prefix, truncated to
|
- %t - node title with the level prefix, truncated to `title-width'
|
||||||
`title-width' characters (see below)
|
characters (see below)
|
||||||
- %c - the name of the grouping function that produced the node
|
- %c - name of the grouping function that produced the node (the
|
||||||
(the `:readable-name' parameter)
|
`:readable-name' parameter)
|
||||||
- %z - time spent in node according to
|
- %z - time spent in the node according to
|
||||||
`org-clock-agg-duration-format'.
|
`org-clock-agg-duration-format'
|
||||||
- %s - time share of the node against the parent node
|
- %s - time share of the node against the parent node
|
||||||
- %S - time share of the node against the top-level node
|
- %S - time share of the node against the top-level node
|
||||||
|
|
||||||
See `format-spec' for the avaliable modifers.
|
Refer to `format-spec' for available modifiers.
|
||||||
|
|
||||||
This format string also evaluates elisp expressions in the
|
This format string also evaluates Elisp expressions in the %(...)
|
||||||
%(...) blocks. During evaluation, the following variables are
|
blocks. During evaluation, the following variables are bound:
|
||||||
bound:
|
- `title-width': `window-width' minus
|
||||||
- `title-width' - `window-width' minus
|
`org-clock-agg-node-title-width-delta'.
|
||||||
`org-clock-agg-node-title-width-delta'
|
|
||||||
|
|
||||||
That way, in the default configuration, the node title is truncated to
|
This way, in the default configuration, the node title is truncated to
|
||||||
make the resulting string fit into the window.
|
fit into the window, utilizing `org-clock-agg-node-title-width-delta'
|
||||||
I.e. `org-clock-agg-node-title-width-delta' means how many characters
|
as the remaining characters for the rest of the string."
|
||||||
to allocate for the rest of the string, without the node title."
|
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
|
|
@ -141,12 +146,12 @@ The following format specifiers are available:
|
||||||
- %d - duration of the time range
|
- %d - duration of the time range
|
||||||
- %t - title of the record.
|
- %t - title of the record.
|
||||||
|
|
||||||
Formats of %s and %e are controlled by `org-time-stamp-formats'."
|
The formats of %s and %e are controlled by `org-time-stamp-formats'."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
(defconst org-clock-agg--extra-params-default
|
(defconst org-clock-agg--extra-params-default
|
||||||
'(("Show elements:" . (checkbox :extras-key :show-elems))
|
'(("Show records:" . (checkbox :extras-key :show-elems))
|
||||||
("Add \"Ungrouped\"" . (checkbox :extras-key :add-ungrouped)))
|
("Add \"Ungrouped\"" . (checkbox :extras-key :add-ungrouped)))
|
||||||
"Default set of extra parameters for `org-clock-agg' views.")
|
"Default set of extra parameters for `org-clock-agg' views.")
|
||||||
|
|
||||||
|
|
@ -182,10 +187,6 @@ It's probably supposed to be nil because it overrides the default
|
||||||
element formatting."
|
element formatting."
|
||||||
:group 'org-clock-agg)
|
:group 'org-clock-agg)
|
||||||
|
|
||||||
;; XXX org-ql caches results of queries, so make sure to run this
|
|
||||||
;; after updating `org-clock-agg--parse-headline'
|
|
||||||
;; (setq org-ql-cache (make-hash-table :weakness 'key))
|
|
||||||
|
|
||||||
;; This function appears in Emacs 29 and isn't avaliable in `compat'
|
;; This function appears in Emacs 29 and isn't avaliable in `compat'
|
||||||
;; for some reason
|
;; for some reason
|
||||||
(defun org-clock-agg--alist-to-plist (alist)
|
(defun org-clock-agg--alist-to-plist (alist)
|
||||||
|
|
@ -234,7 +235,7 @@ Return a list of alists with the following keys:
|
||||||
|
|
||||||
`org-clock-agg-properties' sets the list of properties to select. The
|
`org-clock-agg-properties' sets the list of properties to select. The
|
||||||
properties are inherited from the parent headlines and from the global
|
properties are inherited from the parent headlines and from the global
|
||||||
properties set in the beginning of the file."
|
properties set at the beginning of the file."
|
||||||
(let ((global-props
|
(let ((global-props
|
||||||
(org-ql--value-at
|
(org-ql--value-at
|
||||||
1 (lambda ()
|
1 (lambda ()
|
||||||
|
|
@ -296,16 +297,14 @@ list of properties to select
|
||||||
"Normalize VAL to a time predicate.
|
"Normalize VAL to a time predicate.
|
||||||
|
|
||||||
VAL can be either:
|
VAL can be either:
|
||||||
- a number, in which case it's interpreted as a number of days from
|
- A number interpreted as a number of days from the current one.
|
||||||
the current one
|
- A string parseable by `parse-time-string', with or without the time
|
||||||
- a string, parseable by `parse-time-string', with or without the time
|
part.
|
||||||
part.
|
|
||||||
|
|
||||||
KIND is either \"from\" or \"to\". If it's the latter, the time part is the
|
KIND is either \"from\" or \"to\". If it's the latter, the time part
|
||||||
to 23:59:59 when possible, otherwise it's 00:00:00.
|
is set to 23:59:59 when possible; otherwise, it's set to 00:00:00.
|
||||||
|
|
||||||
The result is a number of seconds since the epoch."
|
|
||||||
|
|
||||||
|
The result is the number of seconds since the epoch."
|
||||||
(when-let (int-val
|
(when-let (int-val
|
||||||
(and (stringp val) (ignore-errors (number-to-string val))))
|
(and (stringp val) (ignore-errors (number-to-string val))))
|
||||||
(setq val int-val))
|
(setq val int-val))
|
||||||
|
|
@ -335,11 +334,10 @@ The result is a number of seconds since the epoch."
|
||||||
(defun org-clock-agg--filter-elems (from to elems)
|
(defun org-clock-agg--filter-elems (from to elems)
|
||||||
"Filter ELEMS by FROM and TO.
|
"Filter ELEMS by FROM and TO.
|
||||||
|
|
||||||
FROM and TO should either be a number (e.g. -7 is the last week) or a
|
Refer to `org-clock-agg--normalize-time-predicate' for the possible
|
||||||
string parseable by `parse-time-string'.
|
values of FROM and TO.
|
||||||
|
|
||||||
ELEMS is a list as descbribed in `org-clock-agg--parse-headline'."
|
|
||||||
|
|
||||||
|
ELEMS is a list as described in `org-clock-agg--parse-headline'."
|
||||||
(let ((from-date (org-clock-agg--normalize-time-predicate from 'from))
|
(let ((from-date (org-clock-agg--normalize-time-predicate from 'from))
|
||||||
(to-date (org-clock-agg--normalize-time-predicate to 'to)))
|
(to-date (org-clock-agg--normalize-time-predicate to 'to)))
|
||||||
(cl-loop for elem in elems
|
(cl-loop for elem in elems
|
||||||
|
|
@ -352,7 +350,10 @@ ELEMS is a list as descbribed in `org-clock-agg--parse-headline'."
|
||||||
(defun org-clock-agg--query (from to files)
|
(defun org-clock-agg--query (from to files)
|
||||||
"Query org files in FILES for clocked entries from FROM to TO.
|
"Query org files in FILES for clocked entries from FROM to TO.
|
||||||
|
|
||||||
Return a list as descbribed in `org-clock-agg--parse-headline'."
|
Refer to `org-clock-agg--normalize-time-predicate' for the possible
|
||||||
|
values of FROM and TO.
|
||||||
|
|
||||||
|
Return a list as described in `org-clock-agg--parse-headline'."
|
||||||
(thread-last
|
(thread-last
|
||||||
(cl-loop for res in (org-ql-query
|
(cl-loop for res in (org-ql-query
|
||||||
:select #'org-clock-agg--parse-headline
|
:select #'org-clock-agg--parse-headline
|
||||||
|
|
@ -365,12 +366,13 @@ ELEMS is a list as descbribed in `org-clock-agg--parse-headline'."
|
||||||
(defvar org-clock-agg-groupby-functions nil
|
(defvar org-clock-agg-groupby-functions nil
|
||||||
"Group by functions for `org-clock-agg'.
|
"Group by functions for `org-clock-agg'.
|
||||||
|
|
||||||
This is an alist with function names as keys and alists with the
|
This is an alist with function names as keys and alists containing the
|
||||||
following keys as values:
|
following keys as values:
|
||||||
- `:function' - grouping function itself
|
- `:function' - the grouping function itself
|
||||||
- `:hidden' - whether to hide the function in the UI
|
- `:hidden' - whether to hide the function in the UI
|
||||||
- `:readable-name' - name to display in the UI
|
- `:readable-name' - name to display in the UI
|
||||||
- `:default-sort' - default sorting function to use for this group.
|
- `:default-sort' - default sorting function to use for this group (a
|
||||||
|
key of `org-clock-agg-sort-functions')
|
||||||
|
|
||||||
See `org-clock-agg-defgroupby' on how to define new grouping
|
See `org-clock-agg-defgroupby' on how to define new grouping
|
||||||
functions.")
|
functions.")
|
||||||
|
|
@ -380,7 +382,7 @@ functions.")
|
||||||
|
|
||||||
This is an alist with function names as keys and alists with the
|
This is an alist with function names as keys and alists with the
|
||||||
following keys as values:
|
following keys as values:
|
||||||
- `:function' - sorting function itself
|
- `:function' - the sorting function itself
|
||||||
- `:readable-name' - name to display in the UI.
|
- `:readable-name' - name to display in the UI.
|
||||||
|
|
||||||
See `org-clock-agg-defsort' on how to define new sorting
|
See `org-clock-agg-defsort' on how to define new sorting
|
||||||
|
|
@ -393,11 +395,12 @@ functions.")
|
||||||
BODY is a list of expressions. PARAMS is a list of symbols starting
|
BODY is a list of expressions. PARAMS is a list of symbols starting
|
||||||
with \":\".
|
with \":\".
|
||||||
|
|
||||||
E.g. if BODY is (:foo 1 :bar 2 something something), the usage is as follows:
|
E.g., if BODY is (:foo 1 :bar 2 something something), the usage is as
|
||||||
|
follows:
|
||||||
|
|
||||||
\(let \(foo bar)
|
\(let \(foo bar)
|
||||||
\(org-clock-agg--extract-params body :foo :bar)
|
\(org-clock-agg--extract-params body :foo :bar)
|
||||||
;; do something with foo and bar
|
;; do something with foo and bar
|
||||||
)"
|
)"
|
||||||
`(let ((body-wo-docstring (if (stringp (car-safe ,body)) (cdr body) ,body))
|
`(let ((body-wo-docstring (if (stringp (car-safe ,body)) (cdr body) ,body))
|
||||||
(docstring (when (stringp (car-safe ,body)) (car-safe ,body))))
|
(docstring (when (stringp (car-safe ,body)) (car-safe ,body))))
|
||||||
|
|
@ -417,19 +420,19 @@ E.g. if BODY is (:foo 1 :bar 2 something something), the usage is as follows:
|
||||||
(cl-defmacro org-clock-agg-defgroupby (name &body body)
|
(cl-defmacro org-clock-agg-defgroupby (name &body body)
|
||||||
"Define a grouping function for `org-clock-agg'.
|
"Define a grouping function for `org-clock-agg'.
|
||||||
|
|
||||||
NAME is the name of the function. BODY has the following variables bound:
|
NAME is the name of the function. BODY binds the following variables:
|
||||||
- `elem' - an alist as described in `org-clock-agg--parse-headline'
|
- `elem' - an alist as described in `org-clock-agg--parse-headline'
|
||||||
- `extra-params' - and alist with extra parameters. See
|
- `extra-params' - an alist with extra parameters. See
|
||||||
`org-clock-agg' on that.
|
`org-clock-agg' on that.
|
||||||
The function must return a list of strings, which are the group
|
|
||||||
names.
|
|
||||||
|
|
||||||
BODY can also contain the following keyword arguments:
|
The function must return a list of strings, which are the group names.
|
||||||
- `:readable-name' - function name for the UI. If not given, the name
|
|
||||||
of the function is used.
|
BODY can also include the following keyword arguments:
|
||||||
|
- `:readable-name' - function name for the UI. If not given, NAME is
|
||||||
|
used.
|
||||||
- `:hidden' - if non-nil, the function is not shown in the UI.
|
- `:hidden' - if non-nil, the function is not shown in the UI.
|
||||||
- `:default-sort' - if non-nil, the function is used as the default
|
- `:default-sort' - if non-nil, the function is used as the default
|
||||||
sort function."
|
sort function."
|
||||||
(declare (indent defun)
|
(declare (indent defun)
|
||||||
(doc-string 2))
|
(doc-string 2))
|
||||||
(let ((func-name (intern (concat "org-clock-agg--groupby-" (symbol-name name))))
|
(let ((func-name (intern (concat "org-clock-agg--groupby-" (symbol-name name))))
|
||||||
|
|
@ -453,13 +456,13 @@ sort function."
|
||||||
(cl-defmacro org-clock-agg-defsort (name &body body)
|
(cl-defmacro org-clock-agg-defsort (name &body body)
|
||||||
"Define a sorting function for `org-clock-agg'.
|
"Define a sorting function for `org-clock-agg'.
|
||||||
|
|
||||||
NAME is the name of the function. BODY has a variable `nodes' bound,
|
NAME is the name of the function. BODY binds a `nodes' variable,
|
||||||
which is a list of tree nodes as described in
|
which is a list of tree nodes as described in function
|
||||||
function `org-clock-agg--groupby'.
|
`org-clock-agg--groupby'.
|
||||||
|
|
||||||
BODY can also contain the following keyword arguments:
|
BODY can also contain the following keyword arguments:
|
||||||
- `:readable-name' - function name for the UI. If not given, the name
|
- `:readable-name' - function name for the UI. If not given, NAME is
|
||||||
of the function is used."
|
used."
|
||||||
(declare (indent defun)
|
(declare (indent defun)
|
||||||
(doc-string 2))
|
(doc-string 2))
|
||||||
(let ((func-name (intern (concat "org-clock-agg--sort-" (symbol-name name))))
|
(let ((func-name (intern (concat "org-clock-agg--sort-" (symbol-name name))))
|
||||||
|
|
@ -612,19 +615,20 @@ of the function is used."
|
||||||
#'> nodes))
|
#'> nodes))
|
||||||
|
|
||||||
(defun org-clock-agg--groupby-apply (alist groups elem)
|
(defun org-clock-agg--groupby-apply (alist groups elem)
|
||||||
"Recursively perform the grouping for `org-clock-agg'.
|
"Recursively perform grouping for `org-clock-agg'.
|
||||||
|
|
||||||
ALIST is the alist in which to store the results. GROUPS is a list of
|
ALIST is the alist used to store the results. GROUPS is a list of
|
||||||
groups for ELEM. GROUPS is a list with the following values:
|
groups for ELEM. GROUPS is a list with the following structure for
|
||||||
|
one group:
|
||||||
- group name
|
- group name
|
||||||
- parameters of the grouping function (as in the variable
|
- parameters of the grouping function (as in the variable
|
||||||
`org-clock-agg-groupby-functions')
|
`org-clock-agg-groupby-functions')
|
||||||
- name of the sorting function (keys of the variable
|
- name of the sorting function (keys of the variable
|
||||||
`org-clock-agg-sort-functions')
|
`org-clock-agg-sort-functions')
|
||||||
- sort order (t to reverse).
|
- sort order (t to reverse).
|
||||||
|
|
||||||
See the function `org-clock-agg--groupby' for the description of the
|
Refer to the function `org-clock-agg--groupby' for a description of
|
||||||
return value."
|
the return value."
|
||||||
(let* ((group-params (car groups))
|
(let* ((group-params (car groups))
|
||||||
(key (nth 0 group-params))
|
(key (nth 0 group-params))
|
||||||
(groupby (nth 1 group-params))
|
(groupby (nth 1 group-params))
|
||||||
|
|
@ -651,13 +655,14 @@ return value."
|
||||||
(defun org-clock-agg--add-ungrouped (tree)
|
(defun org-clock-agg--add-ungrouped (tree)
|
||||||
"Add \"Ungrouped\" nodes to TREE.
|
"Add \"Ungrouped\" nodes to TREE.
|
||||||
|
|
||||||
Such node is added to every node in TREE that has both `:elems',
|
This function adds an \"Ungrouped\" node to every node in TREE that
|
||||||
i.e. ungrouped elements, and `:children'. This can happen when only
|
contains both `:elems' (ungrouped elements) and `:children'. This
|
||||||
part of elements of the node was grouped by a grouping function.
|
can happen when only a portion of the elements of the node was grouped
|
||||||
|
by a grouping function.
|
||||||
|
|
||||||
Adding the \"Ungrouped\" node with all the ungrouped elements ensures that
|
The addition of the \"Ungrouped\" node with all the ungrouped elements
|
||||||
the total time spent in node equals the sum of the total time spent in
|
ensures that the total time spent in the node equals the sum of the
|
||||||
its children.
|
total time spent in its children.
|
||||||
|
|
||||||
TREE is a tree as returned by `org-clock-agg--groupby'."
|
TREE is a tree as returned by `org-clock-agg--groupby'."
|
||||||
(dolist (node tree)
|
(dolist (node tree)
|
||||||
|
|
@ -687,7 +692,7 @@ TREE is a tree as returned by `org-clock-agg--groupby'."
|
||||||
(defun org-clock-agg--groupby-postaggregate (tree &optional total-time parent-time)
|
(defun org-clock-agg--groupby-postaggregate (tree &optional total-time parent-time)
|
||||||
"Perform final aggregation calculations on TREE.
|
"Perform final aggregation calculations on TREE.
|
||||||
|
|
||||||
This function sets the following fields on each tree node:
|
Sets the following fields on each tree node:
|
||||||
- `:parent-share'
|
- `:parent-share'
|
||||||
- `:total-share'
|
- `:total-share'
|
||||||
|
|
||||||
|
|
@ -711,28 +716,29 @@ TOTAL-TIME and PARENT-TIME are recursive parameters."
|
||||||
|
|
||||||
ELEMS is a list as described in `org-clock-agg--parse-headline'.
|
ELEMS is a list as described in `org-clock-agg--parse-headline'.
|
||||||
GROUPBY-LIST is a list of keys of the variable
|
GROUPBY-LIST is a list of keys of the variable
|
||||||
`org-clock-agg-groupby-functions'. SORT-LIST is a list of keys of the variable
|
`org-clock-agg-groupby-functions'. SORT-LIST is a list of keys of
|
||||||
`org-clock-agg-sort-functions'. SORT-ORDER-LIST is a list of booleans
|
the variable `org-clock-agg-sort-functions'. SORT-ORDER-LIST is a
|
||||||
indicating whether to reverse the sort order for the corresponding key
|
list of booleans indicating whether to reverse the sort order for the
|
||||||
in SORT-LIST.
|
corresponding key in SORT-LIST.
|
||||||
|
|
||||||
The root group is always added to the beginning of GROUPBY-LIST.
|
The root group is always added to the beginning of GROUPBY-LIST.
|
||||||
|
|
||||||
EXTRA-PARAMS is an alist of extra parameters for the grouping
|
EXTRA-PARAMS is an alist of extra parameters for the grouping
|
||||||
functions. If `:add-ungrouped' is non-nil, add \"Ungrouped\" nodes to
|
functions. If `:add-ungrouped' is non-nil, \"Ungrouped\" nodes are
|
||||||
the tree. See `org-clock-agg' for more.
|
added to the tree. See `org-clock-agg' for details.
|
||||||
|
|
||||||
The return value is a tree of alists with the following keys:
|
The return value is a tree of alists with the following keys:
|
||||||
- `:total' - total seconds spent in group
|
- `:total' - total seconds spent in the group
|
||||||
- `:parent-share' - `:total' / time spent in parent node
|
- `:parent-share' - `:total' / time spent in the parent node
|
||||||
- `:total-share' - `:total' / time spent in the top-level node
|
- `:total-share' - `:total' / time spent in the top-level node
|
||||||
- `:groupby' - grouping function (as in the variable
|
- `:groupby' - grouping function (as in the variable
|
||||||
`org-clock-agg-groupby-functions')
|
`org-clock-agg-groupby-functions')
|
||||||
- `:children' - list of children tree nodes
|
- `:children' - list of children tree nodes
|
||||||
- `:sort-symbol' - key of the variable `org-clock-agg-sort-functions' used for
|
- `:sort-symbol' - key of the variable `org-clock-agg-sort-functions'
|
||||||
sorting
|
used for sorting
|
||||||
- `:sort-order' - if non-nil, reverse the sort order
|
- `:sort-order' - if non-nil, the sort order is reversed
|
||||||
- `:elems' - list of elements in the group, same form as ELEMS."
|
- `:elems' - list of elements in the group, in the same form as
|
||||||
|
ELEMS."
|
||||||
(let (tree)
|
(let (tree)
|
||||||
(dolist (elem elems)
|
(dolist (elem elems)
|
||||||
(let* ((group-symbols (cons 'root-group groupby-list))
|
(let* ((group-symbols (cons 'root-group groupby-list))
|
||||||
|
|
@ -872,7 +878,8 @@ TREE is a tree of alists as described in `org-clock-agg--groupby'."
|
||||||
"Render the date picker for the `org-clock-agg' buffer."
|
"Render the date picker for the `org-clock-agg' buffer."
|
||||||
(widget-create 'editable-field
|
(widget-create 'editable-field
|
||||||
:size 20
|
:size 20
|
||||||
:format (concat (propertize "Date from: " 'face 'widget-button) "%v ")
|
:format (concat (propertize "Date from: " 'face 'widget-button)
|
||||||
|
"%v ")
|
||||||
:value (let ((val (alist-get :from org-clock-agg--params)))
|
:value (let ((val (alist-get :from org-clock-agg--params)))
|
||||||
(if (numberp val)
|
(if (numberp val)
|
||||||
(number-to-string val)
|
(number-to-string val)
|
||||||
|
|
@ -902,10 +909,12 @@ TREE is a tree of alists as described in `org-clock-agg--groupby'."
|
||||||
(widget-create 'editable-list
|
(widget-create 'editable-list
|
||||||
:tag "Group by"
|
:tag "Group by"
|
||||||
:entry-format "%i %d %v"
|
:entry-format "%i %d %v"
|
||||||
:value (cl-loop for group-value in (alist-get :groupby org-clock-agg--params)
|
:value
|
||||||
for sort-value in (alist-get :sort org-clock-agg--params)
|
(cl-loop for group-value in (alist-get :groupby org-clock-agg--params)
|
||||||
for sort-order-value in (alist-get :sort-order org-clock-agg--params)
|
for sort-value in (alist-get :sort org-clock-agg--params)
|
||||||
collect (list group-value sort-value sort-order-value))
|
for sort-order-value in
|
||||||
|
(alist-get :sort-order org-clock-agg--params)
|
||||||
|
collect (list group-value sort-value sort-order-value))
|
||||||
:notify
|
:notify
|
||||||
(lambda (widget _changed-widget &optional _event)
|
(lambda (widget _changed-widget &optional _event)
|
||||||
(let ((group-value (mapcar #'car (widget-value widget)))
|
(let ((group-value (mapcar #'car (widget-value widget)))
|
||||||
|
|
@ -913,16 +922,18 @@ TREE is a tree of alists as described in `org-clock-agg--groupby'."
|
||||||
(sort-order-value (mapcar #'caddr (widget-value widget))))
|
(sort-order-value (mapcar #'caddr (widget-value widget))))
|
||||||
(setf (alist-get :groupby org-clock-agg--params) group-value)
|
(setf (alist-get :groupby org-clock-agg--params) group-value)
|
||||||
(setf (alist-get :sort org-clock-agg--params) sort-value)
|
(setf (alist-get :sort org-clock-agg--params) sort-value)
|
||||||
(setf (alist-get :sort-order org-clock-agg--params) sort-order-value)))
|
(setf (alist-get :sort-order org-clock-agg--params)
|
||||||
|
sort-order-value)))
|
||||||
`(group
|
`(group
|
||||||
:value (outline-path total)
|
:value (outline-path total)
|
||||||
(menu-choice
|
(menu-choice
|
||||||
:tag "Group"
|
:tag "Group"
|
||||||
:notify (lambda (widget _child &optional event)
|
:notify (lambda (widget _child &optional event)
|
||||||
(if-let* ((value (widget-value widget))
|
(if-let* ((value (widget-value widget))
|
||||||
(default-sort (alist-get
|
(default-sort
|
||||||
:default-sort
|
(alist-get
|
||||||
(alist-get value org-clock-agg-groupby-functions)))
|
:default-sort
|
||||||
|
(alist-get value org-clock-agg-groupby-functions)))
|
||||||
(parent (widget-get widget :parent)))
|
(parent (widget-get widget :parent)))
|
||||||
(widget-value-set parent (list value default-sort)))
|
(widget-value-set parent (list value default-sort)))
|
||||||
(widget-default-action widget event))
|
(widget-default-action widget event))
|
||||||
|
|
@ -930,12 +941,13 @@ TREE is a tree of alists as described in `org-clock-agg--groupby'."
|
||||||
org-clock-agg-groupby-functions
|
org-clock-agg-groupby-functions
|
||||||
(seq-filter (lambda (groupby)
|
(seq-filter (lambda (groupby)
|
||||||
(not (alist-get :hidden (cdr groupby)))))
|
(not (alist-get :hidden (cdr groupby)))))
|
||||||
(mapcar (lambda (groupby)
|
(mapcar
|
||||||
(let ((name (car groupby))
|
(lambda (groupby)
|
||||||
(readable-name (alist-get :readable-name (cdr groupby))))
|
(let ((name (car groupby))
|
||||||
`(item :tag ,readable-name
|
(readable-name (alist-get :readable-name (cdr groupby))))
|
||||||
:value ,name
|
`(item :tag ,readable-name
|
||||||
:menu-tag ,readable-name))))))
|
:value ,name
|
||||||
|
:menu-tag ,readable-name))))))
|
||||||
(menu-choice
|
(menu-choice
|
||||||
:tag "Order"
|
:tag "Order"
|
||||||
,@(mapcar
|
,@(mapcar
|
||||||
|
|
@ -1186,42 +1198,44 @@ return value description."
|
||||||
(defun org-clock-agg (from to files groupby sort sort-order extra-params)
|
(defun org-clock-agg (from to files groupby sort sort-order extra-params)
|
||||||
"Aggregate org-clock data.
|
"Aggregate org-clock data.
|
||||||
|
|
||||||
The function creates an interactive buffer to configure the
|
The function creates an interactive buffer for configuring the
|
||||||
aggregation and display the results. If functions is called
|
aggregation and displaying the results. When called
|
||||||
non-interactively, intials parameters can be passed as arguments.
|
non-interactively, initial parameters can be passed as arguments.
|
||||||
|
|
||||||
Use `org-clock-agg-exec' if you want to retrive the results
|
Use `org-clock-agg-exec' to retrieve the results without the
|
||||||
without the interactive buffer.
|
interactive buffer.
|
||||||
|
|
||||||
FROM and TO define the time range. Both are `org-ql' time predicates,
|
FROM and TO define the time range. Both are either a relative number
|
||||||
that is a number of days (e.g. -7 for the last week) or a date
|
of days, or a date string parseable by `parse-time-string', with or
|
||||||
parseable by `parse-time-string'.
|
without the time part. See `org-clock-agg--normalize-time-predicate'
|
||||||
|
for details.
|
||||||
|
|
||||||
FILES is either `org-agenda', a key of `org-clock-agg-files-preset' (in
|
FILES is either `org-agenda', a key from `org-clock-agg-files-preset'
|
||||||
which case the value of that variable is used) or a list of files.
|
\(in which case the value of that variable is used), or a list of
|
||||||
|
file paths.
|
||||||
|
|
||||||
GROUPBY is a list of keys of `org-clock-agg-groupby-functions'. Each
|
GROUPBY is a list of keys from `org-clock-agg-groupby-functions'.
|
||||||
function returns a list of groups for each entry; the result is a
|
Each function returns a list of groups for each entry; the result
|
||||||
tree. SORT is a list of keys of `org-clock-agg-sort-functions' that
|
forms a tree. SORT is a list of keys from
|
||||||
has to be the same length as GROUPBY. Nth entry is the SORT list
|
`org-clock-agg-sort-functions', and its length must match GROUPBY.
|
||||||
defines the sort logic for the results of the Nth GROUPBY function.
|
The Nth entry in SORT defines the sorting logic for the results of the
|
||||||
|
Nth GROUPBY function.
|
||||||
|
|
||||||
SORT-ORDER has to be the same length as SORT. If Nth entry is non-nil,
|
SORT-ORDER must be of the same length as SORT. If the Nth entry is
|
||||||
the sorting is reversed.
|
non-nil, the sorting is reversed.
|
||||||
|
|
||||||
EXTRA-PARAMS is an alist of \"extra parameters\". Possible keys are
|
EXTRA-PARAMS is an alist of 'extra parameters.' Possible keys are
|
||||||
defined by `org-clock-agg--extra-params-default' and
|
defined by `org-clock-agg--extra-params-default' and
|
||||||
`org-clock-agg-extra-params'. The built-in parameters are:
|
`org-clock-agg-extra-params'. Built-in parameters include:
|
||||||
- `:show-elems' - whether to show raw elements for each group in the
|
- `:show-elems' - whether to display raw elements for each group in
|
||||||
buffer. An \"element\" is one org-clock record.
|
the buffer (an 'element' represents one org-clock record).
|
||||||
- `:add-ungrouped' - whether to add the \"Ungrouped\" group to the
|
- `:add-ungrouped' - whether to add the 'Ungrouped' group to the
|
||||||
results.
|
results.
|
||||||
|
|
||||||
`org-clock-agg-extra-params' can be used to define new parameters.
|
`org-clock-agg-extra-params' can define new parameters, intended for
|
||||||
This is meant to be used by custom aggregation functions to control
|
custom aggregation functions to control their behavior at runtime.
|
||||||
their behavior in runtime.
|
|
||||||
|
|
||||||
See the mentioned variables for and the interactive buffer for the
|
Refer to the mentioned variables and the interactive buffer for
|
||||||
available group and sort functions; use `org-clock-agg-defgroupby' and
|
available group and sort functions; use `org-clock-agg-defgroupby' and
|
||||||
`org-clock-agg-defsort' to define new ones."
|
`org-clock-agg-defsort' to define new ones."
|
||||||
(interactive (list -7 0 'org-agenda nil nil nil nil))
|
(interactive (list -7 0 'org-agenda nil nil nil nil))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue