emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: <news@aleblanc.cotse.net>
To: emacs-orgmode@gnu.org
Subject: Re: SOLVED: elisp formulas in column view (without converting to tables)
Date: Mon, 16 Mar 2009 20:15:13 +0000	[thread overview]
Message-ID: <87tz5tql66.fsf@it.com> (raw)
In-Reply-To: 87sklh0z18.fsf@it.com

<news@aleblanc.cotse.net> writes:

> Hi,
>    I have rewritten the org-columns-compute function to allow elisp
>    formulas in column view.
>    It allows you to specify how to accumulate values from child headers,
>    and how to specify the value for the current header, based on other
>    columns.

Have since discovered that my new version doesn't work with checkbox
formulas. The solution is to use the old version of org-columns-compute
if the formula is not an elisp formula. Rename the old function to
org-columns-compute-orig, and then use this code for
org-columns-compute:

(defun org-columns-compute (property)
  "Sum the values of property PROPERTY hierarchically, for the entire buffer."
  (interactive)
  (let* ((re (concat "^" outline-regexp))
	 (lmax 30) ; Does anyone use deeper levels???
	 (level 0)
	 (ass (assoc property org-columns-current-fmt-compiled))
	 ;; parse elisp form if there is one
	 (form (nth 3 ass))
	 (uselisp (and (> (length form) 1)
		       (or (equal "(" (substring form 0 1)) 
			   (equal "(" (substring form 1 2)))))
	 (form (if uselisp
		   (replace-regexp-in-string 
		    "\$\\([^()\" 	]+\\)" 
		    "(string-to-number (or (org-entry-get nil \"\\1\") \"0\"))" 
		    (nth 3 ass) t)))
	 ;; vector to hold running totals for each level
	 (lsum (make-vector lmax (if uselisp nil 0)))
	 (format (nth 4 ass))
	 (printf (nth 5 ass))
	 (beg org-columns-top-level-marker)
	 last-level val valflag end sumpos sum-alist str str1 useval prevtotal curtotal newvals)
    (if uselisp
	(save-excursion
	  ;; Find the region to compute
	  (goto-char beg)
	  (setq end (condition-case nil (org-end-of-subtree t) (error (point-max))))
	  (goto-char end)
	  ;; Walk the tree from the back and do the computations
	  (while (re-search-backward re beg t)
	    (setq sumpos (match-beginning 0)
		  last-level level
		  level (org-outline-level)
		  ;; total from children, or nil if there were none
		  prevtotal (if (< level last-level) (aref lsum last-level) nil)
		  ;; total at this level
		  curtotal (aref lsum level)
		  ;; current property value as string
		  val (org-entry-get nil property)
		  ;; is it non-empty?
		  valflag (and val (string-match "\\S-" val))
		  ;; current property value as number (or nil if empty)
		  curval (if valflag (org-column-string-to-number val format) nil)
		  ;; get values to replace current value and running total
		  newvals (if uselisp (eval-expression (read form))
			    (list (or prevtotal curval 0)
				  (+ curtotal (or prevtotal curval 0)))))
	    (cond
	     ((< level last-level) ; we have moved up to a parent
	      (setq 
	       ;; new value, as string
	       str (if (nth 0 newvals) (org-columns-number-to-string (nth 0 newvals) format printf) nil)
	       ;; add text properties to it
	       useval (org-add-props (copy-sequence str) nil 'org-computed t 'face 'bold)
	       ;; get current text properties
	       sum-alist (get-text-property sumpos 'org-summaries))
	      ;; put new value here as a text property
	      (if (assoc property sum-alist)
		  (setcdr (assoc property sum-alist) useval)
		(push (cons property useval) sum-alist)
		(org-unmodified
		 (add-text-properties sumpos (1+ sumpos)
				      (list 'org-summaries sum-alist))))
	      ;; put new org property value 
	      (if (nth 0 newvals) (org-entry-put nil property str))
	      ;; set value for current level total
	      (when (or prevtotal valflag)
		(aset lsum level (nth 1 newvals)))
	      ;; clear totals for deeper levels
	      (loop for l from (1+ level) to (1- lmax) do
		    (aset lsum l (if uselisp nil 0))))
	     ((>= level last-level) ; we have not moved up to a parent
	      ;; set new org property value and add to total for this level
	      (org-entry-put nil property (org-columns-number-to-string (nth 0 newvals) format printf))
	      (aset lsum level (nth 1 newvals)))
	     (t (error "This should not happen")))))
      (org-columns-compute-orig property))))



-- 
aleblanc

  parent reply	other threads:[~2009-03-16 20:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-13 23:43 SOLVED: elisp formulas in column view (without converting to tables) news
2009-03-14  1:33 ` news
2009-03-16 20:15 ` news [this message]
2009-06-09  6:26   ` 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:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  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=87tz5tql66.fsf@it.com \
    --to=news@aleblanc.cotse.net \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* 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

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

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).