How do I customize zsh's vim mode?

1.) (see http://zshwiki.org/home/examples/zlewidgets and http://pthree.org/2009/03/28/add-vim-editing-mode-to-your-zsh-prompt/ ):

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

Where:

  • "RPS" stands for 'right prompt string' and defines the prompt appearing on the right hand side of the terminal, and the ${variable/pattern/replacement} syntax is that of 'parameter expansion', see: http://mywiki.wooledge.org/BashSheet#Parameter_Operations.

  • 'zle -N' causes the user-definable widgets 'zle-line-init' and 'zle-keymap-select' to be bound (to shell functions of same names), so that they will be called when the line editor is initialised and the keymap is changed respectively, see: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC125.

2.) i suspect that you have to write another zsh-widget to do that, get inspired by the first of the two links for the first problem.


akira's solution has the following problem when using multi-line prompts: when going from ins to cmd mode, the prompt redraw causes few lines to be deleted from the previous output (and the new prompt is displayed few lines above). How many lines depends on how many lines you have in your prompt.

The way to deal with that is to use zle-line-finish, without using zle reset-prompt there. An example:

# perform parameter expansion/command substitution in prompt
setopt PROMPT_SUBST

vim_ins_mode="[INS]"
vim_cmd_mode="[CMD]"
vim_mode=$vim_ins_mode

function zle-keymap-select {
  vim_mode="${${KEYMAP/vicmd/${vim_cmd_mode}}/(main|viins)/${vim_ins_mode}}"
  zle reset-prompt
}
zle -N zle-keymap-select

function zle-line-finish {
  vim_mode=$vim_ins_mode
}
zle -N zle-line-finish

And then you can add it to your right-prompt, for example:

RPROMPT='${vim_mode}'

This is straight from my blog post about it:

  • http://pawelgoscicki.com/archives/2012/09/vi-mode-indicator-in-zsh-prompt/