emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Custom Bulk Functions With Prompt
@ 2021-01-17  2:31 Kevin Foley
  2021-01-17  5:42 ` Ihor Radchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-01-17  2:31 UTC (permalink / raw)
  To: emacs-orgmode

I'd like to setup a custom bulk function using
`org-agenda-bulk-custom-functions', however I'd like to receive one
prompt when I select the action and then have the action performed on
every entry without being prompted again.

For example the bulk tag function lets the user specify a tag once, then
applies that to every entry.  As far as I can tell from looking through
the source code, there's no way to replicate this via a custom function.

Is there something I'm missing that would allow me to do this?  If not,
any suggestions on how support for it could be implemented?  I'd be
happy to submit a patch but I'm not sure of the best way to approach it.

Kevin Foley


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

* Re: Custom Bulk Functions With Prompt
  2021-01-17  2:31 Custom Bulk Functions With Prompt Kevin Foley
@ 2021-01-17  5:42 ` Ihor Radchenko
  2021-01-17 18:06   ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2021-01-17  5:42 UTC (permalink / raw)
  To: Kevin Foley, emacs-orgmode

Kevin Foley <kevin@kevinjfoley.me> writes:

> I'd like to setup a custom bulk function using
> `org-agenda-bulk-custom-functions', however I'd like to receive one
> prompt when I select the action and then have the action performed on
> every entry without being prompted again.

Generally, you can set a variable indicating if your custom function is
invoked first time during the bulk action. This variable can be set to
nil in :before advice for org-agenda-bulk-action. Then, you can check
the variable value in your custom function. If it is nil, it is the
first invocation and you run the interactive version then setting the
variable to 't. The variable will have 't value in all the following
invocations and your function can run non-interactively.

Instead of advice, you can also provide a simple patch implementing the
described functionality in org-agenda-bulk-action. I do support adding
this functionality to org.

Best,
Ihor


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

* Re: Custom Bulk Functions With Prompt
  2021-01-17  5:42 ` Ihor Radchenko
@ 2021-01-17 18:06   ` Kevin Foley
  2021-01-18  2:11     ` Ihor Radchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-01-17 18:06 UTC (permalink / raw)
  To: Ihor Radchenko, emacs-orgmode

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

Ihor Radchenko <yantar92@gmail.com> writes:

> Instead of advice, you can also provide a simple patch implementing the
> described functionality in org-agenda-bulk-action. I do support adding
> this functionality to org.

I took a look this morning and came up with the attached patch.
Essentially if the custom function is a list then the first element is
the bulk function and the second is the argument function.

If that looks reasonable I can add some documentation and submit a
proper patch.

Kevin Foley

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: custom-bulk-function-args.diff --]
[-- Type: text/x-patch, Size: 0 bytes --]



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

* Re: Custom Bulk Functions With Prompt
  2021-01-17 18:06   ` Kevin Foley
@ 2021-01-18  2:11     ` Ihor Radchenko
  2021-01-18  2:14       ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2021-01-18  2:11 UTC (permalink / raw)
  To: Kevin Foley, emacs-orgmode

Kevin Foley <kevin@kevinjfoley.me> writes:

> I took a look this morning and came up with the attached patch.
> Essentially if the custom function is a list then the first element is
> the bulk function and the second is the argument function.
>
> If that looks reasonable I can add some documentation and submit a
> proper patch.
>
> Kevin Foley

That sounds like a reasonable option.

Note that attachment in the previous email appears to be empty. Can you
resend? I will take a look then.

Best,
Ihor




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

* Re: Custom Bulk Functions With Prompt
  2021-01-18  2:11     ` Ihor Radchenko
@ 2021-01-18  2:14       ` Kevin Foley
  2021-01-18  8:50         ` Ihor Radchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-01-18  2:14 UTC (permalink / raw)
  To: Ihor Radchenko, emacs-orgmode

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

Ihor Radchenko <yantar92@gmail.com> writes:

> Note that attachment in the previous email appears to be empty. Can you
> resend? I will take a look then.

My mistake, populated file is attached. Thanks.

Kevin


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: custom-bulk-function-args.diff --]
[-- Type: text/x-patch, Size: 697 bytes --]

diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index dedf7e5bb..1df99ec79 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -10487,7 +10487,12 @@ (defun org-agenda-bulk-action (&optional arg)
 
 	(action
 	 (pcase (assoc action org-agenda-bulk-custom-functions)
-	   (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
+	   (`(,_ ,f)
+            (when (listp f)
+              (let ((args (funcall (nth 1 f)))
+                    (func (nth 0 f)))
+                (setq f (apply #'apply-partially func args))))
+            (setq cmd f) (setq redo-at-end t))
 	   (_ (user-error "Invalid bulk action: %c" action)))))
 
       ;; Sort the markers, to make sure that parents are handled

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

* Re: Custom Bulk Functions With Prompt
  2021-01-18  2:14       ` Kevin Foley
@ 2021-01-18  8:50         ` Ihor Radchenko
  2021-01-19 18:36           ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2021-01-18  8:50 UTC (permalink / raw)
  To: Kevin Foley, emacs-orgmode

Kevin Foley <kevin@kevinjfoley.me> writes:

> +	   (`(,_ ,f)
> +            (when (listp f)
> +              (let ((args (funcall (nth 1 f)))
> +                    (func (nth 0 f)))
> +                (setq f (apply #'apply-partially func args))))
> +            (setq cmd f) (setq redo-at-end t))

That will not work. pcase will not even match list of 3+ elements using
`(,_ ,f):

(pcase '(a b c)
  (`(,_ ,f)
   (if (listp f)
       "List!"
     "Not list!"))
  (_ "No match!")) => "No match!"

You need to add extra matcher `(,_ ,argf ,f).

Best,
Ihor


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

* Re: Custom Bulk Functions With Prompt
  2021-01-18  8:50         ` Ihor Radchenko
@ 2021-01-19 18:36           ` Kevin Foley
  2021-01-20  6:49             ` Ihor Radchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-01-19 18:36 UTC (permalink / raw)
  To: Ihor Radchenko, emacs-orgmode

Ihor Radchenko <yantar92@gmail.com> writes:

> You need to add extra matcher `(,_ ,argf ,f).

My idea is to keep allow the user to optionally pass a list of argf and
f instead of just a function.

For example if no args need to be collected:

'((?R set-category)
  (?C bulk-cut))

but if arguments needs to be collected for set-category:

'((?R (set-category set-category-args))
  (?C bulk-cut))

I mostly went with this because I'm not very familiar with `pcase'.
I've confirmed it works as expected but let me know if you still think
another approach is better.

Kevin


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

* Re: Custom Bulk Functions With Prompt
  2021-01-19 18:36           ` Kevin Foley
@ 2021-01-20  6:49             ` Ihor Radchenko
  2021-01-21 14:01               ` [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt) Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Ihor Radchenko @ 2021-01-20  6:49 UTC (permalink / raw)
  To: Kevin Foley, emacs-orgmode

Kevin Foley <kevin@kevinjfoley.me> writes:

> '((?R (set-category set-category-args))
>   (?C bulk-cut))
>
> I mostly went with this because I'm not very familiar with `pcase'.
> I've confirmed it works as expected but let me know if you still think
> another approach is better.

I understand now. I thought you wanted to use different format:
(?R set-category set-category-args)

Then, your code looks reasonable. Just need to document the new custom
bulk action format.

Best,
Ihor


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-20  6:49             ` Ihor Radchenko
@ 2021-01-21 14:01               ` Kevin Foley
  2021-01-22  5:14                 ` Ihor Radchenko
  2021-01-22  5:29                 ` Kyle Meyer
  0 siblings, 2 replies; 18+ messages in thread
From: Kevin Foley @ 2021-01-21 14:01 UTC (permalink / raw)
  To: Ihor Radchenko, emacs-orgmode

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

Attached patch should allow user to specify a function to collect
arguments when calling a custom bulk function such that those arguments
are only collected once and used for each entry.

Kevin Foley


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-agenda.el-Support-argument-collection-for-custom.patch --]
[-- Type: text/x-patch, Size: 2223 bytes --]

From dfab64f738f227691d84a2fdec5bba2cf4f1e3b0 Mon Sep 17 00:00:00 2001
From: "Kevin J. Foley" <kevin@kevinjfoley.me>
Date: Thu, 21 Jan 2021 08:48:52 -0500
Subject: [PATCH] org-agenda.el: Support argument collection for custom bulk
 functions

* lisp/org-agenda.el: (org-agenda-bulk-custom-functions): Add
documentation about for collection arguments for custom bulk functions.
(org-agenda-bulk-action): Support function to collect arguments for
custom bulk functions.
---
 lisp/org-agenda.el | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index dedf7e5bb..deadacc1e 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -2080,7 +2080,20 @@ (defcustom org-agenda-bulk-custom-functions nil
 
 With selected entries in an agenda buffer, `B R' will call
 the custom function `set-category' on the selected entries.
-Note that functions in this alist don't need to be quoted."
+Note that functions in this alist don't need to be quoted.
+
+If the custom function accepts arguments which you'd like to
+collect once from the user to be used for each call, you can pass
+a list with the bulk function, and the function which collects
+it's arguments and returns them as a list.  For example:
+
+  \\='((?R (set-category get-category))
+    (?C bulk-cut))
+
+Now, `B R' will call the custom `get-category' which would prompt
+the user once for a category.  That category is then passed as an
+argument to `set-category' for each entry it's called against.
+"
   :type '(alist :key-type character :value-type (group function))
   :version "24.1"
   :group 'org-agenda)
@@ -10487,7 +10500,12 @@ (defun org-agenda-bulk-action (&optional arg)
 
 	(action
 	 (pcase (assoc action org-agenda-bulk-custom-functions)
-	   (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
+	   (`(,_ ,f)
+            (when (listp f)
+              (let ((args (funcall (nth 1 f)))
+                    (func (nth 0 f)))
+                (setq f (apply #'apply-partially func args))))
+            (setq cmd f) (setq redo-at-end t))
 	   (_ (user-error "Invalid bulk action: %c" action)))))
 
       ;; Sort the markers, to make sure that parents are handled
-- 
2.28.0


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-21 14:01               ` [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt) Kevin Foley
@ 2021-01-22  5:14                 ` Ihor Radchenko
  2021-01-22  5:29                 ` Kyle Meyer
  1 sibling, 0 replies; 18+ messages in thread
From: Ihor Radchenko @ 2021-01-22  5:14 UTC (permalink / raw)
  To: Kevin Foley, emacs-orgmode

Kevin Foley <kevin@kevinjfoley.me> writes:

> Attached patch should allow user to specify a function to collect
> arguments when calling a custom bulk function such that those arguments
> are only collected once and used for each entry.

Looks good for me. Maybe you can also add an entry to ORG-NEWS.

Marking this thread as a patch for maintainer review.

Best,
Ihor


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-21 14:01               ` [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt) Kevin Foley
  2021-01-22  5:14                 ` Ihor Radchenko
@ 2021-01-22  5:29                 ` Kyle Meyer
  2021-01-27 23:13                   ` Kevin Foley
  1 sibling, 1 reply; 18+ messages in thread
From: Kyle Meyer @ 2021-01-22  5:29 UTC (permalink / raw)
  To: Kevin Foley; +Cc: emacs-orgmode, Ihor Radchenko

Kevin Foley writes:

> Attached patch should allow user to specify a function to collect
> arguments when calling a custom bulk function such that those arguments
> are only collected once and used for each entry.

Thanks, Kevin and Ihor.  This sounds like a good change to me too.

> Subject: [PATCH] org-agenda.el: Support argument collection for custom bulk
>  functions
>
> * lisp/org-agenda.el: (org-agenda-bulk-custom-functions): Add

nit: No ":" after "lisp/org-agenda.el".

> documentation about for collection arguments for custom bulk functions.

Drop either "about" or "for"?

> (org-agenda-bulk-action): Support function to collect arguments for
> custom bulk functions.
> ---
>  lisp/org-agenda.el | 22 ++++++++++++++++++++--

In addition to the NEWS entry that Ihor mentioned, it looks like an
update to the manual is missing.

>  1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
> index dedf7e5bb..deadacc1e 100644
> --- a/lisp/org-agenda.el
> +++ b/lisp/org-agenda.el
> @@ -2080,7 +2080,20 @@ (defcustom org-agenda-bulk-custom-functions nil
>  
>  With selected entries in an agenda buffer, `B R' will call
>  the custom function `set-category' on the selected entries.
> -Note that functions in this alist don't need to be quoted."
> +Note that functions in this alist don't need to be quoted.
> +
> +If the custom function accepts arguments which you'd like to
> +collect once from the user to be used for each call, you can pass
> +a list with the bulk function, and the function which collects
> +it's arguments and returns them as a list.  For example:

s/it's/its/

> +
> +  \\='((?R (set-category get-category))
> +    (?C bulk-cut))
> +
> +Now, `B R' will call the custom `get-category' which would prompt
> +the user once for a category.  That category is then passed as an
> +argument to `set-category' for each entry it's called against.
> +"
>    :type '(alist :key-type character :value-type (group function))

Should this :type be updated?

>    :version "24.1"

Please update this version, or rather drop :version and add

  :package-version '(Org . "9.5")

>    :group 'org-agenda)


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-22  5:29                 ` Kyle Meyer
@ 2021-01-27 23:13                   ` Kevin Foley
  2021-01-30  7:48                     ` Kyle Meyer
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-01-27 23:13 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Ihor Radchenko

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

Kyle Meyer <kyle@kyleam.com> writes:

Thanks for the review Kyle.

> nit: No ":" after "lisp/org-agenda.el".

Fixed.

> Drop either "about" or "for"?

Fixed.

> In addition to the NEWS entry that Ihor mentioned, it looks like an
> update to the manual is missing.

NEWS entry added.  With regard to the manual, the custom bulk function
option is only mentioned as a footnote.  I'm happy to add a more in
depth explanation, however I'm not sure where it should go, any
recommendations?

> s/it's/its/

Fixed.

> Should this :type be updated?

Updated.  I went with list with and optional second element for the
argument collection function (I also updated my patch to handle a nil
second argument).

I think it makes sense to encourage use of the list even when not using
an argument collection function but let me know if you think a choice
between function and list would be better.

> Please update this version, or rather drop :version and add
>   :package-version '(Org . "9.5")

Updated.


Thanks,
Kevin


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-agenda.el-Support-argument-collection-for-custom.patch --]
[-- Type: text/x-patch, Size: 3630 bytes --]

From 1d09a90abcb4136a3cf7562870f7eda831f163d3 Mon Sep 17 00:00:00 2001
From: "Kevin J. Foley" <kevin@kevinjfoley.me>
Date: Thu, 21 Jan 2021 08:48:52 -0500
Subject: [PATCH] org-agenda.el: Support argument collection for custom bulk
 functions

* lisp/org-agenda.el (org-agenda-bulk-custom-functions): Add
documentation about argument collection for custom bulk functions.
(org-agenda-bulk-action): Support function to collect arguments for
custom bulk functions.
* etc/ORG-NEWS (Option ~org-agenda-bulk-custom-functions~ now supports
collecting bulk arguments): Add entry to NEWS.
---
 etc/ORG-NEWS       |  7 ++++++-
 lisp/org-agenda.el | 29 +++++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5e5f1954d..4958d2b2e 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -81,8 +81,13 @@ block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
 the user to specify the preamble and code that preceedes and proceeds
 the contents of the source block.
 
+*** Option ~org-agenda-bulk-custom-functions~ now supports collecting bulk arguments
+
+When specifying a custom agenda bulk option, you can now also specify a function which collects the arguments to be used with each call to the custom function.
+
+
 ** New features
-*** =ob-python= improvements to =:return= header argument 
+*** =ob-python= improvements to =:return= header argument
 
 The =:return= header argument in =ob-python= now works for session
 blocks as well as non-session blocks.  Also, it now works with the
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index dedf7e5bb..c5c1b54ba 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -2080,9 +2080,25 @@ (defcustom org-agenda-bulk-custom-functions nil
 
 With selected entries in an agenda buffer, `B R' will call
 the custom function `set-category' on the selected entries.
-Note that functions in this alist don't need to be quoted."
-  :type '(alist :key-type character :value-type (group function))
-  :version "24.1"
+Note that functions in this alist don't need to be quoted.
+
+If the custom function accepts arguments which you'd like to
+collect once from the user to be used for each call, you can pass
+a list with the bulk function, and the function which collects
+its arguments and returns them as a list.  For example:
+
+  \\='((?R (set-category get-category))
+    (?C bulk-cut))
+
+Now, `B R' will call the custom `get-category' which would prompt
+the user once for a category.  That category is then passed as an
+argument to `set-category' for each entry it's called against.
+"
+  :type '(alist :key-type character
+                :value-type (list (function :tag "Bulk Custom Function")
+                                  (choice (const :tag "No Bulk Custom Argument Function" nil)
+                                          (function :tag "Bulk Custom Argument Function"))))
+  :package-version '(Org . "9.5")
   :group 'org-agenda)
 
 (defmacro org-agenda-with-point-at-orig-entry (string &rest body)
@@ -10487,7 +10503,12 @@ (defun org-agenda-bulk-action (&optional arg)
 
 	(action
 	 (pcase (assoc action org-agenda-bulk-custom-functions)
-	   (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
+	   (`(,_ ,f)
+            (when (listp f)
+              (let ((args (when (nth 1 f) (funcall (nth 1 f))))
+                    (func (nth 0 f)))
+                (setq f (apply #'apply-partially func args))))
+            (setq cmd f) (setq redo-at-end t))
 	   (_ (user-error "Invalid bulk action: %c" action)))))
 
       ;; Sort the markers, to make sure that parents are handled
-- 
2.28.0


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-27 23:13                   ` Kevin Foley
@ 2021-01-30  7:48                     ` Kyle Meyer
  2021-02-13 17:29                       ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Kyle Meyer @ 2021-01-30  7:48 UTC (permalink / raw)
  To: Kevin Foley; +Cc: emacs-orgmode, Ihor Radchenko

Kevin Foley writes:

> Kyle Meyer <kyle@kyleam.com> writes:
[...]
>> In addition to the NEWS entry that Ihor mentioned, it looks like an
>> update to the manual is missing.
>
> NEWS entry added.  With regard to the manual, the custom bulk function
> option is only mentioned as a footnote.  I'm happy to add a more in
> depth explanation, however I'm not sure where it should go, any
> recommendations?

Ah, okay, thanks for taking a look.  I'm okay leaving the details about
this functionality to the defcustom then.

> Subject: [PATCH] org-agenda.el: Support argument collection for custom bulk
>  functions
[...]
> diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
> index 5e5f1954d..4958d2b2e 100644
> --- a/etc/ORG-NEWS
> +++ b/etc/ORG-NEWS
> @@ -81,8 +81,13 @@ block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
>  the user to specify the preamble and code that preceedes and proceeds
>  the contents of the source block.
>  
> +*** Option ~org-agenda-bulk-custom-functions~ now supports collecting bulk arguments
> +
> +When specifying a custom agenda bulk option, you can now also specify a function which collects the arguments to be used with each call to the custom function.

Please fill this line (fill-column in .dir-locals.el is set to 70)
and...

>  ** New features
> -*** =ob-python= improvements to =:return= header argument 
> +*** =ob-python= improvements to =:return= header argument

... drop this unrelated space change.

> @@ -2080,9 +2080,25 @@ (defcustom org-agenda-bulk-custom-functions nil
>  
[...]
> +
> +If the custom function accepts arguments which you'd like to
> +collect once from the user to be used for each call, you can pass
> +a list with the bulk function, and the function which collects
> +its arguments and returns them as a list.  For example:
> +
> +  \\='((?R (set-category get-category))
> +    (?C bulk-cut))
> +

Reading this docstring in full, I felt it was a bit odd to repeat the
bulk-cut entry from the initial example again, as it stays the same and
isn't relevant.  So perhaps something like this would be clearer:

  ... and returns them as a list.  For example, the first
  entry in the above example could be extended as
  
    (?R (set-category get-category))
  
  Now, `B R' will ...

Or perhaps not.  I'm okay with it either way and will leave that up to
you.

> +Now, `B R' will call the custom `get-category' which would prompt
> +the user once for a category.  That category is then passed as an
> +argument to `set-category' for each entry it's called against.
> +"

Please drop the new line before the closing quote.

> +  :type '(alist :key-type character
> +                :value-type (list (function :tag "Bulk Custom Function")
> +                                  (choice (const :tag "No Bulk Custom Argument Function" nil)
> +                                          (function :tag "Bulk Custom Argument Function"))))
> +  :package-version '(Org . "9.5")
>    :group 'org-agenda)

convention nit: It'd be good to reflow the type to not go beyond ~80
columns.

This type looks like it's specifying a format that isn't supported by
org-agenda-bulk-action:

  (x . (y z)) => (x y z)

This is discussed a bit in (info "(elisp)Composite Types") under the
alist entry.

To use a concrete example, I believe all of these entries should be
valid with this patch:

  (defun my/bulk-action (&rest args)
    args)
  
  (defun my/args ()
    (list 1 2 3))
  
  (setq org-agenda-bulk-custom-functions
        '((?D my/bulk-action)
          (?E (my/bulk-action))
          (?F (my/bulk-action my/args))))

However, customize doesn't render the above value properly

    (customize-option 'org-agenda-bulk-custom-functions)

So, you'll need to flesh out the type entry more so that all of the
valid cases are handled by the customize interface.  I think it'd
probably end up a bit cleaner if you go with (key fn [arg-fn]), which is
the structure Ihor originally thought you were using, rather than
(key (fn [arg-fn])) or (key fn).  But I'd say that's dealer's choice.


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-01-30  7:48                     ` Kyle Meyer
@ 2021-02-13 17:29                       ` Kevin Foley
  2021-02-14 20:23                         ` Kyle Meyer
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-02-13 17:29 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Ihor Radchenko

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

Kyle Meyer <kyle@kyleam.com> writes:
> Please fill this line (fill-column in .dir-locals.el is set to 70)
> and...
>> [...]
> ... drop this unrelated space change.

Done and done.

> Reading this docstring in full, I felt it was a bit odd to repeat the
> bulk-cut entry from the initial example again, as it stays the same and
> isn't relevant.  So perhaps something like this would be clearer:
>
>   ... and returns them as a list.  For example, the first
>   entry in the above example could be extended as
>   
>     (?R (set-category get-category))
>   
>   Now, `B R' will ...
>
> Or perhaps not.  I'm okay with it either way and will leave that up to
> you.

I agree, I've removed it.


> Please drop the new line before the closing quote.

Done.

> convention nit: It'd be good to reflow the type to not go beyond ~80
> columns.

Fixed.

>> +  :type '(alist :key-type character
>> +                :value-type (list (function :tag "Bulk Custom Function")
>> +                                  (choice (const :tag "No Bulk Custom Argument Function" nil)
>> +                                          (function :tag "Bulk Custom Argument Function"))))
> This type looks like it's specifying a format that isn't supported by
> org-agenda-bulk-action:
> [...]
> I think it'd probably end up a bit cleaner if you go with (key fn
> [arg-fn])

I ended up moving to this structure and changing the pcase to a
pcase-let which I think makes things a bit cleaner, let me know your
thoughts.

>   (setq org-agenda-bulk-custom-functions
>         '((?D my/bulk-action)
>           (?E (my/bulk-action))
>           (?F (my/bulk-action my/args))))
> However, customize doesn't render the above value properly

I believe I have the type correct for the new layout.  For example the
following renders correctly:

(setq org-agenda-bulk-custom-functions 
      '((?a ignore)
	(?b ignore nil)
	(?c ignore ignore)))

Side note I'm not sure your example would render properly regardless
since `my/bulk-action' and `my/args' aren't functions.

Cheers,
Kevin Foley


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-agenda.el-Support-argument-collection-for-custom.patch --]
[-- Type: text/x-patch, Size: 3596 bytes --]

From 3d5dc61c1565695e797936af1f2eb50cd5460c95 Mon Sep 17 00:00:00 2001
From: "Kevin J. Foley" <kevin@kevinjfoley.me>
Date: Sat, 13 Feb 2021 12:04:38 -0500
Subject: [PATCH] org-agenda.el: Support argument collection for custom bulk
 functions

* lisp/org-agenda.el (org-agenda-bulk-custom-functions): Add
documentation about argument collection for custom bulk functions.
(org-agenda-bulk-action): Support function to collect arguments for
custom bulk functions.
* etc/ORG-NEWS (Option ~org-agenda-bulk-custom-functions~ now supports
collecting bulk arguments): Add entry to NEWS.
---
 etc/ORG-NEWS       |  7 +++++++
 lisp/org-agenda.el | 34 +++++++++++++++++++++++++++-------
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5e5f1954d..d7de97e2c 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -81,6 +81,13 @@ block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
 the user to specify the preamble and code that preceedes and proceeds
 the contents of the source block.
 
+*** Option ~org-agenda-bulk-custom-functions~ now supports collecting bulk arguments
+
+When specifying a custom agenda bulk option, you can now also specify
+a function which collects the arguments to be used with each call to
+the custom function.
+
+
 ** New features
 *** =ob-python= improvements to =:return= header argument 
 
diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index dedf7e5bb..42d127232 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -2080,9 +2080,25 @@ (defcustom org-agenda-bulk-custom-functions nil
 
 With selected entries in an agenda buffer, `B R' will call
 the custom function `set-category' on the selected entries.
-Note that functions in this alist don't need to be quoted."
-  :type '(alist :key-type character :value-type (group function))
-  :version "24.1"
+Note that functions in this alist don't need to be quoted.
+
+You can also specify a function which collects arguments to be
+used for each call to your bulk custom function.  The argument
+collecting function will be run once and should return a list of
+arguments to pass to the bulk function.  For example:
+
+  \\='((?R set-category get-category))
+
+Now, `B R' will call the custom `get-category' which would prompt
+the user once for a category.  That category is then passed as an
+argument to `set-category' for each entry it's called against."
+  :type
+  '(alist :key-type character
+	  :value-type
+          (group (function :tag "Bulk Custom Function")
+		 (choice (function :tag "Bulk Custom Argument Function")
+		         (const :tag "No Bulk Custom Argument Function" nil))))
+  :package-version '(Org . "9.5")
   :group 'org-agenda)
 
 (defmacro org-agenda-with-point-at-orig-entry (string &rest body)
@@ -10486,10 +10502,14 @@ (defun org-agenda-bulk-action (&optional arg)
 		(completing-read "Function: " obarray #'fboundp t nil nil))))
 
 	(action
-	 (pcase (assoc action org-agenda-bulk-custom-functions)
-	   (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
-	   (_ (user-error "Invalid bulk action: %c" action)))))
-
+	 (pcase-let (`(,_ ,fn ,arg-fn)
+                     (assoc action org-agenda-bulk-custom-functions))
+           (if (not fn)
+               (user-error "Invalid bulk action: %c" action)
+             (when (functionp arg-fn)
+               (setq fn (apply #'apply-partially fn (funcall arg-fn))))
+             (setq cmd fn)
+             (setq redo-at-end t)))))
       ;; Sort the markers, to make sure that parents are handled
       ;; before children.
       (setq entries (sort entries
-- 
2.28.0


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-02-13 17:29                       ` Kevin Foley
@ 2021-02-14 20:23                         ` Kyle Meyer
  2021-02-15  2:30                           ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Kyle Meyer @ 2021-02-14 20:23 UTC (permalink / raw)
  To: Kevin Foley; +Cc: emacs-orgmode, Ihor Radchenko

Kevin Foley writes:

> Kyle Meyer <kyle@kyleam.com> writes:
>
>>   (setq org-agenda-bulk-custom-functions
>>         '((?D my/bulk-action)
>>           (?E (my/bulk-action))
>>           (?F (my/bulk-action my/args))))
>> However, customize doesn't render the above value properly
[...]
> Side note I'm not sure your example would render properly regardless
> since `my/bulk-action' and `my/args' aren't functions.

I'm confused by this.  They were defined just above the text you quoted:

  (defun my/bulk-action (&rest args)
    args)

  (defun my/args ()
    (list 1 2 3))

  (setq org-agenda-bulk-custom-functions
  [...]

Either way, your latest defcustom type as well as the rest of the
update, aside from the issue I note below, looks good to me.  Thanks.

> @@ -10486,10 +10502,14 @@ (defun org-agenda-bulk-action (&optional arg)
>  		(completing-read "Function: " obarray #'fboundp t nil nil))))
>  
>  	(action
> -	 (pcase (assoc action org-agenda-bulk-custom-functions)
> -	   (`(,_ ,f) (setq cmd f) (setq redo-at-end t))
> -	   (_ (user-error "Invalid bulk action: %c" action)))))
> -
> +	 (pcase-let (`(,_ ,fn ,arg-fn)
> +                     (assoc action org-agenda-bulk-custom-functions))
> +           (if (not fn)
> +               (user-error "Invalid bulk action: %c" action)
> +             (when (functionp arg-fn)
> +               (setq fn (apply #'apply-partially fn (funcall arg-fn))))
> +             (setq cmd fn)
> +             (setq redo-at-end t)))))

Aren't the pcase-let bindings missing a set of parentheses?

  (pcase-let (`(,_ ,fn ,arg-fn)
              (list 1 2 3))
    (list fn arg-fn))  ; let: Invalid function: (\, _)

  (pcase-let ((`(,_ ,fn ,arg-fn)
               (list 1 2 3)))
    (list fn arg-fn))  ; => (2 3)

However, I don't see using pcase-let here as an improvement.  Admittedly
it's mostly subjective, but I think it's unhelpfully permissive for this
use case:

  (pcase-let ((`(,a ,b) (list 1 2 3 4)))
    (list a b))  ; => (1 2)

Fwiw, here's a relevant emacs.devel thread:
https://lists.gnu.org/archive/html/emacs-devel/2015-07/msg00103.html
(message ID: <jwvegkfoniv.fsf-monnier+emacs@gnu.org>)

My pcase-based suggestion, on top of your patch, is below.  If that
looks okay to you, there's no need to resend; I can squash it in.

diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el
index 42d127232..d6499e6b0 100644
--- a/lisp/org-agenda.el
+++ b/lisp/org-agenda.el
@@ -10502,14 +10502,15 @@ (defun org-agenda-bulk-action (&optional arg)
 		(completing-read "Function: " obarray #'fboundp t nil nil))))
 
 	(action
-	 (pcase-let (`(,_ ,fn ,arg-fn)
-                     (assoc action org-agenda-bulk-custom-functions))
-           (if (not fn)
-               (user-error "Invalid bulk action: %c" action)
-             (when (functionp arg-fn)
-               (setq fn (apply #'apply-partially fn (funcall arg-fn))))
-             (setq cmd fn)
-             (setq redo-at-end t)))))
+         (setq cmd
+               (pcase (assoc action org-agenda-bulk-custom-functions)
+                 (`(,_ ,fn)
+                  fn)
+                 (`(,_ ,fn ,arg-fn)
+                  (apply #'apply-partially fn (funcall arg-fn)))
+                 (_
+                  (user-error "Invalid bulk action: %c" action))))
+         (setq redo-at-end t)))
       ;; Sort the markers, to make sure that parents are handled
       ;; before children.
       (setq entries (sort entries


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-02-14 20:23                         ` Kyle Meyer
@ 2021-02-15  2:30                           ` Kevin Foley
  2021-02-15  3:01                             ` Kyle Meyer
  0 siblings, 1 reply; 18+ messages in thread
From: Kevin Foley @ 2021-02-15  2:30 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Ihor Radchenko

Kyle Meyer <kyle@kyleam.com> writes:
> Kevin Foley writes:
>
>> Side note I'm not sure your example would render properly regardless
>> since `my/bulk-action' and `my/args' aren't functions.
>
> I'm confused by this.  They were defined just above the text you
> quoted:

Sorry about that, I completely missed those.

> Aren't the pcase-let bindings missing a set of parentheses?

Hmm, you're right.  I swear I tested it and it was working so I'm not
sure if I accidentally dropped them or what.

I was hoping to add a test for this use case but it ended up seeming
like a rather large task with how much the function handles coupled with
my inexperience with ERT.

> However, I don't see using pcase-let here as an improvement.  Admittedly
> it's mostly subjective, but I think it's unhelpfully permissive for this
> use case:
>
>   (pcase-let ((`(,a ,b) (list 1 2 3 4)))
>     (list a b))  ; => (1 2)
>
> Fwiw, here's a relevant emacs.devel thread:
> https://lists.gnu.org/archive/html/emacs-devel/2015-07/msg00103.html
> (message ID: <jwvegkfoniv.fsf-monnier+emacs@gnu.org>)

I actually intended to be overly permissive in case additional options
are added in the future.  For example I was thinking it would be nice to
be able to assign a label to the custom action.

> My pcase-based suggestion, on top of your patch, is below.  If that
> looks okay to you, there's no need to resend; I can squash it in.

I'll defer to your pcase solution as I think my reasoning for using
pcase-let isn't particularly strong and I agree your suggestion is
cleaner.

Kevin Foley


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-02-15  2:30                           ` Kevin Foley
@ 2021-02-15  3:01                             ` Kyle Meyer
  2021-02-15 14:04                               ` Kevin Foley
  0 siblings, 1 reply; 18+ messages in thread
From: Kyle Meyer @ 2021-02-15  3:01 UTC (permalink / raw)
  To: Kevin Foley; +Cc: emacs-orgmode, Ihor Radchenko

Kevin Foley writes:

> I'll defer to your pcase solution as I think my reasoning for using
> pcase-let isn't particularly strong and I agree your suggestion is
> cleaner.

Okay, pushed (885ee086d).

Thanks again for the nice addition.


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

* Re: [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt)
  2021-02-15  3:01                             ` Kyle Meyer
@ 2021-02-15 14:04                               ` Kevin Foley
  0 siblings, 0 replies; 18+ messages in thread
From: Kevin Foley @ 2021-02-15 14:04 UTC (permalink / raw)
  To: Kyle Meyer; +Cc: emacs-orgmode, Ihor Radchenko

> Thanks again for the nice addition.
My pleasure, thanks for all of your feedback.

Also I took another look at adding a test around this, will hopefully
have another patch to submit for that.

Kevin


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

end of thread, other threads:[~2021-02-15 14:05 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-17  2:31 Custom Bulk Functions With Prompt Kevin Foley
2021-01-17  5:42 ` Ihor Radchenko
2021-01-17 18:06   ` Kevin Foley
2021-01-18  2:11     ` Ihor Radchenko
2021-01-18  2:14       ` Kevin Foley
2021-01-18  8:50         ` Ihor Radchenko
2021-01-19 18:36           ` Kevin Foley
2021-01-20  6:49             ` Ihor Radchenko
2021-01-21 14:01               ` [PATCH] Org Agenda Support Argument Collection for Custom Bulk Functions (was: Custom Bulk Functions With Prompt) Kevin Foley
2021-01-22  5:14                 ` Ihor Radchenko
2021-01-22  5:29                 ` Kyle Meyer
2021-01-27 23:13                   ` Kevin Foley
2021-01-30  7:48                     ` Kyle Meyer
2021-02-13 17:29                       ` Kevin Foley
2021-02-14 20:23                         ` Kyle Meyer
2021-02-15  2:30                           ` Kevin Foley
2021-02-15  3:01                             ` Kyle Meyer
2021-02-15 14:04                               ` Kevin Foley

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