help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: Eval keymapp in a macros


From: Arthur Miller
Subject: Re: Eval keymapp in a macros
Date: Wed, 04 Aug 2021 11:38:55 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Yuri Khan <yuri.v.khan@gmail.com> writes:

> On Wed, 4 Aug 2021 at 04:20, Arthur Miller <arthur.miller@live.com> wrote:
>
>> Here is example from my init file (with conses):
>>
>>              (with-key-map global
>>                            ;; Window-buffer operations
>>                            ("C-<insert>"    . term-toggle)
>>                            ("<insert>"      . term-toggle-eshell)
>>                            ([f9]            . ispell-word)
>>                            ([S-f10]         . next-buffer)
>>                            ([f10]           . previous-buffer)
>>                            ([f12]           . kill-buffer-but-not-some)
>>                            ([M-f12]         . kill-buffer-other-window)
>>                            ([C-M-f12]       . only-current-buffer))
>
> Two observations from the side:
>
> * “with-*” naming is usually used for context manager macros. That is,
> a macro initializes some resource or performs some temporary changes,
> then executes the body, then does any necessary cleanup. You don’t
> have any of that here.

Yes indeed, I am aware, back when I named it I was thinking like "with
this keymap do this ..." so I actually crapped on the convention indeed.
I agree with you, and since I have rewrote it, to use a list of pairwise
elements instead of cons I have also renamed it to "defkeys", to
actually shorten the name, but it also does not violate the convention.

> * If you sacrifice a quote and a pair of braces, you can have your
> typing saving as a simple function:
>
>     (my-define-keys global-map
>       '(("C-<insert>" . term-toggle)
>         ("<insert>" . term-toggle-eshell)
>         …))

I know, but I wish the least noise as possible :-):

(defmacro defkey (mapname &rest body)
  `(let ((defs '(,@body)))
     (while defs
       (define-key ,mapname
         (if (vectorp (car defs))
             (car defs)
           (read-kbd-macro (car defs)))
         (if (or (listp (cadr defs))
                 (functionp (cadr defs)))
             (cadr defs)
           (if (eval`(keymapp ,(cadr defs)))
               (eval (cadr defs)))))
       (setq defs (cddr defs)))))



Than the usage looks like this

(setq pkg-ops-map
  (let ((map (make-sparse-keymap "Packages")))
    (defkey map
      "h" ("describe" . describe-package)
      "a" ("autoremove" . package-autoremove)
      "d" ("delete" . package-delete)
      "i" ("install" . package-install)
      "s" ("selected" . package-install-selected-packages)
      "r" ("refresh" . package-refresh-contents)
      "l" ("list" . list-packages))
  map))

(defkey global-map "C-c p" pkg-ops-map)

(defkey global-map "s-1" pkg-ops-map)
(defkey global-map "s-1" list-packages)
(defkey global-map "s-1"  ("list" . list-packages))


Or the init file exammple:


(defkey global-map
  ;; Window-buffer operations
  "C-<insert>"    term-toggle
  "<insert>"      term-toggle-eshell
  [f9]            ispell-word
  [S-f10]         next-buffer
  [f10]           previous-buffer
  [f12]           kill-buffer-but-not-some
  [M-f12]         kill-buffer-other-window
  [C-M-f12]       only-current-buffer)


I just would like to understand why order of lisp/functionp matters and
how can I get read of those two eval's, if possible.



reply via email to

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