summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2016-02-17 15:16:22 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2016-02-17 22:49:19 +0100
commitaa2db034a0edbc60f006e5be60faf9d2ca68575d (patch)
tree888f6fc675a379b5d050467ad477e2b144210e0d
parent04c405660dc53d686c9eb95fe599159061c1bb85 (diff)
downloadorg-mode-aa2db034a0edbc60f006e5be60faf9d2ca68575d.tar.gz
org-colview: Fix age related summary
* lisp/org-colview.el (org-columns-time): Rename to... (org--columns-time): ... this. (org-columns--fractional-duration-re): New variable. (org-columns-edit-value): (org-columns): (org-columns-compute-all): (org-agenda-columns): Use new variable. (org-columns-compile-map): Remove unneeded "calc" attribute. (org-columns-number-to-string): (org-columns-string-to-number): Fix ages set as a duration (e.g., "1d 12h"). Compare ages as seconds, not number of days. * doc/org.texi (Column attributes): Document syntax for "age".
-rw-r--r--doc/org.texi7
-rw-r--r--lisp/org-colview.el161
2 files changed, 84 insertions, 84 deletions
diff --git a/doc/org.texi b/doc/org.texi
index ed84836..1365b06 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -5636,7 +5636,12 @@ optional. The individual parts have the following meaning:
@{:min@} @r{Smallest time value in column.}
@{:max@} @r{Largest time value.}
@{:mean@} @r{Arithmetic mean of time values.}
- @{@@min@} @r{Minimum age (in days/hours/mins/seconds).}
+ @{@@min@} @r{Minimum age (in
+ days/hours/mins/seconds@footnote{Days, hours, minutes and
+ seconds are represented with, respectively, @samp{d},
+ @samp{h}, @samp{m} and @samp{s} suffixes, e.g., @samp{13h
+ 10s}. Alternatively, an age can be defined as a duration
+ since a given time-stamp (@pxref{Timestamps}).}).}
@{@@max@} @r{Maximum age (in days/hours/mins/seconds).}
@{@@mean@} @r{Arithmetic mean of ages (in days/hours/mins/seconds).}
@{est+@} @r{Add @samp{low-high} estimates.}
diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 8fe35df..de5c0d9 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -60,7 +60,8 @@ or nil if the normal value should be used."
(defvar org-columns-overlays nil
"Holds the list of current column overlays.")
-(defvar org-columns-time)
+(defvar org-columns--time 0.0
+ "Number of seconds since the epoch, as a floating point number.")
(defvar-local org-columns-current-fmt nil
"Local variable, holds the currently active column format.")
@@ -74,6 +75,10 @@ This is the compiled version of the format.")
(defvar org-columns-top-level-marker (make-marker)
"Points to the position where current columns region starts.")
+(defconst org-columns--fractional-duration-re
+ (concat "[0-9.]+ *" (regexp-opt (mapcar #'car org-effort-durations)))
+ "Regexp matching a duration.")
+
(defvar org-columns-map (make-sparse-keymap)
"The keymap valid in column display.")
@@ -471,7 +476,7 @@ Where possible, use the standard interface for changing this line."
(bol (point-at-bol)) (eol (point-at-eol))
(pom (or (get-text-property bol 'org-hd-marker)
(point))) ; keep despite of compiler waring
- (org-columns-time (time-to-number-of-days (current-time)))
+ (org-columns--time (float-time (current-time)))
nval eval allowed)
(cond
((equal key "CLOCKSUM")
@@ -718,39 +723,39 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column format."
(org-columns-goto-top-level)
;; Initialize `org-columns-current-fmt' and
;; `org-columns-current-fmt-compiled'.
- (let ((org-columns-time (time-to-number-of-days (current-time))))
- (org-columns-get-format columns-fmt-string))
- (unless org-columns-inhibit-recalculation (org-columns-compute-all))
- (save-excursion
- (save-restriction
- (when (and (not global) (org-at-heading-p))
- (narrow-to-region (point) (org-end-of-subtree t t)))
- (when (assoc-string "CLOCKSUM" org-columns-current-fmt-compiled t)
- (org-clock-sum))
- (when (assoc-string "CLOCKSUM_T" org-columns-current-fmt-compiled t)
- (org-clock-sum-today))
- (let ((cache
- ;; Collect contents of columns ahead of time so as to
- ;; compute their maximum width.
- (org-map-entries
- (lambda () (cons (point) (org-columns--collect-values)))
- nil nil (and org-columns-skip-archived-trees 'archive))))
- (when cache
- (setq-local org-columns-current-maxwidths
- (org-columns--autowidth-alist cache))
- (org-columns--display-here-title)
- (when (setq-local org-columns-flyspell-was-active
- (org-bound-and-true-p flyspell-mode))
- (flyspell-mode 0))
- (unless (local-variable-p 'org-colview-initial-truncate-line-value)
- (setq-local org-colview-initial-truncate-line-value
- truncate-lines))
- (setq truncate-lines t)
- (dolist (entry cache)
- (goto-char (car entry))
- (org-columns--display-here (cdr entry))))))))
-
-(defvar org-columns-compile-map
+ (let ((org-columns--time (float-time (current-time))))
+ (org-columns-get-format columns-fmt-string)
+ (unless org-columns-inhibit-recalculation (org-columns-compute-all))
+ (save-excursion
+ (save-restriction
+ (when (and (not global) (org-at-heading-p))
+ (narrow-to-region (point) (org-end-of-subtree t t)))
+ (when (assoc-string "CLOCKSUM" org-columns-current-fmt-compiled t)
+ (org-clock-sum))
+ (when (assoc-string "CLOCKSUM_T" org-columns-current-fmt-compiled t)
+ (org-clock-sum-today))
+ (let ((cache
+ ;; Collect contents of columns ahead of time so as to
+ ;; compute their maximum width.
+ (org-map-entries
+ (lambda () (cons (point) (org-columns--collect-values)))
+ nil nil (and org-columns-skip-archived-trees 'archive))))
+ (when cache
+ (setq-local org-columns-current-maxwidths
+ (org-columns--autowidth-alist cache))
+ (org-columns--display-here-title)
+ (when (setq-local org-columns-flyspell-was-active
+ (org-bound-and-true-p flyspell-mode))
+ (flyspell-mode 0))
+ (unless (local-variable-p 'org-colview-initial-truncate-line-value)
+ (setq-local org-colview-initial-truncate-line-value
+ truncate-lines))
+ (setq truncate-lines t)
+ (dolist (entry cache)
+ (goto-char (car entry))
+ (org-columns--display-here (cdr entry)))))))))
+
+(defconst org-columns-compile-map
'(("none" none +)
(":" add_times +)
("+" add_numbers +)
@@ -760,17 +765,13 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column format."
("X%" checkbox-percent +)
("max" max_numbers max)
("min" min_numbers min)
- ("mean" mean_numbers
- (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
+ ("mean" mean_numbers (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
(":max" max_times max)
(":min" min_times min)
- (":mean" mean_times
- (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
- ("@min" min_age min (lambda (x) (- org-columns-time x)))
- ("@max" max_age max (lambda (x) (- org-columns-time x)))
- ("@mean" mean_age
- (lambda (&rest x) (/ (apply '+ x) (float (length x))))
- (lambda (x) (- org-columns-time x)))
+ (":mean" mean_times (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
+ ("@min" min_age min)
+ ("@max" max_age max)
+ ("@mean" mean_age (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
("est+" estimate org-estimate-combine))
"Operator <-> format,function,calc map.
Used to compile/uncompile columns format and completing read in
@@ -916,7 +917,7 @@ display, or in the #+COLUMNS line of the current buffer."
"Compute all columns that have operators defined."
(org-with-silent-modifications
(remove-text-properties (point-min) (point-max) '(org-summaries t)))
- (let ((org-columns-time (time-to-number-of-days (current-time))))
+ (let ((org-columns--time (float-time (current-time))))
(dolist (spec org-columns-current-fmt-compiled)
(pcase spec
(`(,property ,_ ,_ ,operator . ,_)
@@ -1062,46 +1063,40 @@ PRINTF, when non-nil, is a format string used to print N."
(printf (format printf n))
((eq fmt 'currency) (format "%.2f" n))
((memq fmt '(min_age max_age mean_age))
- (let* ((days (floor n))
- (frac-hours (* 24 (- n days)))
- (hours (floor frac-hours))
- (minutes (floor (* 60 (- frac-hours hours))))
- (seconds (floor (* 60 (- (* 60 (- frac-hours hours)) minutes)))))
- (format "%dd %02dh %02dm %02ds" days hours minutes seconds)))
+ (format-seconds "%dd %.2hh %mm %ss" n))
(t (number-to-string n))))
(defun org-columns-string-to-number (s fmt)
- "Convert a column value to a number that can be used for column computing."
- (if s
- (cond
- ((memq fmt '(min_age max_age mean_age))
- (cond ((string= s "") org-columns-time)
- ((string-match
- "\\([0-9]+\\)d \\([0-9]+\\)h \\([0-9]+\\)m \\([0-9]+\\)s"
- s)
- (+ (* 60 (+ (* 60 (+ (* 24 (string-to-number (match-string 1 s)))
- (string-to-number (match-string 2 s))))
- (string-to-number (match-string 3 s))))
- (string-to-number (match-string 4 s))))
- (t (time-to-number-of-days (apply 'encode-time
- (org-parse-time-string s t))))))
- ((string-match ":" s)
- (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
- (while l
- (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
- sum))
- ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
- (if (equal s "[X]") 1. 0.000001))
- ((memq fmt '(estimate)) (org-string-to-estimate s))
- ((string-match (concat "\\([0-9.]+\\) *\\("
- (regexp-opt (mapcar 'car org-effort-durations))
- "\\)") s)
- (setq s (concat "0:" (org-duration-string-to-minutes s t)))
- (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
- (while l
- (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
- sum))
- (t (string-to-number s)))))
+ "Convert a column value S to a number.
+FMT is a symbol describing the summary type."
+ (cond
+ ((not s) nil)
+ ((memq fmt '(min_age max_age mean_age))
+ (cond
+ ((string= s "") org-columns--time)
+ ((string-match "\\`\\(?: *\\([0-9]+\\)d\\)?\\(?: *\\([0-9]+\\)h\\)?\
+\\(?: *\\([0-9]+\\)m\\)?\\(?: *\\([0-9]+\\)s\\)?\\'" s)
+ (let ((d (if (match-end 1) (string-to-number (match-string 1 s)) 0))
+ (h (if (match-end 2) (string-to-number (match-string 2 s)) 0))
+ (m (if (match-end 3) (string-to-number (match-string 3 s)) 0))
+ (s (if (match-end 4) (string-to-number (match-string 4 s)) 0)))
+ (+ (* 60 (+ (* 60 (+ (* 24 d) h)) m)) s)))
+ (t
+ (- org-columns--time
+ (float-time (apply #'encode-time (org-parse-time-string s)))))))
+ ((string-match-p ":" s) ;Interpret HH:MM:SS.
+ (let ((sum 0.0))
+ (dolist (n (nreverse (split-string s ":")) sum)
+ (setq sum (+ (string-to-number n) (/ sum 60))))))
+ ((memq fmt '(checkbox checkbox-n-of-m checkbox-percent))
+ (if (equal s "[X]") 1. 0.000001))
+ ((eq fmt 'estimate) (org-string-to-estimate s))
+ ((string-match-p org-columns--fractional-duration-re s)
+ (let ((s (concat "0:" (org-duration-string-to-minutes s t)))
+ (sum 0.0))
+ (dolist (n (nreverse (split-string s ":")) sum)
+ (setq sum (+ (string-to-number n) (/ sum 60))))))
+ (t (string-to-number s))))
(defun org-columns-uncompile-format (cfmt)
"Turn the compiled columns format back into a string representation."
@@ -1365,7 +1360,7 @@ PARAMS is a property list of parameters:
(interactive)
(org-columns-remove-overlays)
(move-marker org-columns-begin-marker (point))
- (let ((org-columns-time (time-to-number-of-days (current-time)))
+ (let ((org-columns--time (float-time (current-time)))
(fmt
(cond
((org-bound-and-true-p org-agenda-overriding-columns-format))