diff options
| author | Thanos Apollo <public@thanosapollo.org> | 2026-04-26 02:54:17 +0300 |
|---|---|---|
| committer | Thanos Apollo <public@thanosapollo.org> | 2026-04-26 02:54:17 +0300 |
| commit | fd1e0b584988ba182ddbd0c7f37fc5cc288c4293 (patch) | |
| tree | d85310a387d02f1b65b69c6f677e9b976873bdb5 | |
| parent | 65f76d097cc0e0f3419e1fa01d4fa52a86a2c639 (diff) | |
readme: Add actual usage examples
| -rw-r--r-- | README.org | 139 |
1 files changed, 89 insertions, 50 deletions
@@ -2,81 +2,120 @@ One macro replaces both your mode keymap and transient menu. -No EIEIO, no transient dependency, single file. +No EIEIO, no transient dependency, single file. Requires Emacs 29.1+. -#+BEGIN_QUOTE -Vendor it into your project. - -Requires Emacs 29.1+. -#+END_QUOTE - -** Example +** Usage #+begin_src emacs-lisp -(define-described-keymap my-mode-map - :group "Actions" - "c" ("Comment" my-comment) - "r" ("Reply" my-reply) - :group "Options" - "V" ("Verbose" :switch my-verbose-var) - "n" ("Limit" :option my-limit-var :reader read-number :prompt "Limit: ") - :row - :group "Navigate" - "g" ("Refresh" my-refresh) - "q" ("Quit" quit-window)) + (define-described-keymap my-mode-map + "My mode commands." + :group "Actions" + "c" ("Comment" my-comment) + "r" ("Reply" my-reply) + "x" ("Toggle" my-toggle) + :group "Navigate" + "g" ("Refresh" my-refresh) + "q" ("Quit" quit-window)) + + (define-derived-mode my-mode special-mode "My" + (use-local-map my-mode-map)) #+end_src -This gives you a real =defvar-keymap= you can use directly with =use-local-map=. Press =h= to see the popup. - -Infixes stay open and re-render when toggled. Suffixes close the popup and dispatch. =q= dismisses. +This produces a real =defvar-keymap=. Keys work directly in the mode. +Press =h= for the popup. -** Switches and options - -Switches are buffer-local booleans. Options are buffer-local values set via a reader function. Your commands read them directly: +** Infixes #+begin_src emacs-lisp -(defun my-list () - (interactive) - (my-fetch :verbose my-verbose-var - :limit my-limit-var)) + (define-described-keymap my-list-map + :group "Options" + "V" ("Verbose" :switch my-verbose-var) + "n" ("Limit" :option my-limit-var :reader read-number :prompt "Limit: ") + :group "Actions" + "l" ("List" (lambda () (interactive) + (my-fetch :verbose my-verbose-var + :limit my-limit-var)))) #+end_src -** Conditional entries +Switches toggle buffer-local booleans. Options set buffer-local +values via a reader. Pressing an infix key re-renders the popup +without closing it. + +** Sub-menus #+begin_src emacs-lisp -"s" ("Secret" my-secret-cmd :if (lambda () my-verbose-var)) + (define-described-keymap my-metadata-map + :group "Add" + "l" ("Label" my-add-label) + "a" ("Assignee" my-add-assignee) + "m" ("Milestone" my-set-milestone)) + + (define-described-keymap my-view-map + :group "Actions" + "c" ("Comment" my-comment) + "a" ("Metadata" :keymap my-metadata-map) + :group "Navigate" + "q" ("Quit" quit-window)) #+end_src -Hidden from the popup when the predicate returns nil. The keybinding still exists. +Press =a= to enter the sub-menu. =q= or =C-g= goes back. -** Dynamic descriptions +** Inheritance #+begin_src emacs-lisp -"s" ((lambda () (format "Submit (%s)" branch)) my-submit) + (define-described-keymap view-base-map + :group "Common" + "g" ("Refresh" my-refresh) + "b" ("Browse" my-browse) + "q" ("Quit" quit-window)) + + (define-described-keymap issue-view-map + :parent view-base-map + :group "Issue" + "c" ("Comment" my-comment) + "x" ("Close" my-close)) + + (define-described-keymap pull-view-map + :parent view-base-map + :group "Pull Request" + "c" ("Comment" my-comment) + "m" ("Merge" my-merge)) #+end_src -** Layout +Both =issue-view-map= and =pull-view-map= inherit Refresh, Browse, and +Quit from =view-base-map=. The popup shows entries from both child +and parent. -- =:group= starts a new column. -- =:row= starts a new line of columns. +** Conditional and inapt entries -Columns align across rows. +#+begin_src emacs-lisp + (define-described-keymap my-map + :group "Actions" + "c" ("Comment" my-comment) + ;; hidden when verbose is off + "d" ("Debug info" my-debug :if (lambda () my-verbose-var)) + ;; visible but grayed out when merge is not possible + "m" ("Merge" my-merge :inapt-if (lambda () (not (my-can-merge-p))))) +#+end_src -** Extending from outside +** Prefix argument #+begin_src emacs-lisp -(keymap-popup-add-entry 'my-mode-map "z" "New action" #'my-action "Actions") -(keymap-popup-remove-entry 'my-mode-map "z") + (define-described-keymap my-map + :group "Actions" + "s" ("Submit" my-submit :c-u "force push") + "g" ("Refresh" my-refresh)) #+end_src -** Options +In the popup, =C-u= enters prefix mode: entries with =:c-u= are +highlighted, others are dimmed. The next key dispatches with the +prefix argument. =C-g= cancels prefix mode. -Docstring is optional. Popup key defaults to =h=, change it with =:popup-key=: +** Other features -#+begin_src emacs-lisp -(define-described-keymap my-map - "My commands." - :popup-key "?" - :group "Actions" - "c" ("Comment" my-comment)) -#+end_src +- =:stay-open t= on a suffix keeps the popup open after dispatch +- =:popup-key "?"= changes the popup key (default =h=) +- Dynamic descriptions: use a function instead of a string +- Dynamic group names: =:group (lambda () (format "Items (%d)" count))= +- =:row= starts a new row of columns in the popup layout +- =keymap-popup-add-entry= / =keymap-popup-remove-entry= for runtime modification |
