Emacs evil: general window movement remap - emacs

This is the question I should have asked instead of this:
Emacs evil: space as a prefix key in motion state
I want to define a bunch of commands for moving, moving between, opening and closing windows and buffers that works in all states except insert mode, and are all of the form "SPC ". It would be nice to be able to set this once and be fine everywhere (except when there are conflicts, though overriding would be fine), but if that isn't easy, I would also like to know how to override keybindings in new states that I run across where my keybindings don't work. Hopefully knowing that would also help me edit keybindings in arbitrary states.
What I currently have is this:
(define-key evil-normal-state-map (kbd "SPC") nil)
(define-key evil-motion-state-map (kbd "SPC") nil)
(define-key evil-motion-state-map (kbd "SPC h") 'evil-window-left)
(define-key evil-motion-state-map (kbd "SPC j") 'evil-window-down)
(define-key evil-motion-state-map (kbd "SPC k") 'evil-window-up)
(define-key evil-motion-state-map (kbd "SPC l") 'evil-window-right)
(define-key evil-normal-state-map (kbd "SPC h") 'evil-window-left)
(define-key evil-normal-state-map (kbd "SPC j") 'evil-window-down)
(define-key evil-normal-state-map (kbd "SPC k") 'evil-window-up)
(define-key evil-normal-state-map (kbd "SPC l") 'evil-window-right)
and "SPC H" and so on for moving windows. It doesn't work in list-buffers or Dired. Evil leader only seems to work for normal mode.

We meet again.
Perhaps it'd be simpler to define a prefix keymap and bind to it. For example:
(define-prefix-command 'my-window-map)
(let ((map my-window-map))
(define-key map "h" 'evil-window-left)
(define-key map "j" 'evil-window-down)
(define-key map "k" 'evil-window-up)
(define-key map "l" 'evil-window-right)
(define-key map "H" 'evil-window-move-far-left)
(define-key map "J" 'evil-window-move-very-bottom)
(define-key map "K" 'evil-window-move-very-top)
(define-key map "L" 'evil-window-move-far-right)
;; And presumably, for opening/closing
(define-key map "v" 'evil-window-vsplit)
(define-key map "s" 'evil-window-split)
(define-key map "c" 'evil-window-delete))
Then you can map the prefix keymap to SPC in various modes:
;; Do this for each state you want these bindings available
(define-key evil-motion-state-map " " 'my-window-map)
(define-key evil-visual-state-map " " 'my-window-map)
;; You don't need to unbind/rebind evil-normal-state-map --
;; there is no default mapping for " ". Also: unbound keys in normal
;; mode will fall through to motion bindings.
;; For particular modes (like dired and list-buffer window)
(define-key dired-mode-map " " 'my-window-map)
(define-key Buffer-menu-mode-map " " 'my-window-map)
Alternatively, you can have dired and list-buffer start in normal mode. This will likely interfere with their default mappings.
(evil-set-initial-state 'dired-mode 'normal)
(evil-set-initial-state 'Buffer-menu-mode 'normal)
If you find your mapping overridden by another mode (which shouldn't be common for that key), you can try adding my-window-map to evil-overriding-maps: (add-to-list 'evil-overriding-maps '(my-window-map)). This supposedly gives those maps precedence.
Disclaimer: I haven't tested this. I find it simpler to undefine keys in conflicting plugins.
On a side note, all these commands are already available in evil-window-map. It may be simpler for you to map SPC to that:
(define-key evil-motion-state-map " " 'evil-window-map)
(define-key evil-visual-state-map " " 'evil-window-map)
...

Related

Evil in emacs: cannot remap "s": buffer is read-only

I'm trying to remap some evil keys to navigate using htns. htn works fine, but s always gives me the "buffer is read-only" error. I'm assuming I need to remap save buffer, but I'm getting lost in the key rebinding api. My .emacs looks like
(define-key evil-motion-state-map (kbd "n") 'evil-next-line)
(define-key evil-motion-state-map (kbd "s") 'evil-previous-line)
(define-key evil-motion-state-map (kbd "h") 'evil-forward-char)
(define-key evil-motion-state-map (kbd "t") 'evil-backward-char)
It's ok if IĀ use the normal state map instead:
(define-key evil-normal-state-map (kbd "s") 'evil-previous-line)
Does that suit your needs ?
I guess you had this error because the binding was not working.

Smex in Evil mode

I'm using Evil mode and would now like to use smex so that when I press ":" in evil mode I get smex. This is what I have now in my Emacs file:
(define-key key-translation-map (kbd ";") (kbd ":"))
(define-key key-translation-map (kbd ":") (kbd ";"))
This is obviously not enough to enter smex.
The following bindings allow you to use : to get smex and ; to get to Ex mode, which is what you seem to want from your example:
(define-key evil-motion-state-map ":" 'smex)
(define-key evil-motion-state-map ";" 'evil-ex)
(Note that normal state inherits from motion state.)

Unbinding Evil's C-w mappings?

I'm trying out Emacs with Evil mode.
I'd like to use C-w as a prefix for my own window manipulation shortcuts that are defined globally, not just for buffers with Evil mode. I have the following code in my init.el
(define-prefix-command 'my-window-map)
(global-set-key (kbd "C-w") 'my-window-map)
(define-key my-window-map (kbd "h") 'windmove-left)
(define-key my-window-map (kbd "j") 'windmove-down)
(define-key my-window-map (kbd "k") 'windmove-up)
(define-key my-window-map (kbd "l") 'windmove-right)
(define-key my-window-map (kbd "v") 'split-window-right)
(define-key my-window-map (kbd "b") 'split-window-below)
(define-key my-window-map (kbd "x") 'delete-window)
(define-key my-window-map (kbd "o") 'delete-other-windows)
This works if Evil is not loaded, but when I load Evil it overwrites any conflicting maps (C-w b for example).
I can also comment out L106-158 and L236 from evil-maps.el and my maps work, but I would rather not deal with modifying evil-maps.el.
Is there a way to prevent Evil from using the C-w prefix, or unset it afterwards?
The C-w prefix switches you into the evil-window-map, so undefining C-w in that map will not help. The key mapping in the "evil-maps" file that is relevant sets C-w in evil-motion-state-map to evil-window-map, and that binding is inherited by most of the other evil maps. You could set that keybinding to nil so you can use your own binding in this way:
(eval-after-load "evil-maps"
(define-key evil-motion-state-map "\C-w" nil))
However, neither evil-insert-state-map nor evil-emacs-state-map inherit in this way (I'm pretty sure), so you'll need to unbind in those maps as well. So use the following to unbind in all 3 maps in one fell swoop:
(eval-after-load "evil-maps"
(dolist (map '(evil-motion-state-map
evil-insert-state-map
evil-emacs-state-map))
(define-key (eval map) "\C-w" nil)))
You could also replace the nil with 'my-window-map to rebind to your own mapping, but it's probably already exposed via your call to global-set-key.
The easiest way to do something after some package is loaded is using eval-after-load. In your example, you could put this in your .emacs:
(defun set-control-w-shortcuts ()
(define-prefix-command 'my-window-map)
(global-set-key (kbd "C-w") 'my-window-map)
(define-key my-window-map (kbd "h") 'windmove-left)
(define-key my-window-map (kbd "j") 'windmove-down)
(define-key my-window-map (kbd "k") 'windmove-up)
(define-key my-window-map (kbd "l") 'windmove-right)
(define-key my-window-map (kbd "v") 'split-window-right)
(define-key my-window-map (kbd "b") 'split-window-below)
(define-key my-window-map (kbd "x") 'delete-window)
(define-key my-window-map (kbd "o") 'delete-other-windows))
(set-control-w-shortcuts)
(eval-after-load "evil-maps"
'(progn
(define-key evil-window-map "\C-w" 'nil)
(set-control-w-shortcuts)))

Want to use Space Bar followed by a key instead of C-key in Normal State of Evil Mode in Emacs

I would like to be able to hit the space bar followed by another key as an alternative to hitting Ctrl and than the key in Normal State of Evil Mode.
For example, this is what I've started defining in my .emacs file:
(define-key evil-normal-state-map " ww" 'evil-window-next)
(define-key evil-normal-state-map " wr" 'evil-window-rotate-downwards)
(define-key evil-normal-state-map " wR" 'evil-window-rotate-upwards)
(define-key evil-normal-state-map " wo" 'delete-other-windows)
(define-key evil-normal-state-map " wn" 'evil-window-new)
(define-key evil-normal-state-map " wl" 'evil-window-right)
(define-key evil-normal-state-map " wh" 'evil-window-left)
(define-key evil-normal-state-map " wj" 'evil-window-down)
(define-key evil-normal-state-map " wk" 'evil-window-up)
From what I know so far, it seems as if I can only define a key sequence as a given function, and not as as something that wouldn't be used on its own such as Ctrl. Is there a general way of doing this so that the space bar followed by another key would be equivalent to any C-"that key" in Normal State of Evil Mode?
I don't know enough about Evil to give you a specific answer, but you could try
(define-key function-key-map " " 'event-apply-control-modifier)
(define-key evil-normal-state-map " " nil)
Tho the function-key-map binding will only kick in if SPC is "unbound" in all other maps, so binding it to nil in evil-normal-state-map might not be sufficient. Otherwise you can use key-translation-map instead of function-key-map, so the rewrite will take precedence to the normal SPC bindings, but then you'll need to figure out how to enable/disable this binding when enering/leaving Evil's normal state.

emacs -nw issues with cscope and terminals

Few issues with emacs in term windows. Any help is appreciated.
a. I start emacs over ssh with emacs -nw with cscope enabled. After I search for a symbol or a definition, on the cscope buffer when i press 'enter', emacs says - Buffer is read-only. Whereas the same functionality on emacs with xwindows (gtk or anything else) takes me to the file and line on edit buffer. How can I have the same functionality with 'emacs -nw'.
b. Also the arrow mark on edit/source buffer when i do next reference for symbol from cscope buffer stays on the edit buffer. How can I make it go?
c. My keys are mapped to cscope functions just like in xcscope.el. All the control keys expect Ctrl-F3 and Ctrl-F4 work. How can I enable this too.
Thanks much,
a. Add the following to your .emacs file:
(define-key global-map (kbd "\r") [return])
I got the answer from http://weenix.cs.brown.edu/mediawiki/index.php/Cscope
b. If you hit the space bar in the cscope buffer, you will get the arrow. It's just a display thing; the file has not changed. If you want to get rid of it, add the following to your .emacs file:
(setq cscope-allow-arrow-overlays nil)
terminal send different key sequences than emacs may be expecting. you need to provide translations for the terminal type in order to get emacs to work correctly. for example, i have this config to setup the terminal i use (the weird char is a literal "escape" char, which you can type in using "C-q <esc>":
(let ((map (if (boundp 'input-decode-map)
input-decode-map function-key-map)))
(define-key map (kbd "RET") [return])
(define-key map "[OA" (kbd "<C-up>"))
(define-key map "[OB" (kbd "<C-down>"))
(define-key map "[OC" (kbd "<C-right>"))
(define-key map "[OD" (kbd "<C-left>"))
(define-key map "[A" (kbd "<C-up>"))
(define-key map "[B" (kbd "<C-down>"))
(define-key map "[C" (kbd "<C-right>"))
(define-key map "[D" (kbd "<C-left>"))
(define-key map "OA" (kbd "<M-up>"))
(define-key map "OB" (kbd "<M-down>"))
(define-key map "OC" (kbd "<M-right>"))
(define-key map "OD" (kbd "<M-left>"))
(define-key map "[OA" (kbd "<M-C-up>"))
(define-key map "[OB" (kbd "<M-C-down>"))
(define-key map "[OC" (kbd "<M-C-right>"))
(define-key map "[OD" (kbd "<M-C-left>"))
(define-key map "[[17~" (kbd "<C-f6>"))
(define-key map "[[18~" (kbd "<C-f7>"))
(define-key map "[[19~" (kbd "<C-f8>"))
(define-key map "[[20~" (kbd "<C-f9>"))
(define-key map "[[21~" (kbd "<C-f10>"))
(define-key map "[[23~" (kbd "<C-f11>"))
(define-key map "[[24~" (kbd "<C-f12>"))
(define-key map "\e[1~" [home])
(define-key map "\e[4~" [end])
(define-key map "\e\e[1~" [M-home])
(define-key map "\e\e[4~" [M-end])
)
in some terminals, you can get the key code by typing "C-v" and then the desired keys. this should output the actual keycodes that the terminal sends for the keys you pressed after the "C-v".