emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Mikael Fornius <mfo@abc.se>
To: emacs-orgmode@gnu.org
Subject: colview min/mean/max
Date: Wed, 20 May 2009 13:15:49 +0200	[thread overview]
Message-ID: <87ab58owii.fsf@abc.se> (raw)

[-- Attachment #1: Type: text/plain, Size: 780 bytes --]

I have changed my org-colview.el so that it is possible to get min, mean
and max values calculated instead of just sums in the table summaries.

I use orgmode as a dayplanner and physical exercise diary.

My exercise data is stored as properties in a year->month->day tree and
it is very nice for med to get an overview of my fastest run or average
heartrate over time with columnview. 

If you developers like it I can make the same changes to
org-colview-xemacs.el and document it in the manual for use in future

New column operators: min, mean, max, :min, :mean, :max. When prefixed
with ':' use timevalue output format.

Example (I measure speed in min/km):

#+COLUMNS:  %DISTANCE{+;%.1f} %HEARTRATE{mean;%.1f} %MAXHEARTRATE{max} %SPEED{:min} 

Here is the patch:

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: min/mean/max --]
[-- Type: text/x-patch, Size: 5800 bytes --]

diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 377343d..04bfeb0 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -869,12 +869,13 @@ Don't set this, this is meant for dynamic scoping.")
   (let* ((re (concat "^" outline-regexp))
 	 (lmax 30) ; Does anyone use deeper levels???
-	 (lsum (make-vector lmax 0))
+	 (lvals (make-vector lmax nil))
 	 (lflag (make-vector lmax nil))
 	 (level 0)
 	 (ass (assoc property org-columns-current-fmt-compiled))
 	 (format (nth 4 ass))
 	 (printf (nth 5 ass))
+	 (fun (nth 6 ass))
 	 (beg org-columns-top-level-marker)
 	 last-level val valflag flag end sumpos sum-alist sum str str1 useval)
@@ -892,7 +893,7 @@ Don't set this, this is meant for dynamic scoping.")
 	 ((< level last-level)
 	  ;; put the sum of lower levels here as a property
-	  (setq sum (aref lsum last-level)   ; current sum
+	  (setq sum (apply fun (aref lvals last-level))
 		flag (aref lflag last-level) ; any valid entries from children?
 		str (org-columns-number-to-string sum format printf)
 		str1 (org-add-props (copy-sequence str) nil 'org-computed t 'face 'bold)
@@ -908,18 +909,18 @@ Don't set this, this is meant for dynamic scoping.")
 	    (org-entry-put nil property (if flag str val)))
 	  ;; add current to current  level accumulator
 	  (when (or flag valflag)
-	    (aset lsum level (+ (aref lsum level)
-				(if flag sum (org-column-string-to-number
-					      (if flag str val) format))))
+	    (push (if flag sum
+		    (org-column-string-to-number (if flag str val) format))
+		  (aref lvals level))
 	    (aset lflag level t))
 	  ;; clear accumulators for deeper levels
 	  (loop for l from (1+ level) to (1- lmax) do
-		(aset lsum l 0)
+		(aset lvals l nil)
 		(aset lflag l nil)))
 	 ((>= level last-level)
 	  ;; add what we have here to the accumulator for this level
-	  (aset lsum level (+ (aref lsum level)
-			      (org-column-string-to-number (or val "0") format)))
+	  (push (org-column-string-to-number (or val "0") format)
+		(aref lvals level))
 	  (and valflag (aset lflag level t)))
 	 (t (error "This should not happen")))))))
@@ -990,23 +991,34 @@ Don't set this, this is meant for dynamic scoping.")
     (if (equal s "[X]") 1. 0.000001))
    (t (string-to-number s))))
