Emacs keybinding not working in custom major mode
Asked Answered
S

3

6

I'm in the early stages of creating a major mode for Emacs for browsing and interacting with the Stack Exchange Network.

Involved in it are several major modes, all with one-key keybindings similar to dired. I looked at the source for dired, and extracted what I thought would work:

(defvar stack-network-mode-map
  (let ((map (make-keymap)))
    (define-key map "n"     'stack-network-next-site)
    (define-key map "p"     'stack-network-previous-site)
    (define-key map ","     'stack-network-move-site-up)
    (define-key map "."     'stack-network-move-site-down)
    (define-key map "j"     'stack-network-jump-to-bookmarks)
    (define-key map "\C-m"  'stack-network-do-enter-site) ; ret
    (define-key map "o"     'stack-network-do-enter-site)
    (define-key map "u"     'stack-network-do-profile-summary)
    (define-key map "\C-uu" 'stack-network-do-profile-summary-for-user)
    (define-key map "i"     'stack-network-do-inbox)
    (define-key map "b"     'stack-network-toggle-bookmark)
    (define-key map "?"     'stack-network-list-functions) ; [1]
    (define-key map "\C-i"  'stack-network-display-details) ; tab
    map)
  "Keymap for Stack Exchange: Network Browser major mode")

but unfortunately this seems to have absolutely no effect; the buffer is simply edited just as any other normal buffer would be. How can I achieve single-key keybindings if this isn't they way? (Which, by the way, I'm sure it is. There has to be something else going on here.)

Shoifet answered 27/2, 2013 at 23:47 Comment(2)
Need more detail.... I load the package you refer to, and it works just fine. All the major mode bindings are available (though undefined).Telegraph
Don't define major modes with defun. Use define-derived-mode, which handles all the boilerplate for you, including killing local variables, switching the key map, setting major mode vars, running the hooks, etc.Revulsive
Z
4

You want to define stack-network-mode using define-derived-mode (and make it derive from special-mode, for example).

Other comments about your code:

  • use () rather than nil for empty argument lists.
  • stack-network-next-site needs to have (interactive) right after the docstring to make it an interactive command otherwise it won't work as a key-binding.

If you don't want to use special-mode, you can call supress-keymap right after creating your make-keymap.

Zigmund answered 28/2, 2013 at 1:50 Comment(10)
This does prevent buffer editing (thanks to special-mode, I presume), but the keys are still not being bound :( (Also, to my knowledge, () === nil.)Shoifet
If you'd like to see the code as it stands, it's here (specific commit linked to preserve use for future reference)Shoifet
@vermiculus () === nil holds, but it is convention to use () for empty argument lists. nil at this place looks disturbing to most Emacs Lisp programmers.Revulsive
@lunaryorn I'll keep that in mind -- I've mostly used it because it is much faster for me to type, and the idea of 'nil arguments' still makes sense. But if it's convention we're after, I suppose I'll oblige. I'm still stuck though; see the first two comments.Shoifet
Move the definition of stack-network-mode-map before the define-derived-mode form. Otherwise define-derived-mode defines stack-network-mode-map implicitly with a newly created keymap. defvar however does not change the value of variables which are already set.Revulsive
@lunaryorn, would you please edit that into the answer? That's what fixed it for good!Shoifet
@vermiculus I have added this as a new answer.Revulsive
It's unfortunate then that all I can give you is an upvote there.Shoifet
@vermiculus I do not care for votes and reputation on my answers.Revulsive
@lunaryorn it's only fair. This is as much part of the solution as the accepted answer -- I would not have easily put together the fact that defvar is a little silly and define-derived-mode had the behavior. At its core, upvoting is a way of saying 'thanks.'Shoifet
R
3

Move the definition of stack-network-mode-map before the definition of the mode. Otherwise define-derived-mode implicitly defines this variable, and defvar does not change the value of non-nil variables, so the map will be empty actually.

See Derived Modes:

The new mode has its own sparse keymap, named variant-map. define-derived-mode makes the parent mode's keymap the parent of the new map, unless variant-map is already set and already has a parent.

Revulsive answered 1/3, 2013 at 16:26 Comment(0)
N
0

You have defined a keymap but you have not used it. The variable exists but does not capture any key events.

(use-local-map stack-network-mode-map)
Nimwegen answered 28/2, 2013 at 0:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.