From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Eric Schulte" Subject: Re: Re: orgmode and physical fitness training Date: Thu, 06 Nov 2008 08:56:42 -0800 Message-ID: <87abccu71x.fsf@gmail.com> References: <1223994514.15613.17.camel@monad.lab> <87abceez2z.fsf@abc.se> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ky8Dz-0006Vk-KN for emacs-orgmode@gnu.org; Thu, 06 Nov 2008 12:00:51 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ky8Dx-0006UA-Dr for emacs-orgmode@gnu.org; Thu, 06 Nov 2008 12:00:50 -0500 Received: from [199.232.76.173] (port=43149 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ky8Dw-0006Tq-D3 for emacs-orgmode@gnu.org; Thu, 06 Nov 2008 12:00:48 -0500 In-Reply-To: <87abceez2z.fsf@abc.se> (Mikael Fornius's message of "Wed, 05 Nov 2008 20:45:40 +0100") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Mikael Fornius Cc: emacs-orgmode@gnu.org, David O'Toole --=-=-= Mikael Fornius writes: > David O'Toole writes: > >> Does anyone else here use org-mode for fitness and/or health tracking? [...] > Lately I have been thinking of and trying to implement a true org-mode > running diary. Which means to use the org-mode file as raw-data file > (properties) instead of my parallell sexp-assoc-list-elisp-data-file. > > I tried column mode but it is far too slow for 300 headings and the > calculations possible is only sums but I need much more. > Hi Mikael, I ran into a very similar issue with column view lately while trying to use org-mode to collect experimental results. I created the attached file, which can be used to collect data from properties in a manner similar to column view, but using a simpler method meant only for table display, rather than column viewing, and allowing for the application of general elisp to the values before they are dumped into the table. I think it would work in your case as well. I applied it to the data you posted with the following results. The mechanics are working, but it could use some display cleaning. The file `org-collector.el' is attached --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=org-collector.el Content-Transfer-Encoding: quoted-printable ;;; org-collector --- collect properties into tables ;; ;;; Eric Schulte ;; ;;; Comments: ;; ;; pass in an alist of columns, each column can be either a single ;; property or a function which takes column as arguments. Specify a ;; column ;;=20 (require 'org) (require 'org-table) (defun and-rest (list) (if (listp list) (if (> (length list) 1) (and (car list) (and-rest (cdr list))) (car list)) list)) (put 'org-collector-error 'error-conditions '(error column-prop-error org-collector-error)) (defun org-read-prop (prop) "Convert the string property PROP to a number if appropriate. Otherwise if prop looks like a list (meaning it starts with a '(') then read it as lisp, otherwise return it unmodified as a string." (if (stringp prop) (if prop (let ((out (string-to-number prop))) (if (equal out 0) (if (or (equal "(" (substring prop 0 1)) (equal "'" (substring prop 0 1))) (read prop) (if (string-match "^\\(+0\\|-0\\|0\\)$" prop) 0 (progn (set-text-properties 0 (length prop) nil prop) prop))) out)) nil) prop)) (defun org-dblock-write:propview (params) "collect the column specification from the #+cols line preceeding the dblock, then update the contents of the dblock." (interactive) (condition-case er (let ((cols (plist-get params :cols)) id table) (save-excursion (when (setq id (plist-get params :id)) (cond ((not id) nil) ((eq id 'global) (goto-char (point-min))) ((eq id 'local) nil) ((setq idpos (org-find-entry-with-id id)) (goto-char idpos)) (t (error "Cannot find entry with :ID: %s" id)))) (org-narrow-to-subtree) (setq table (org-propview-to-table (org-propview-collect cols))) (widen)) (insert table) (org-cycle)) (org-collector-error (widen) (error "%s" er)) (error (widen) (error "%s" er)))) (defun org-propview-collect (cols) (interactive) ;; collect the properties from every header (let* ((header-props (org-map-entries (quote (cons (cons "ITEM" (org-get-= heading)) (org-entry-properties))))) ;; collect all property names (prop-names (mapcar 'intern (delete-dups (apply 'append (mapcar (lambda (header) (mapcar 'car header)) header-props)))))) ;; (message (format "header-props=3D%S" header-props)) ;; (message (format "prop-names=3D%S" prop-names)) (append (list ;; create an output list of the headers for each output col (mapcar (lambda (el) (format "%S" el)) cols) 'hline) (mapcar ;; for each header's entries (lambda (props) (mapcar ;; for each col (lambda (col) (or ;; if col is a symbol and it's present return it's value (and (symbolp col) (let ((val (cdr (assoc (symbol-name col) props)))) (if val (org-read-prop val)))) ;; if col is a list, and everything in it's cdr is present, ;; then evaluate it as a function (and (listp col) (let ((vals (mapcar (lambda (el) (if (memq el prop-names) (org-read-prop (cdr (assoc (symbol-name el) props))) el)) (cdr col)))) (message (format "vals-%S" vals)) (condition-case col-er (and (and-rest vals) (org-read-prop (eval (cons (car col) vals)))) (error (signal 'org-collector-error (list (format "%S while processing: %S" col-er col))))) )) :na)) ;; else return an appropriate default cols)) header-props)))) (defun org-propview-to-table (results) ;; (message (format "cols:%S" cols)) (orgtbl-to-orgtbl (mapcar (lambda (row) (if (equal row 'hline) 'hline (mapcar (lambda (el) (format "%S" el)) row))) (delq nil results)) '())) (provide 'org-collector) ;;; org-collector ends here --=-=-= and is available at http://github.com/eschulte/org-contrib/tree/master Best -- Eric ** exercise #+BEGIN: propview :id "nov" :cols (ITEM TIME DISTANCE (/ DISTANCE TIME) HEARTRATE) | "ITEM" | "TIME" | "DISTANCE" | "(/ DISTANCE TIME)" | "HEARTRATE" | |------------------------------------------------------------+--------+------------+---------------------+-------------| | "<2008-11-01 sat> :running:hill:" | 20 | 3.0 | 0.15 | 169 | | "<2008-11-02 sun> :skiing:alpine:" | 27 | 4.0 | 0.14814814814814814 | 198 | | "<2008-11-04 tue> :running:lake:" | 27 | 6.0 | 0.2222222222222222 | 169 | | | | | | | #+END: *** 2008-11 :november: :PROPERTIES: :ID: nov :END: **** <2008-11-01 sat> :running:hill: :PROPERTIES: :TIME: 20:08 :DISTANCE: 3.0 :HEARTRATE: 169 :MAXHEARTRATE: 183 :PACE: 4:36 :SHAPEINDEX: -8.4% :WEATHER: +5 cloudy :CALORIES: 370 :SHOES: nb858-1 :STATFLAG: t :END: **** <2008-11-02 sun> :skiing:alpine: :PROPERTIES: :TIME: 27:34 :DISTANCE: 4.0 :HEARTRATE: 198 :MAXHEARTRATE: 145 :PACE: 4:36 :SHAPEINDEX: -8.4% :WEATHER: +5 cloudy :CALORIES: 370 :SHOES: nb858-1 :STATFLAG: t :END: **** <2008-11-04 tue> :running:lake: :PROPERTIES: :TIME: 27:34 :DISTANCE: 6.0 :HEARTRATE: 169 :MAXHEARTRATE: 183 :PACE: 4:36 :SHAPEINDEX: -8.4% :WEATHER: +5 cloudy :CALORIES: 370 :SHOES: nb858-1 :STATFLAG: t :END: --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-orgmode mailing list Remember: use `Reply All' to send replies to the list. Emacs-orgmode@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-orgmode --=-=-=--