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: Max Nikulin
Subject: Re: Proposal: 'executable' org-capture-templaes
Date: Thu, 30 Jun 2022 00:02:11 +0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.9.1

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

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.

P.S. I am sorry for long delay.




reply via email to

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