1

I have my own user defined key-bindings as described here: Globally override key binding in Emacs

Whenever I load a new major mode, say OrgMode, I have some of my bindings over-written to fit my needs in that specific mode. But then when I load another major mode, which have its own over-writes, they stay put even if I'm not in a buffer with that major mode anymore.

For example

(define-key custom-keys-mode-map (kbd "C-p") 'some-cool-function)
(add-hook 'org-mode-hook
    (lambda ()
    (define-key custom-keys-mode-map (kbd "C-p") 'org-cool-function )))
(add-hook 'sunrise-mode-hook
    (lambda ()
    (define-key custom-keys-mode-map (kbd "C-p") 'sunrise-cool-function )))

At first I use C-p to execute my cool, default, function. After I load Org-Mode I use C-p to execute "org-cool-function", and when I load Sunrise-Commander, C-p executes "sunrise-cool-function".

But then when I go back to an Org-Mode file, C-p still tries to execute "sunrise-cool-function" instead of "org-cool-function".

Hope I'm clear:)

Community
  • 1
  • 1
Devon Ville
  • 2,001
  • 2
  • 19
  • 32

3 Answers3

6

The behavior you see is what is expected from the code. It goes as follows:

  • you launch emacs and some-cool-function gets assigned
  • then whenever you open a new org file (and not just switch buffer to it) org-cool-function gets assigned
  • whenever you launch sunrise-commander sunrise-cool-function gets assigned

Your problem comes from trying to set a global property from a local event.

You should use the org-mode-map instead of custom-keys-mode-map to put your C-p keybinding. This will set it once and for all for every buffer with org content:

(define-key custom-keys-mode-map (kbd "C-p") 'some-cool-function)
(eval-after-load "org"
  '(define-key org-mode-map (kbd "C-p") 'org-cool-function))
Nicolas Dudebout
  • 9,172
  • 2
  • 34
  • 43
  • That's great, but what's the solution?;) – Devon Ville Apr 08 '13 at 19:21
  • Well, wouldn't that beat the purpose of having a custom minor mode from the beginning? To override annoying major mode key bindings that I do not wish or want? – Devon Ville Apr 08 '13 at 19:27
  • But you want a different behavior for the same key in different modes. Therefore you need different key maps. So you could do `custom-keys-mode-map` then `custom-org-keys-mode-map` etc. Using this custom keymap is some kind of a hack. To push it further will require work. The `eval-after-load` I just added should be enough for your case. – Nicolas Dudebout Apr 08 '13 at 19:29
  • Maybe I asked the wrong question. The C-p defined with my custom-mode-map will always get precedence, since it's a minor mode map (unlike org mode, which is a major-mode)... – Devon Ville Apr 08 '13 at 19:33
  • You have a single custom map. This map is used by the entire emacs environment irrespective of mode and buffer. Whenever you open an org file you put a specific function on `C-p`. Whenever you open sunrise-commanded you put a different function on `C-p`. Depending on what was last done your behavior will change. – Nicolas Dudebout Apr 08 '13 at 19:35
  • Only one variable and you want to store three different functions. – Nicolas Dudebout Apr 08 '13 at 19:35
  • I understand and agree with your logic, but the fact still remains - when I define C-p with my custom-mode-map, I can try to assign C-p to org-mode-map until tommorow and it wouldn't work. C-p would still execute "some-cool-function". – Devon Ville Apr 08 '13 at 19:37
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27789/discussion-between-nicolas-dudebout-and-eladr) – Nicolas Dudebout Apr 08 '13 at 19:39
3

Minor mode maps supersede major mode maps which supersede the global map.

So a few options are:

  1. Do not include these bindings in your custom minor mode map at all. Make your preferred binding a plain global binding, and let the major modes over-ride it as required.

  2. Create additional minor modes to take precedence over your existing minor mode, and enable them in the corresponding major modes. Each minor mode's position in minor-mode-map-alist determines precedence when looking up key bindings, so you need these additional modes to be defined after your current mode is defined (meaning that they will appear earlier in the alist), and of course keep them in that order if updating that list dynamically.

  3. Leave everything the way it is, but bind these keys to custom functions which check the major mode and act accordingly. You may or may not need to take care of passing on prefix arguments if you take this approach.

Community
  • 1
  • 1
phils
  • 71,335
  • 11
  • 153
  • 198
0

I've read a couple more threads which led me to believe there is another way, which I'm currently using:.

Currently I'm using this:

;;; Disable Custom keys for specific major modes.
(define-global-minor-mode my-custom-keys-mode custom-keys-mode
  (lambda ()
    (when (not (memq major-mode (list 'sr-mode)))
      (custom-keys-mode))))
(my-custom-keys-mode 1)

which pretty much suits my needs at the moment.

Community
  • 1
  • 1
Devon Ville
  • 2,001
  • 2
  • 19
  • 32