Re: On keybindings and the slow erosion of help's utility
Ihor Radchenko <[email protected]> Sun, 02 Aug 2026 09:38:02 +0000
| Newsgroups | gmane.emacs.devel |
|---|---|
| Message-ID | <871pcg982o.fsf@localhost> |
Stefan Monnier <[email protected]> writes: >> But in the API I described, each condition can only return nil, command, >> or keymap. If our (org-metaright--try-hook) already executed the >> command, it cannot return nil - that would make us search further, which >> we do not want. It cannot return a command or keymap either - we do not >> want to execute those. Maybe, we can treat non-keymap, non-command >> return value as "stop here, we are done". That's an option, yes. > > I'd let the condition return a dummy command like `ignore`, just > like we already do for similar purposes in keymaps. AFAIU, that only works because `ignore' is an actual command that is executed. If we just handle it as it is currently done, we will end up executing *2 commands* - one triggered by `org-metaright--try-hook', and also `ignore'. That will mess up `this-command' and others. >>>> I proposed a very particular shape for those (to be implemented inside >>>> user-level `keymap-dynamic-bind'), but we do not have to hard-code the= m. >>> >>> I see. I'm trying to look at it from the `C-h k` side where we want the >>> API to be minimalist (the hard coding of sub-elements would be fine on >>> the side of helper macros/functions to define&set such "dynamic keymaps= "). >> >> That's what I meant by >> >> (dynamic-bind >> :filter FILTER-FN ; runs hook: hook =E2=86=92 command/keymap= /nil >> :doc DOC-FN ; (dynamic-binding) =E2=86=92 string for C= -h k >> :enumerate ENUM-FN ; (dynamic-binding) =E2=86=92 list for whe= re-is >> :default COMMAND) ; fallback when hook returns nil >> >> :doc is a custom function that will take care about rendering >> documentation. The `keymap-dynamic-bind' will define a particular >> standard shape of :doc function, but it can be anything. > > Ah, I see, so that would be the "equivalent" in your model to my > `composite-command`. > > [ FWIW, my mental model of `partial-binding` and `composite-command` are > OClosures, for which we can already define dynamic docstrings via > `cl-defmethod`. I'm thinking that we'd have two subtypes of > `partial-binding`: those that have a condition and a command (active > only when the (side-effect free) condition is satisfied), and those > that have only a command (which returns nil to indicate that it didn't > do anything and we should keep trying with others, i.e. for when the > condition can't be side-effect free). ] Yes, OClosures are a good idea here. In contrast to the hook-inspired system I am proposing, OClosures can hold a shared state between different conditions. That would, for example, simplify tracking things like old-tick, old-point, and old-indent in the `indent-for-tab-command' to be reused by multiple conditions. However, I am not quite sure about how to deal with docstrings in OClosures, especially with my idea with indicating the matching condition as in =E2=97=8B True if point is at a block. =E2=86=92 org-indent-bl= ock =E2=97=8F At a heading. =E2=86=92 org-do-demote I imagine that we will need to have a special way to call OClosure holding the dynamic binding that will avoid side effects. I am also not sure about facilities to manipulate the proposed OClosures. Could you give some examples that are less trivial than just chaining simple conditions? >>> OTOH, it's fine *if* `lookup-key` doesn't evaluate the conditions and >>> just returns the whole dynamic keymap. >> Sure. > > But that brings us back to whether the conditions are evaluated during > keymap lookup or afterwards. >> I think https://elpa.nongnu.org/nongnu/casual.html as a whole is a >> counterexample to your intuition. It defines whole keymaps depending on >> cursor location. For example, see >> https://elpa.nongnu.org/nongnu/doc/casual.html#Dired-Usage >> >> Another example is context menus :) > > But these are "all keymaps" aren't they? Hmm. Yeah. You are right. I need a better example :) Here is a better example: In Org mode, C-c C-c can sometimes invoke an Org menu, and sometimes just calls a command. On headings, with org-use-fast-tag-selection set to t, Org mode uses an equivalent of repeat map to toggle tags. On source blocks, C-c C-c simply runs the code block. More generally, limiting the dynamic keymap to only return keymaps or only commands /feels/ like artificial limitation. >> One important thing in this code that we did not discuss yet is prefix >> argument. It will need to be passed to the conditions. > > Yup. That's easy if we evaluate the conditions when we run the command > rather than when we lookup the keymap. It is easy either way. Just via current-prefix-arg. We just need to make sure that it is available within conditions. --=20 Ihor Radchenko // yantar92, Org mode maintainer, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92>