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, 05 Jun 2022 17:07:49 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

Max Nikulin <manikulin@gmail.com> writes:

> On 04/06/2022 22:35, Arthur Miller wrote:
>>
>> However before I continue, I am thinking of ditching the 'read-key' 
>> completely
>> and switching to "standard" Emacs way of implementing interactivity via mode 
>> and
>> mode-map. I am currently playing with such implementation, which to me 
>> appears
>> both simpler (code reduction) and more flexible, but it does change the 
>> mental
>> model of how clients of org-mks are used, for example org-capture.
>
> Frankly speaking, I am quite confused concerning what you are trying to do in
> particular. At some moment I had an impression that you were going to factor 
> out
> of `org-capture' the menu that is already a separate function `org-mks'.

>From the beginning I relized I can easily create menus with org-capture, bu 
>just
definiing org-templates, which are simply lists, and wanted to generalize the
org-capture to create menus that can execute ordinary functions, which 'exec'
keyword did. After input from Ihor I agree that it isn't the best way, and was
able to refactor org-mks to create a menu where I can execute any lisp form,
when it comes in a list like this : ("h" "hello-word" (message "Hello,
World")), where third element is just a lisp form. I have something like this:

#+begin_src emacs-lisp

(defun demo1 ()
  "Simple illustration to recreate org-capture menu (visually only)."
  (interactive)
  (let ((quick-menu-key-decorator-chars "[]")
        (return
         (quick-menu
          ;; table
          test-templates
          ;; description
          '(:label "*Quick Select*"
                   :text "Select a capture template\n=========================")
          ;; more tables
          '(("C" "Customize org-capture-templates"
             (customize-variable 'org-capture-templates))
            ("q" "Abort" (user-error "Abort"))))))
    (if (called-interactively-p 'interactive)
        (message "%S" return)
      return)))

(defun demo3 ()
  "Illustrate nested menus, unicode separator and alternative decorator."
  (interactive)
  (let ((quick-menu-key-decorator-chars "<>")
        (quick-menu-vertical-separator ?─))
    (quick-menu
     ;; table
     '(("g" "Greetings")
       ("gh" "Hello, World!" (message "Hello, World!"))
       ("gb" "Bar" (message "Hello, Bar!")))
     ;; description
     nil
     ;; more tables
     '(("f" "Functions")
       ("ff" "Find File" (call-interactively #'find-file))
       ("fo" "Open File" (flet ((next-read-file-uses-dialog-p () t))
                           (call-interactively 'find-file))))
     '(("q" "Abort" (user-error "Abort"))))))
     
"quick-menu" is my refactoring of org-mks, definition looks like this:



(defun quick-menu (table &optional description &rest tables)
  "Select a member of an alist with multiple keys.

TABLE is an alist which should contain entries where the car is a string.
There should be two types of entries.

1. prefix descriptions like (\"a\" \"Description\")
   This indicates that `a' is a prefix key for multi-letter selection, and
   that there are entries following with keys like \"ab\", \"ax\"...

2. Select-able members must have more than two elements, with the first
   being the string of keys that lead to selecting it, and the second a
   short description string of the item. 

The command will then make a temporary buffer listing all entries
that can be selected with a single key, and all the single key
prefixes.  When you press the key for a single-letter entry, it is selected.
When you press a prefix key, the commands (and maybe further prefixes)
under this key will be shown and offered for selection.

DESCRIPTON is a property list containing following members:

:text          a string placed over the selection in the buffer.
:label         a string used for the selections buffer name.
:prompt        a string used when prompting for a key.
:always        when `t', this menu is shown; even descended into submenus
:horizontal    when `t', if multiple menus are present they are rendered from
left to right, otherwise from top to bottom.
:key-decorator a two-character string used to decorate command characters. When
this string is specified, it will take precedence over the global variable
`quick-menu-key-decorator-chars'.

TABLES are additional menus in the same format as TABLE. If there are more
then one menus, they will be separated by a separator line rendered with
character as specified in `quick-menu-vertical-separator'")

#+end_src

I have paramterized decorator character for shortcut keys as they appear in the
buffer, org-capture uses "[]", as well as menu separator, which is currently
hard-coded in org-capture, and I am currently trying to implement horizontal
layout, where menus are stacked from left to right. I also have a not so nice
bug when drawing nested menu that it leaves undesired space where menus not
visible after descension into current are; I have to redraw the entire menu but
haven't yet implemented it so I don't want to post a demo yet. But before I fix
redrawing and implement horizontal layout, I would like to switch to the
different model of interaction and use ordinary mode map idioms instead of
blocking read key. Since I need to rework current prototype for the re-drawing
part, I can as well rework it to skip read-key at the same time.

> Interface is blocking for purpose. Capture has single-task workflow
> currently.

Yes, I am aware of that. That is why I ask if it would be acceptable to switch
away from non-blocking interface. I totally agree that capture is a single-task
workflow, however more generalized menu should allow for other applications as
well. We can still achieve single-task workflow with org-capture, by simply not
allowing more then one org-capture menu buffer at a time, it is just that it
won't block entire Emacs. So one could have more than one application of
quick-menu, where for example org-capture is one application, some imaingary
greating-app would be a different application, etc.

>            Capture data are stored in global variables, so parallel captures 
> may
> cause problems. Likely it is assumed that a user quickly selects template and
> necessary data are added to the target document buffer.

Exactly.  It is important that org-capture is one capture at the time so people
don't mess their note files, agenda files etc.

>                                                         Unsure if some
> intermediate persistent store would be an improvement.

Not sure what you mean here, but I don't plan to change anything in org-capture
itself, it should still be one-task at the time.

> The following complain is mainly related to selection of a window to show the
> menu, but it should have in mind that some people use Emacs as window manager
> and menu should not hide windows related to current activity.
>
> Eric S Fraga. Re: Bug: org-no-popups disregards
> display-buffer-fallback-action. Mon, 15 Nov 2021 09:57:46
> +0000. https://list.orgmode.org/87fsrxeo6d.fsf@ucl.ac.uk
>
> Likely nobody performed any steps toward `transient' as the interface, but due
> to such requests it would be nice to have possibility to switch between menu
> implementations.

I am not building some generalized framework, as I said in my first respone to
Ihor :-). 



reply via email to

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