emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Conditional summing in column-mode?
@ 2017-08-24 15:49 Stig Brautaset
  2017-08-25  7:55 ` Nicolas Goaziou
  0 siblings, 1 reply; 8+ messages in thread
From: Stig Brautaset @ 2017-08-24 15:49 UTC (permalink / raw)
  To: emacs-org list


I have the following column-mode defined in =~/org/Holidays.org=:

#+BEGIN_SRC org
  ,#+COLUMNS: %TIMESTAMP(When) %ITEM(What) %CONFIRMED(Confirmed?){X/} %DAYS(Days){+}
  ,#+Confirmed_ALL: "[ ]" "[X]"
  ,#+TODO: TODO | DONE CANCELLED
#+END_SRC

Is it possible to have the =%DAYS(Days){+}= part only sum up rows that
have an =[X]= in their =Confirmed?= property?

Stig

-- 
; GNU Emacs 26.0.50, Org mode version 9.0.9

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-24 15:49 Conditional summing in column-mode? Stig Brautaset
@ 2017-08-25  7:55 ` Nicolas Goaziou
  2017-08-25 17:10   ` Stig Brautaset
  0 siblings, 1 reply; 8+ messages in thread
From: Nicolas Goaziou @ 2017-08-25  7:55 UTC (permalink / raw)
  To: Stig Brautaset; +Cc: emacs-org list

Hello,

Stig Brautaset <stig@brautaset.org> writes:

> I have the following column-mode defined in =~/org/Holidays.org=:
>
> #+BEGIN_SRC org
>   ,#+COLUMNS: %TIMESTAMP(When) %ITEM(What) %CONFIRMED(Confirmed?){X/} %DAYS(Days){+}
>   ,#+Confirmed_ALL: "[ ]" "[X]"
>   ,#+TODO: TODO | DONE CANCELLED
> #+END_SRC
>
> Is it possible to have the =%DAYS(Days){+}= part only sum up rows that
> have an =[X]= in their =Confirmed?= property?

Not out of the box. But you could write a function creating and updating
another property, e.g., CHECKED_DAYS and have columns view display this
instead.

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-25  7:55 ` Nicolas Goaziou
@ 2017-08-25 17:10   ` Stig Brautaset
  2017-08-25 19:55     ` Nicolas Goaziou
  0 siblings, 1 reply; 8+ messages in thread
From: Stig Brautaset @ 2017-08-25 17:10 UTC (permalink / raw)
  To: emacs-org list


Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> Hello,
>
> Stig Brautaset <stig@brautaset.org> writes:
>
>> I have the following column-mode defined in =~/org/Holidays.org=:
>>
>> #+BEGIN_SRC org
>>   ,#+COLUMNS: %TIMESTAMP(When) %ITEM(What) %CONFIRMED(Confirmed?){X/} %DAYS(Days){+}
>>   ,#+Confirmed_ALL: "[ ]" "[X]"
>>   ,#+TODO: TODO | DONE CANCELLED
>> #+END_SRC
>>
>> Is it possible to have the =%DAYS(Days){+}= part only sum up rows that
>> have an =[X]= in their =Confirmed?= property?
>
> Not out of the box. But you could write a function creating and updating
> another property, e.g., CHECKED_DAYS and have columns view display this
> instead.

Thank you! That's a great idea. I've managed to come up with the
following, which works interactively:

