emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Proposal: 'executable' org-capture-templaes


From: Arthur Miller
Subject: Re: Proposal: 'executable' org-capture-templaes
Date: Sun, 19 Jun 2022 17:34:06 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

Max Nikulin <manikulin@gmail.com> writes:

> On 18/06/2022 22:05, Arthur Miller wrote:
>> Max Nikulin writes:
>>> On 11/06/2022 12:26, Ihor Radchenko wrote:
>>>> Max Nikulin writes:
>>>>
>>>>> Imagine what would happen if Emacs decided to show several capture menus
>>>>> with keymap non-blocking interface in different virtual desktops.
>> Different Emacs processes, or just different Emacs frames?
>
> I mean single Emacs process perhaps with multiple frames spread over monitors
> and virtual desktops. I am unsure if Emacs can create windows for different 
> X11
> displays, but let's leave it aside and inter-process file locks as well.

Allright then; in that case what Ihor suggests, a variable somewhere, should
do. I suggest that variable be the capture buffer itself. I'll try to implement
this in a day or two; just need some time from other things in life.

>> In case of different Emacs processes, there is no way to guarantee 
>> consistence
>> unless one locks file in the file system. Windows can do it, I am not sure 
>> what
>> is Linux API to do this, don't know if Emacs exposes this functionality, have
>> never tried.
>> Otherewise, if it is only different Emacs frames/clients, the capture should
>> always find the capture buffer and return that one instead of creating new
>> ones. That way there is only one capture buffer, so multiple captures should 
>> not
>> be possible, i.el, it creates same effect as locking the input to 
>> minibuffer. I
>> am not sure how org-capture does, I haven't studied the code in-depth yet, 
>> but
>> what I see currently a user cancels it with C-c C-k. org-capture buffer could
>> setup hooks to clean everything, even if user kills buffer by other means, 
>> c-x
>> k, or whatever. It maybe already does, as said I haven't looked at those
>> details.
>
> Arthur, be reasonably skeptical concerning my ideas or suggestions, it seems I
> have not managed to convince e.g. Ihor.

:-). I think this would be quite a big and radical change in some important
parts of Org, so I really want to make sure that a fundamental error does not
happen. It would be a horrible thing if someones file with maybe lots of data
from the past gets messed up. That must not happen, so I really value the input
and would like to make sure use cases we have to take care of.

> I believe, multiple capture menus should be possible in parallel even within
> single frame since it may contain several windows and user experience should 
> be
> better than now. Keymap-based selection opens a road in this direction since
> menu may be non-modal, but it requires a bit different design.

That sounds like a new feature. You are correct, keymaps do open in that
direction. That would be possible to tuck on the routine that saves the
temporary buffer (whatever is called with C-c C-c). When user press C-c C-c in a
capture buffer, that is the only time when interaction with real a file on the
disk happends, right? Everythign else is done in a temporary buffer in ram. User
can physically press it only in one capture buffer, so it least in theory,
multiple capture shouldn't be impossible or too hard to implement. But, lets do
it after the rework of the menu thing?

> Waiting for return value to get capture template is not possible any more. A
> kind of continuations should be passed to the function creating menu buffer
> instead. E.g. it can be some state object that stores snapshot of data 
> necessary
> to fill capture template, export options, etc. and functions in menu entries
> that accept this state object as argument or obtain it from a dynamic
> variable. The state object likely should be a buffer-local variable. For
> non-blocking menu, entries should contain callbacks or menu may have single
> callback that is able to process static data from menu entries.

I happened to send the code yesterday by misstake only to one participant,
unfortunately, it wasn't ment; I seem to have pressed S w instead of S W and
wasn't looking at the address on top, so unfortunately you probably haven't seen
the code. However I have to rework it again because I did a bit bad design in
handling of one feature; I'll try to do it tomorrow.

However the idea is that the selection menu framework have no idea who is
calling it and why. It can not possibly know that either. It is entirely up to
the caller, so for that reason a caller can setup a handler that gets entire
template passed back and can do what it wants with it.

Current org-mks & Co don't really know who is calling than and why, but locking
happens automatically due to nature how the input is read (via minibuffer). In
case of new menu handling, the client has to do locking on its own, so it is a
bit more extra, but client can just buffer-get-create to get an existing buffer
before calling org-select, so it shouldn't be too much of the work. I
think. I'll test tomorrow or so.