+(defvar org-columns-compile-map
+  '((":"     add_times         +) 
+    ("+"     add_numbers       +) 
+    ("$"     currency          +) 
+    ("X"     checkbox          +) 
+    ("X/"    checkbox-n-of-m   +) 
+    ("X%"    checkbox-percent  +)
+    ("max"   add_numbers       max)               
+    ("min"   add_numbers       min)              
+    ("mean"  add_numbers       (lambda (&rest x) (/ (apply '+ x) (float (length x)))))
+    (":max"  add_times         max)               
+    (":min"  add_times         min)              
+    (":mean" add_times         (lambda (&rest x) (/ (apply '+ x) (float (length x))))))
+  "Operator <-> format,fuction map.")
 (defun org-columns-uncompile-format (cfmt)
   "Turn the compiled columns format back into a string representation."
-  (let ((rtn "") e s prop title op width fmt printf)
+  (let ((rtn "") e s prop title op op-match width fmt printf)
     (while (setq e (pop cfmt))
       (setq prop (car e)
 	    title (nth 1 e)
 	    width (nth 2 e)
 	    op (nth 3 e)
 	    fmt (nth 4 e)
-	    printf (nth 5 e))
-      (cond
-       ((eq fmt 'add_times) (setq op ":"))
-       ((eq fmt 'checkbox) (setq op "X"))
-       ((eq fmt 'checkbox-n-of-m) (setq op "X/"))
-       ((eq fmt 'checkbox-percent) (setq op "X%"))
-       ((eq fmt 'add_numbers) (setq op "+"))
-       ((eq fmt 'currency) (setq op "$")))
+	    printf (nth 5 e)
+	    fun (nth 6 e))
+      (when (setq op-match (rassoc (list fmt fun) org-columns-compile-map))
+	(setq op (car op-match)))
       (if (and op printf) (setq op (concat op ";" printf)))
       (if (equal title prop) (setq title nil))
       (setq s (concat "%" (if width (number-to-string width))
@@ -1025,8 +1037,9 @@ title        the title field for the columns
 width        the column width in characters, can be nil for automatic
 operator     the operator if any
 format       the output format for computed results, derived from operator
-printf       a printf format for computed values"
-  (let ((start 0) width prop title op f printf)
+printf       a printf format for computed values
+fun          the lisp function to compute values, derived from operator"
+  (let ((start 0) width prop title op op-match f printf fun)
     (setq org-columns-current-fmt-compiled nil)
     (while (string-match
 	    (org-re "%\\([0-9]+\\)?\\([[:alnum:]_-]+\\)\\(?:(\\([^)]+\\))\\)?\\(?:{\\([^}]+\\)}\\)?\\s-*")
@@ -1037,20 +1050,16 @@ printf       a printf format for computed values"
 	    title (or (match-string 3 fmt) prop)
 	    op (match-string 4 fmt)
 	    f nil
-	    printf nil)
+	    printf nil
+	    fun '+) 
       (if width (setq width (string-to-number width)))
       (when (and op (string-match ";" op))
 	(setq printf (substring op (match-end 0))
 	      op (substring op 0 (match-beginning 0))))
-      (cond
-       ((equal op "+")  (setq f 'add_numbers))
-       ((equal op "$")  (setq f 'currency))
-       ((equal op ":")  (setq f 'add_times))
-       ((equal op "X")  (setq f 'checkbox))
-       ((equal op "X/") (setq f 'checkbox-n-of-m))
-       ((equal op "X%") (setq f 'checkbox-percent))
-       )
-      (push (list prop title width op f printf) org-columns-current-fmt-compiled))
+      (when (setq op-match (assoc op org-columns-compile-map))
+	(setq f (cadr op-match)
+	      fun (caddr op-match)))
+      (push (list prop title width op f printf fun) org-columns-current-fmt-compiled))
     (setq org-columns-current-fmt-compiled
 	  (nreverse org-columns-current-fmt-compiled))))

[-- Attachment #3: Type: text/plain, Size: 46 bytes --]

Thanks for a great mode!

Mikael Fornius

[-- Attachment #4: Type: text/plain, Size: 204 bytes --]

Emacs-orgmode mailing list
Remember: use `Reply All' to send replies to the list.

             reply	other threads:[~2009-05-20 11:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-20 11:15 Mikael Fornius [this message]
2009-05-20 13:21 ` colview min/mean/max Mikael Fornius
2009-05-20 13:47   ` Carsten Dominik
2009-05-20 22:42     ` Mikael Fornius
2009-05-21  6:01       ` Carsten Dominik
2009-05-21  7:23         ` Mikael Fornius
2009-05-21  8:48           ` Carsten Dominik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ab58owii.fsf@abc.se \
    --to=mfo@abc.se \
    --cc=emacs-orgmode@gnu.org \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).