#+BEGIN_SRC emacs-lisp
  (defun sb/org-calc-confirmed-days ()
    "For an entry with both a `CONFIRMED' and `DAYS' property, calculate `CONFIRMED_DAYS'"
    (let ((days (org-entry-get nil "DAYS"))
          (confirmed (org-entry-get nil "CONFIRMED")))
      (when (and days
                 (string= "[X]" confirmed))
        (org-entry-put nil "CONFIRMED_DAYS" days))))

  (defun sb/org-map-confirmed-days ()
    "Map over entries and calculate confirmed days"
    (interactive)
    (org-map-entries #'sb/org-calc-confirmed-days))
#+END_SRC

However, I would like to add an advice around =org-columns-compute-all=
to run the =sb/org-map-confirmed-days= function, and this I have not
been successful at. I've tried doing this:

: (add-function :before org-columns-compute-all #'sb/org-map-confirmed-days)

However, I keep getting the following error:

: Use of gv-ref probably requires lexical-binding
: advice--add-function: Symbol’s value as variable is void: org-columns-compute-all

I would appreciate if anyone has any insight into solving this.

Stig

PS: I'm using Emacs and Org both installed from Git, on macOS.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-25 17:10   ` Stig Brautaset
@ 2017-08-25 19:55     ` Nicolas Goaziou
  2017-08-28 10:41       ` Stig Brautaset
  0 siblings, 1 reply; 8+ messages in thread
From: Nicolas Goaziou @ 2017-08-25 19:55 UTC (permalink / raw)
  To: Stig Brautaset; +Cc: emacs-org list

Stig Brautaset <stig@brautaset.org> writes:

> However, I would like to add an advice around =org-columns-compute-all=
> to run the =sb/org-map-confirmed-days= function, and this I have not
> been successful at. I've tried doing this:
>
> : (add-function :before org-columns-compute-all #'sb/org-map-confirmed-days)
>
> However, I keep getting the following error:
>
> : Use of gv-ref probably requires lexical-binding
> : advice--add-function: Symbol’s value as variable is void: org-columns-compute-all
>
> I would appreciate if anyone has any insight into solving this.

Not really your question but since you can define your own summary
function (see `org-columns-summary-types'), just make sure the summary
function first refreshes the new property in headlines below the node
you're currently summarizing.

Regards,

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-25 19:55     ` Nicolas Goaziou
@ 2017-08-28 10:41       ` Stig Brautaset
  2017-08-29  7:11         ` Nicolas Goaziou
  0 siblings, 1 reply; 8+ messages in thread
From: Stig Brautaset @ 2017-08-28 10:41 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-org list


Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> Stig Brautaset <stig@brautaset.org> writes:
>
>> However, I would like to add an advice around =org-columns-compute-all=
>> to run the =sb/org-map-confirmed-days= function, and this I have not
>> been successful at. I've tried doing this:
>>
>> : (add-function :before org-columns-compute-all #'sb/org-map-confirmed-days)
>>
>> However, I keep getting the following error:
>>
>> : Use of gv-ref probably requires lexical-binding
>> : advice--add-function: Symbol’s value as variable is void: org-columns-compute-all
>>
>> I would appreciate if anyone has any insight into solving this.
>
> Not really your question but since you can define your own summary
> function (see `org-columns-summary-types'), just make sure the summary
> function first refreshes the new property in headlines below the node
> you're currently summarizing.

Thanks! This _almost_ works:

,----
| (defun sb/org-columns--summary-sum (values printf)
|   (org-map-entries #'sb/org-calc-confirmed-days nil 'tree)
|   (org-columns--summary-sum values printf))
|
| (setq org-columns-summary-types
|       '(("X+" . sb/org-columns--summary-sum)))
`----

Unfortunately it doesn't quite: the functions in
=org-columns-summary-types= are passed a list of values already
extracted from the properties, so my calculation of "confirmed days"
only takes effect on the _next_ call to the summary function. Is there a
hook I can use that is called before the property values are extracted?
(I wasn't able to find one.)

Stig

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-28 10:41       ` Stig Brautaset
@ 2017-08-29  7:11         ` Nicolas Goaziou
  2017-09-01  0:07           ` Stig Brautaset
  0 siblings, 1 reply; 8+ messages in thread
From: Nicolas Goaziou @ 2017-08-29  7:11 UTC (permalink / raw)
  To: Stig Brautaset; +Cc: emacs-org list

Hello,

Stig Brautaset <stig@brautaset.org> writes:

> Unfortunately it doesn't quite: the functions in
> =org-columns-summary-types= are passed a list of values already
> extracted from the properties, so my calculation of "confirmed days"
> only takes effect on the _next_ call to the summary function.

You can ignore the provided values, collect your own and summarize
those. Granted, this is sub-optimal.

> Is there a hook I can use that is called before the property values
> are extracted? (I wasn't able to find one.)

There isn't.

But here is an idea: `org-columns-summary-types' could also accept
entries like:

  (LABEL SUMMARIZE COLLECT)

where COLLECT is a function called on each summarized entry. SUMMARIZE
is applied on the values returned by COLLECT. When not provided, COLLECT
default to `org-entry-get' as it is the case already.

WDYT?

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-08-29  7:11         ` Nicolas Goaziou
@ 2017-09-01  0:07           ` Stig Brautaset
  2017-09-01 21:29             ` Nicolas Goaziou
  0 siblings, 1 reply; 8+ messages in thread
From: Stig Brautaset @ 2017-09-01  0:07 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-org list


Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

>> Is there a hook I can use that is called before the property values
>> are extracted? (I wasn't able to find one.)
>
> There isn't.
>
> But here is an idea: `org-columns-summary-types' could also accept
> entries like:
>
>   (LABEL SUMMARIZE COLLECT)
>
> where COLLECT is a function called on each summarized entry. SUMMARIZE
> is applied on the values returned by COLLECT. When not provided, COLLECT
> default to `org-entry-get' as it is the case already.
>
> WDYT?

I think I like it. So I could then do something like:

    (defun sb/org-collect-confirmed-days ()
      "Return `DAYS' for `CONFIRMED' entries, otherwise return 0"
      (let ((days (org-entry-get nil "DAYS"))
            (confirmed (org-entry-get nil "CONFIRMED")))
        (if (and days (string= "[X]" confirmed))
            days
          "0")))

    (setq org-columns-summary-types
          '(("X+" org-columns--summary-sum sb/org-collect-confirmed-days)))


That seems quite elegant! I guess the COLLECT function would be called
in `org-agenda-colview-summarize' such that the existing summary
functions would not need to change?

Though, there will then be a tight coupling between the "X+" label and
the column name, which is not ideal. Perhaps the COLLECT function could
(optionally?) take the column name (or the whole column spec) as an
argument so we could do something like:

    (defun sb/org-collect-confirmed-things (thing)
      "Return `THING for `CONFIRMED' entries, otherwise return 0"
      (let ((thing (org-entry-get nil thing))
            (confirmed (org-entry-get nil "CONFIRMED")))
        (if (and thing (string= "[X]" confirmed))
            thing
          "0")))

Then we could use =X+= to calculate both confirmed Days and Bananas:

    #+COLUMNS: %TIMESTAMP(When) %ITEM(What) %CONFIRMED(Confirmed?){X/} %Days(X+) %Bananas(X+)

Does this make sense?

I don't mind having a go at adding support for this, though I admit I'm
slightly terrified of the code in `org-agenda-colview-summarize' :-)


Stig

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Conditional summing in column-mode?
  2017-09-01  0:07           ` Stig Brautaset
@ 2017-09-01 21:29             ` Nicolas Goaziou
  0 siblings, 0 replies; 8+ messages in thread
From: Nicolas Goaziou @ 2017-09-01 21:29 UTC (permalink / raw)
  To: Stig Brautaset; +Cc: emacs-org list

Hello,

Stig Brautaset <stig@brautaset.org> writes:

> I think I like it. So I could then do something like:
>
>     (defun sb/org-collect-confirmed-days ()
>       "Return `DAYS' for `CONFIRMED' entries, otherwise return 0"
>       (let ((days (org-entry-get nil "DAYS"))
>             (confirmed (org-entry-get nil "CONFIRMED")))
>         (if (and days (string= "[X]" confirmed))
>             days
>           "0")))
>
>     (setq org-columns-summary-types
>           '(("X+" org-columns--summary-sum
>           sb/org-collect-confirmed-days)))

That's the idea, expect it should take one argument, the property being
summarized.

> That seems quite elegant! I guess the COLLECT function would be called
> in `org-agenda-colview-summarize' such that the existing summary
> functions would not need to change?

No, it wouldn't. It would be called in `org-columns--compute-spec' where
`value' is bound. Actually, we could write a getter,
`org-columns--collect', which would return COLLECT, as defined in the
summary, or

  (lambda (p) (org-entry-get (point) p))

Note that COLLECT function is called on a headline. Returning an empty
string means the property has no value (per `value-set' in the function
`org-columns--compute-spec').

> Though, there will then be a tight coupling between the "X+" label and
> the column name, which is not ideal. Perhaps the COLLECT function could
> (optionally?) take the column name

Indeed.

> I don't mind having a go at adding support for this,

Great. Implementation-wise, I think there is not much to do. But it
needs to be documented and tested in "test-org-colview.el".

Thank you!

Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-09-01 21:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-24 15:49 Conditional summing in column-mode? Stig Brautaset
2017-08-25  7:55 ` Nicolas Goaziou
2017-08-25 17:10   ` Stig Brautaset
2017-08-25 19:55     ` Nicolas Goaziou
2017-08-28 10:41       ` Stig Brautaset
2017-08-29  7:11         ` Nicolas Goaziou
2017-09-01  0:07           ` Stig Brautaset
2017-09-01 21:29             ` Nicolas Goaziou

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