I'm using a fresh install of ubuntu 16.04, with the bash shell. There are two things that I want to do:
- Set up vi mode so I can have vim-like movements from the terminal
- exit insert mode by typing
jk
I read in another post how this can be done with zsh
, how can I do it with bash
?
tl;dr
put bind '"jk":vi-movement-mode'
into your .bashrc
file after set -o vi
🙂
server@thinkpad:~$ tail -n 2 .bashrc
set -o vi
bind '"jk":vi-movement-mode'
please see @grochmal's answer for a more detailed explanation
Best Answer
TL;DR
Bash has a similar functionality to
zsh
'sbindkey
throughbind
, but it does not have severalvi
modes likezsh
. Afterset -o vi
you can do:which is the equivalent of
zsh
'sbindkey -M <all vi modes> jk vi-movement-mode
The
vi-movement-mode
functions comes frominputrc
(see/etc/inputrc
for a list of them).Full text
As Stephen Harris points out in his comment:
.bashrc
is called bybash
always (and notably not by other shells)..bash_profile
is only called on login shells (and again, bash only).Several distros come with a
.bash_profile
skeleton that looks as follows:Which is a good content for
.bash_profile
since you can simply forget it exists.Now, to map jk to Esc in the shell session, that is not really possible. When you do:
In Vim, after you type j, Vim knows it needs to wait a little bit to see if you type k next and it should invoke the mapping (or that you type another key and the mapping should not be triggered). As an addendum this is controlled by
:set timeoutlen=<miliseconds>
in Vim (see:h timeoutlen
).Several shell's or X11 has no such timeout control and does not allow for multiple character mappings. Only a mapping of a single key is allowed (But see the support notes below.) .
Does not read
.vimrc
, it only imitates somevi
(not evenvim
) key combinations that can be used in the shell. The same can be said about-o emacs
, it does not come with the full power ofemacs
.zsh support
zsh
actually supports map timeout. And you can use the following to mapjk
to<esc>
:(That will need to go to
~/.zshrc
not~/.bashrc
)Yet, I advise against this. I use
vim
andzsh
most of the time. I haveinoremap jk <esc>
in myvimrc
and I did try using thebindkey
combination above.zsh
waits too long to printj
when using it, and that annoyed me a lot.bash support
bash
supportsreadline
bind
. I believe thatbash
can be compiled withoutreadilne
therefore there may be some rare systems that have bash that do not supportbind
(be watchful). To mapjk
to<esc>
inbash
you need to do:(yes that's a double level of quoting, it is needed)
Again, this makes typing
j
quite annoying. But somehow less annoying than thezsh
solution on my machine (probably the default timeout is shorter).Workaround (for non-bash and non-zsh shells)
The reason for remapping the Esc key is that it lies quite far away on the keyboard, and typing it takes time. A trick that can be borrowed from the
emacs
guys is to remap CapsLock since it is a useless key anyway.emacs
guys remap it to Ctrl but we will remap it to Esc.Let's use
xev -event keyboard
to check the keycode of CapsLock:And to check the function of Esc:
Very good, CapsLock is keycode 66 and Esc's function is called "Escape". Now we can do:
The above must be done in this order. Now every time you hit CapsLock it works like an Esc key.
The tricky part is where to set this. A file
~/.Xmodmap
with the content:Should be respected by most distros (actually display managers, but I'm saying distros for simplicity), but I saw ones that don't respect several
~/X*
files. For such distros you may try something like:In your
.bashrc
.(In theory that would be better placed in
~/.xinitrc
but if a display manager does not respect.Xmodmap
it will definitely not respect~/.xnintrc
.)Extra note: This only remaps CapsLock to Esc in a X11 session, therefore the map will only work in terminal emulators. Actual
tty
's will not see the map.References and extra reading:
.bashrc
vs..bash_profile