> As a result, capture can not be processed till filling of a template (and so
> till adding it to the target buffer) within a single function. Instead first
> function prepares set of callbacks and renders a buffer with menu. When user
> activates a menu entry, a callback either just modifies the state object to
> change some option or starts some action (fills capture template and inserts
> result to the target document) and notifies caller that the menu should be
> destroyed. E.g. if some special symbol is returned from the menu entry 
> callback
> than it means change of some option, so menu should be retained, otherwise it 
> is
> action and the menu buffer is not necessary any more.

I have used a property 'transient' to flag that menu should be destroyed, and I
have done that before a handler is called, in osl--do-entry. But I it is a bad
thing. I came up with a different plan yesterday, and I will rework the meaning
of "transient" property there (btw if you have better word to skip confusion 
with
transient.el please suggest).

The idea is to have something like this:

    (defun org-capture--handler (entry &optional menu-buffer)

When a menu buffer is marked as "transient", it means that a client will take
ownership of the menu buffer and will can do whichever it prefer: keep it alive
or destroy it; in most cases destry it by reusing it, as in example of
org-capture where current code seems to recreate capture buffer in same
buffer.

> So despite I earlier opposed to executable menu entries, they are quite 
> natural
> way to implement non-blocking menu. State object specific to menu instance
> should be added in some way convenient for developers.

Current proposition is meant to be backwards compatible with org-capture, so it
has to work with org-capture-templates modell of state. Means a list of form

(key label ....)

Sometimes it is not even a proper plist, but anyway, it is a list, i.e. a state
carrier. So IMO menu "framework" itself is just a presentation of choices to a
user. Hanlder is the logic, so I don't think menu framwork should do too much
here; just present choices to a user, and pass the choice to the handler. There
is default handler

(defun osl--default-handler-fn (entry)
  "Try to execute form found in ENTRY if any."
  (let* ((form (nth 2 entry))
         (message
          (cond
           ((commandp form)
            (call-interactively form))
           ((functionp form)
            (apply form (cddr entry)))
           (t (eval form)))))
    (if (stringp message) message)))

(I have to rework, that is the one from yesterday )

That can cover lots of simple cases, so most use-cases don't need to write
handler in one-shot actions, (even org-agenda seems to work with this scenario),
but more advanced uses should give a handler and deal with the state in hanlder.

> More work may be necessary however to make org-capture really convenient and
> reliable. Capture menu should display some summary of captured data otherwise 
> it
> is impossible to decide which template should be chosen in the case of several
> simultaneous capture buffers. It is better to save capture data somewhere on
> disk while while menu is displayed to recover it after a crash.

See the comment about new feature above; I think that covers same issue. Sure
temporary file might be something, but that would be more work. Lets leave it
out for the particular moment, and come to it later.

>> I agree with you that completing read is a good alternative, but it is a
>> bit like discussion about GUI vs. terminal. I am personally heavy user
>> of Helm, but not everyone is I believe.
>
> I mentioned completing-read because I consider it as a test of API quality. It
> should be possible to plug alternative menu implementation and completing read
> may be a simple enough variant. It is blocking, but in the case of capture 
> "push
> to capture queue" could be used to postpone the action.

I don't think it matters there that completing read is blocking. Users do
completing read just to pick one action to get executed. I don't think I
understand how qeue of captures to do would work, to be honest.

> P.S. Notice text properties for entries in the following modal menu:
> Timothy to emacs-orgmode. [PATCH] New remote resource download policy. Sun, 12
> Jun 2022 22:43:07 +0800. 87mteiq6ou.fsf@gmail.com">https://list.orgmode.org/87mteiq6ou.fsf@gmail.com

I am not sure what do you bring that cod up? I looked at the link, but I just
see text styling with faces. Do  you mean to use text properties to communicate
the state? Sure text properties can be used for different things, but already
have "template" (a list) we are passing around. Isn't it sufficient as a state
carrier. You can push/pop things off of it to communicate whatever. Forgive me
if I don't understand what you meant there.

best regards
/a



reply via email to

[Prev in Thread] Current Thread [Next in Thread]