3

I am writing my first minor mode, and would like to understand how to bind a key to an action in that mode.

(define-minor-mode hello-mode
  "My Mode"
  :init-value nil
  :lighter " Hello"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map (kbd "M-p")
              (lambda ()
                (interactive)
                (message "HI!!!")))
            map)
  :group 'hello)

After running this followed by M-x hello-mode (or (hello-mode t)), I would hope that hitting M-p would display "HI!!!" in the echo area, but Emacs tells me M-p is still undefined.

What else is needed to bind a key to a function when my minor mode is active?

1 Answer 1

5

Your code works perfectly, for me. Did you try it in emacs -Q (no init file)?

And if I load library help-fns+.el and then use M-k hello-mode-map it shows me that M-p is bound to an (anonymous) command.

However, I recommend that you give your keymap a name (a symbol). That helps users (and yourself) more.


(If you have an Emacs 28 preview then you also have that command, describe-keymap - it's been added to Emacs itself.)

2
  • 1
    It was very helpful to me to know it worked for someone else. Restarted Emacs with a minimal config, then my full config, and it worked with no issues (!!).
    – JohnJ
    Sep 8, 2021 at 1:14
  • 1
    @JohnJ: define-minor-mode generates a defvar when :keymap specifies a keymap value directly. As evaluating a defvar doesn't overwrite an existing value for that variable, re-evaluating the define-minor-mode form with an updated keymap value won't change any existing value of that variable. This probably explains what was happening for you. Note that you can (makunbound 'VAR) if necessary.
    – phils
    Dec 3, 2022 at 2:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.