make my zsh prompt show mode in vi mode
I found this via SU. Here's the basic example, though I'm still customizing it for myself:
function zle-line-init zle-keymap-select {
RPS1="${${KEYMAP/vicmd/-- NORMAL --}/(main|viins)/-- INSERT --}"
RPS2=$RPS1
zle reset-prompt
}
zle -N zle-line-init
zle -N zle-keymap-select
I'd explain it except I don't really understand it yet
You've already found zle-keymap-select
which is executed whenever the mode changes. You could use it to set some other visual indicator than the prompt, depending on what your terminal supports it (and your taste in mode indicator display, of course).
There is a standard terminfo capability to change the shape of the cursor. However some terminals display the same cursor in both modes. Xterm's notion of a less visible cursor is to make it blink (and this must be enabled with the -bc
command line argument or cursorBlink
resource).
zle-keymap-select () {
case $KEYMAP in
vicmd) print -rn -- $terminfo[cvvis];; # block cursor
viins|main) print -rn -- $terminfo[cnorm];; # less visible cursor
esac
}
With some terminals, you can also change the cursor color with print -n '\e]12;pink\a'
(by color name) or print -n '\e]12;#abcdef\a'
(by RGB specification). These sequences are described in the xterm documentation, in the ctlseqs
file; modern terminal emulators typically emulate xterm, though they might not support all its features.
For the people having problems using reset-prompt with multiline prompts, this worked for me: http://zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html In combination with https://stackoverflow.com/questions/3622943/zsh-vi-mode-status-line I ended up doing:
terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1]
function insert-mode () { echo "-- INSERT --" }
function normal-mode () { echo "-- NORMAL --" }
precmd () {
# yes, I actually like to have a new line, then some stuff and then
# the input line
print -rP "
[%D{%a, %d %b %Y, %H:%M:%S}] %n %{$fg[blue]%}%m%{$reset_color%}"
# this is required for initial prompt and a problem I had with Ctrl+C or
# Enter when in normal mode (a new line would come up in insert mode,
# but normal mode would be indicated)
PS1="%{$terminfo_down_sc$(insert-mode)$terminfo[rc]%}%~ $ "
}
function set-prompt () {
case ${KEYMAP} in
(vicmd) VI_MODE="$(normal-mode)" ;;
(main|viins) VI_MODE="$(insert-mode)" ;;
(*) VI_MODE="$(insert-mode)" ;;
esac
PS1="%{$terminfo_down_sc$VI_MODE$terminfo[rc]%}%~ $ "
}
function zle-line-init zle-keymap-select {
set-prompt
zle reset-prompt
}
preexec () { print -rn -- $terminfo[el]; }
zle -N zle-line-init
zle -N zle-keymap-select