god-mode icon indicating copy to clipboard operation
god-mode copied to clipboard

Rebind more commands than just self-insert-command

Open jamienicol opened this issue 10 years ago • 6 comments

Some modes bind some keys to functions other than self-insert-command. This is so that they can do something clever as well as insert the character. eg. in c-mode "/" is bound to c-electric-slash. This means that when in god-mode, pressing these keys will still insert the character instead of doing C-key.

I have these workarounds in my init.el:

(define-key god-local-mode-map [remap c-electric-slash] 'god-mode-self-insert)
(define-key god-local-mode-map [remap c-electric-brace] 'god-mode-self-insert)
; etc

This appears to have been encountered by people before (tickets #16 and #41). I'd imagine that "/" doing c-electric-slash instead of undo is a common problem. Perhaps it would be sensible to have a customisable list of commands god-mode should remap, and maintain a default list (which people are encouraged to submit pull requests to modify, like for god-exempt-major-modes).

Or perhaps not, in which case feel free to close and I'll just stick with remapping some commands myself.

jamienicol avatar Jul 09 '14 18:07 jamienicol

Even if you decide against god mode remapping more commands, a note in the readme showing how to do this would be really helpful. It took me a wee while to work out, so I'm sure it'd help others too!

(Thanks for making god mode by the way, only been using it a few days but I'm really liking it so far!)

jamienicol avatar Jul 09 '14 18:07 jamienicol

I've had to remap some things too, like / in html-mode. Adding these suggestions in the README sounds like a good idea.

chrisdone avatar Jul 11 '14 09:07 chrisdone

Ideally god-mode could work in a different way to solve this problem more generally, but I have no idea how to implement that -- I love the idea behind god-mode but it sometimes acts a bit weirdly and sometimes you still need to use ctrl. (For C-g if nothing else, but also sometimes for other things like C-/ in C-mode if you haven't remapped it specifically.)

snan avatar Sep 03 '16 19:09 snan

Based on this Stackoverflow answer I added this to my god-mode-enabled-hook and it appears to solve this issue. Basically it just makes sure that the god-mode local map is always first in the list of minor mode key maps.

(defun god-has-priority ()
  "Try to ensure that god mode keybindings retain priority over other minor modes."
  (unless (and (consp (car minor-mode-map-alist)) 
               (eq (caar minor-mode-map-alist) 'god-local-mode-map))
    (let ((godkeys (assq 'god-local-mode minor-mode-map-alist)))
      (assq-delete-all 'god-local-mode minor-mode-map-alist)
      (add-to-list 'minor-mode-map-alist godkeys))))

qazmonk avatar Dec 15 '16 01:12 qazmonk

In the Emacs Lisp manual I read that minor-mode-map-alist comes after emulation-mode-map-alists. What if God mode would add god-local-mode-map to emulation-mode-map-alists instead of minor-mode-map-alist when initializing? Isn't God mode more an emulation mode than an ordinary minor mode anyway?

First, it could solve what the previously suggested adding of god-has-priority to god-mode-enabled-hook solves.

Second, it could help to get God mode in command state of Viper mode (vi emulation).

Currently the second is not possible because the keymaps of Viper mode are in emulation-mode-map-alists and therefore god-mode-self-insert even with god-has-priority is too late. As a workaround I tried

(add-to-ordered-list 'emulation-mode-map-alists 'god-local-mode-map 50)

and it added god-local-mode-map in front of viper--intercept-key-maps and viper--key-maps as expected but for example b is still bound to viper-backward-word instead of god-mode-self-insert when god-local-mode is on. How can I make this work?

brandm avatar Jul 03 '18 16:07 brandm

The following solution has worked for me in evil-mode/evil-god-state, but should be adaptable generally:

  • Move god-local-mode-map entry to the front of emulation-mode-map-alists, as in @brandm's answer. (In my Evil setup, I instead achieve this by setting god-local-mode-map as an "intercept map," using the Evil-specific sense of that term. Evil's emulation map alist already comes first within my emulation-mode-map-alists so this effectively gives god-local-mode-map priority over all other keymaps.)
  • Create a separate keymap containing the extra keybindings you want available in God mode. I use (make-composed-keymap (current-active-maps)) to suck up all active keybindings just before entering God mode.
  • Use set-keymap-parent to set this keymap as the parent keymap of god-local-mode-map. This way, all its bindings get priority just below God mode's special self-insertion bindings, but still override anything below.

fishyfriend avatar Apr 04 '20 23:04 fishyfriend