33

For example, in the codes of zen-coding, the "C-j" shadows the normal behavior of "C-j" (newline-and-indent)

(define-key zencoding-mode-keymap (kbd "C-j") 'zencoding-expand-line)

Then how can I unset this keybinding and use C-j for newline-and-indent again?

I tried this, but it doesn't work:

(add-hook 'html-mode-hook
          (lambda ()
            (progn
              (zencoding-mode)
              (local-set-key (kbd "C-j") 'newline-and-indent))))

Does anyone have ideas about this?

Hanfei Sun
  • 45,281
  • 39
  • 129
  • 237
  • Anyone knows why the `add-hook` is not working in this case? – darksky Oct 14 '13 at 16:41
  • 1
    Nayefc: That code doesn't affect zencoding-mode's keymap because zencoding-mode is a minor mode, and (as per the answer below) local-set-key affects the major mode's keymap. Minor mode keymaps take precedence over major mode keymaps, so the unmodified zencoding-mode binding continued to be used. – phils Nov 24 '13 at 22:06

1 Answers1

54

The general way to unbind a key (for any keymap) is to define a binding of nil:

(define-key KEYMAP KEY nil)

For convenience, there are also two standard functions for unbinding from the global keymap and from the local keymap (which is usually the major mode's keymap).

  • (global-unset-key KEY)
  • (local-unset-key KEY)

Those ones are interactive commands, as per their respective complements global-set-key and local-set-key.

As to your specific example, you probably want something like this:

(with-eval-after-load "zencoding-mode"
  (define-key zencoding-mode-keymap (kbd "C-j") nil))

For the benefit of other readers trying to do similar things, those arguments are "zencoding-mode" because the library being loaded is named zencoding-mode.el (note that you should omit the ".el" suffix); and zencoding-mode-keymap rather than the typical/expected zencoding-mode-map because zencoding-mode.el is unusual in explicitly declaring its keymap and not using the standard name for it.

Use C-hk to check what the key in question is bound to, and Emacs will tell you both the name of the keymap and the name of the library, which establishes both arguments.

phils
  • 71,335
  • 11
  • 153
  • 198
  • 1
    Perfect answer I would say. – PascalVKooten Dec 20 '12 at 06:54
  • 99% of the time this is exactly what you want. However, I got tripped up yesterday and figured I'd make a comment since it's still fresh in my head. Some keymaps have default bindings, i.e. any key that isn't explicitly bound defaults to some command instead of nothing. In my case it was isearch-mode-map, which defaults to isearch-other-meta-char for keys starting with M- or ESC. – jpkotta Dec 20 '12 at 16:24
  • 2
    Maybe this should be a whole question, but what is a good way to figure out the name of the keymap if I don't already know what it is? – Samuel Edwin Ward Jun 08 '15 at 16:49
  • 2
    @SamuelEdwinWard Use C-h k , then type the keybinding – Vivi Sep 18 '15 at 09:12
  • @Vivi, that got me a lot of text but I don't see the name of the keymap in there. – Samuel Edwin Ward Sep 18 '15 at 16:22
  • 1
    Samuel Edwin Ward: See http://emacs.stackexchange.com/questions/653/how-can-i-find-out-in-which-keymap-a-key-is-bound – phils Sep 19 '15 at 00:51
  • Doesn't work for me. I'm doing in diff-mode `(define-key diff-mode-map (kbd "") nil)`, but the keybinding still scrolls the screen. – Hi-Angel Oct 19 '18 at 12:38
  • Oh, nvm, it seems Emacs doesn't understand `backspace` even though it's shown in help. Works with `M-DEL` instead. – Hi-Angel Oct 19 '18 at 12:42
  • 1
    @Hi-Angel Emacs is probably showing you `M-DEL (translated from )`, no? The diff-mode-map binding is for `M-DEL` not for `` (and the latter was translated before diff-mode-map was ever looked at). – phils Oct 19 '18 at 12:44