From: Arthur Miller <arthur.miller@live.com>
To: Max Nikulin <manikulin@gmail.com>
Cc: emacs-orgmode@gnu.org
Subject: Re: Proposal: 'executable' org-capture-templaes
Date: Fri, 01 Jul 2022 01:30:16 +0200 [thread overview]
Message-ID: <AM9PR09MB497740CC420654E0C7A5D9D896BA9@AM9PR09MB4977.eurprd09.prod.outlook.com> (raw)
In-Reply-To: <t9i0ik$gu2$1@ciao.gmane.io> (Max Nikulin's message of "Thu, 30 Jun 2022 00:02:11 +0700")
Max Nikulin <manikulin@gmail.com> writes:
> On 26/06/2022 11:50, Arthur Miller wrote:
>> Max Nikulin writes:
>>>
>>> By state I mean some structure opaque to menu package. It just receives it from
>>> caller as an optional argument and (when given) later passes it to
>>> handler. Maybe it is alien approach in LISP, but in C (where closures are
>>> impossible) it is a widely used technique. Functions having callback argument
>>> usually have another void* one that is later passed as an argument of the
>>> callback function in addition to other data.
>> I understand, I have done my share of C, and know what you mean. Say
>> posix thread will take a void* to user data, and pass it on. This is
>> exactly what this is about. It is just that we don't need an extra
>> structure to pass around. We have a menu entry, which *is* the user
>> data.
>
> You a right, it is not strictly necessary that menu should be aware of state. I
> expect some helper though, e.g.
>
> ;;; -*- lexical-binding: t; -*-
> (defun org-menu-multiinstance-stateful (menus &rest args)
> (let* ((buffer-name (or (plist-get args :buffer-name)
> "*Select menu*"))
> (state (plist-get args :state))
> (handler (plist-get args :handler))
> (handler-closure
> (and handler
> state
> (lambda (entry &rest _)
> (funcall handler entry state)))))
> (when state (org-plist-delete args :state))
> (when handler (org-plist-delete args :handler))
> (plist-put args
> :buffer-name
> (generate-new-buffer-name buffer-name))
> (apply #'org-select
> (if handler-closure
> (mapcar
> (lambda (menu)
> (append menu (list :org-select-handler
> handler-closure)))
> menus)
> menus)
> args)))
> (provide 'org-multimenu)
>
> To be able to call menu as
>
> (load (expand-file-name "org-multimenu"))
> (org-menu-multiinstance-stateful
> `((("1" "one" 1)
> ("2" "two" 2)))
> :state (format-time-string "%T")
> :text "Some heading"
> :buffer-name "*Test menu*"
> :handler (lambda (entry state)
> (org-select-quit) ; it does not kill the buffer
> (message "handler %S %S" entry state)))
I might be missunderstanding you now, but from this example it seems to me that
you see menu entries as something that aims for the menu itself, while state is
some user data?
The "menu data" here is just: "1" and "one" in the first entry, and simillary
"2" and "two" in the second entry. After those, client code can put whatever it
desires: ("1" "one" ..... lots of client state .....). So for example client
could have something like ("1" "one" 1 (format-time-string "%T")).
However that might be tedious to type for each entry, so maybe we could pass an
optional "menu-global" state (or entry) that is passed to the user. So it would
be:
(lambda (entry &optional state)
(org-select-quit) ; it does not kill the buffer
(message "handler %S %S" entry state)))
Reason for optional: I prefer simplicity. I think the idea to lump together
menu selection with user state as it is done in org-capture-templates is really
good. Kudos to whomever came up with that one!
I like it because it puts everything into one place, we don't need to update
display and logic separately but everything is in an entry. I think it is good,
and I would like to keep that simplicity. I wouldnt like to suddenly separate
user state and menu state, because it would negate that fundamental idea.
> I do not like how to closures are represented in elisp stack traces
> (e.g. JavaScript engines in browsers tries hard to give some debug names for
> anonymous functions). It should not be a problem when passed handler is a named
> function (not a lambda) despite closure in the adjacent frame.
>
> However I would expect that menu handler is not aware if menu is implemented
> using buffers. From my point of view handler should not have buffer argument.
I understand, and I agree it is not very beautiful design :). The problem is when
client code provides its own handler. In the beginning I used a flag,
org-select-transient, to signal the menu should go away, but that wasn't very
clean either. The solution is maybe to never give total control to user handler,
but to always wrap/call user handler and finnish in menu's own handler. That way
we can use a flag to signal some state. I don't know, just thinking loud at the
moment; will have to test.
> What I missed in your current implementation is ability to change text of menu
> entries in response to action. E.g. "C-c C-e" ox dispatcher has some options and
> user should see current values.
The buffer text is just dead text; menu entries are a graphical display for the
user, not really interactive in the sense that it will update itself upon some
user action, unless user picks submenu or returns from one.
> E.g. "C-c C-e" ox dispatcher has some options and
> user should see current values.
Can that be implemented as a submenu (group node as in org-capture-templates)?
> P.S. I am sorry for long delay.
Don't worry. It was midsummer celebration here and lots of sun so I was out on
the beach with the family, not much behind the computer last weekend and entire
week. We are expecting rain next week, so I will probably work on it more over
the weekend and early next week. I have rebuild it for now, I have removed
tripple nesting and incorporated some (most) of Ihors remarks, and removed some
ugly iteration for recursion but I am not completely done with everything I wish
to do yet.
best regards
/a
next prev parent reply other threads:[~2022-06-30 23:32 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-26 15:27 Proposal: 'executable' org-capture-templaes Arthur Miller
2022-05-27 5:27 ` Ihor Radchenko
2022-05-27 12:17 ` Arthur Miller
2022-05-27 14:35 ` Max Nikulin
2022-05-28 3:51 ` Ihor Radchenko
2022-05-30 2:04 ` Arthur Miller
2022-05-30 5:05 ` Ihor Radchenko
2022-05-30 12:40 ` Arthur Miller
2022-05-31 4:58 ` Ihor Radchenko
2022-05-31 14:46 ` Arthur Miller
2022-06-04 15:35 ` Arthur Miller
2022-06-05 0:04 ` Ihor Radchenko
2022-06-05 15:16 ` Arthur Miller
2022-06-05 23:05 ` Tim Cross
2022-06-08 12:43 ` Ihor Radchenko
2022-06-08 21:13 ` Tim Cross
2022-06-09 4:00 ` Ihor Radchenko
2022-06-17 4:40 ` Arthur Miller
2022-06-18 4:03 ` Ihor Radchenko
2022-06-18 4:26 ` Tim Cross
2022-06-18 12:25 ` Max Nikulin
2022-06-08 12:24 ` Ihor Radchenko
2022-06-05 7:36 ` Max Nikulin
2022-06-05 15:07 ` Arthur Miller
2022-06-06 17:06 ` Max Nikulin
2022-06-07 3:09 ` Samuel Wales
2022-06-07 3:16 ` Samuel Wales
2022-06-08 12:48 ` Ihor Radchenko
2022-06-10 16:53 ` Max Nikulin
2022-06-11 5:26 ` Ihor Radchenko
2022-06-18 8:18 ` Max Nikulin
2022-06-18 8:25 ` Ihor Radchenko
2022-06-19 11:20 ` Max Nikulin
2022-06-20 12:10 ` Ihor Radchenko
2022-06-20 17:24 ` Max Nikulin
2022-06-21 4:07 ` Ihor Radchenko
2022-06-21 7:38 ` Arthur Miller
2022-06-21 15:48 ` Max Nikulin
2022-06-22 12:13 ` Arthur Miller
2022-06-22 16:29 ` Max Nikulin
2022-06-26 4:50 ` Arthur Miller
2022-06-29 17:02 ` Max Nikulin
2022-06-30 23:30 ` Arthur Miller [this message]
2022-07-01 15:53 ` Proposal: 'executable' org-capture-templates Max Nikulin
2022-06-25 7:32 ` Proposal: 'executable' org-capture-templaes Ihor Radchenko
2022-06-26 4:25 ` Arthur Miller
2022-06-26 4:37 ` Ihor Radchenko
2022-06-26 4:52 ` Arthur Miller
2022-06-21 7:37 ` Arthur Miller
2022-07-02 11:31 ` Max Nikulin
2022-07-03 15:12 ` Arthur Miller
2022-07-07 16:14 ` Proposal: 'executable' org-capture-templates Max Nikulin
2022-06-18 15:05 ` Proposal: 'executable' org-capture-templaes Arthur Miller
2022-06-19 10:53 ` Max Nikulin
2022-06-19 15:34 ` Arthur Miller
2022-07-03 3:32 ` Max Nikulin
2022-06-08 12:35 ` Ihor Radchenko
2022-05-31 16:37 ` Max Nikulin
2022-06-01 1:45 ` arthur miller
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AM9PR09MB497740CC420654E0C7A5D9D896BA9@AM9PR09MB4977.eurprd09.prod.outlook.com \
--to=arthur.miller@live.com \
--cc=emacs-orgmode@gnu.org \
--cc=manikulin@gmail.com \
/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 external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.