Você pode fazer algo como:
branch=master mode=insert
setopt promptsubst
left='%m | %~'
PS1='%K{green}$left${(l,COLUMNS-${#${(%)left}},)${${:-$branch | $mode}//[%]/%%}}%k$ '
Usamos o operador ${(l,length,)...}
do bloco de notas para preencher o lado direito do prompt com $COLUMNS
menos o comprimento do que foi exibido no lado esquerdo.
Para que $mode
seja atualizado quando você pressionar Inserir , você faria:
update-mode() {
case $KEYMAP in
(main)
case $ZLE_STATE in
(*insert*) mode=insert;;
(*) mode=overwrite
esac;;
(*) mode=$KEYMAP
esac
[[ $mode = $oldmode ]] || zle reset-prompt
}
overwrite-mode() {
zle ".$WIDGET"
update-mode
}
zle -N overwrite-mode
Isso faz com que o prompt seja redesenhado quando você alterna o modo.
Para o modo vi
, você também precisa considerar todos os casos em que o modo de inserção é inserido (no modo de inserção ( a
/ A
, i
/ I
, c
/ C
, s
/ S
) ou sobrescrever ( R
)), o que você pode fazer com o widget de gancho especial zle-keymap-select
(como você descobriu):
zle -N zle-keymap-select update-mode
Eu reescrevi sua solução final como:
bindkey -v
# Bind the <Insert> key.
bindkey $terminfo[kich1] overwrite-mode
setopt promptsubst
(){ # local scope
local left right invisible leftcontent
# User name.
left+='%B%F{black}%K{green} %n '
# Current working directory.
left+='%K{yellow} %~ '
# Version control branch.
right='${vcs_info_msg_0_:+${vcs_info_msg_0_//[%]/%%} }'
# Virtualenv.
export VIRTUAL_ENV_DISABLE_PROMP=1
right+='${VIRTUAL_ENV:+venv }'
# Editing mode. $ZLE_MODE shouldn't contain %, no need to escape
ZLE_MODE=insert
right+='%K{green} $ZLE_MODE'
# closing
right+=$' %k%f%b'
# Combine left and right prompt with spacing in between.
invisible='%([BSUbfksu]|([FBK]|){*})'
leftcontent=${(S)left//$~invisible}
rightcontent=${(S)right//$~invisible}
PS1="$left\${(l,COLUMNS-\${#\${(%):-$leftcontent$rightcontent}},)}$right%{"$'\n%}$ '
}
autoload vcs_info
precmd() vcs_info
update-mode() {
case $KEYMAP in
(main)
case $ZLE_STATE in
(*insert*) ZLE_MODE=insert;;
(*) ZLE_MODE=overwrite
esac;;
(*) ZLE_MODE=$KEYMAP
esac
[[ $ZLE_MODE = $oldmode ]] || zle reset-prompt
}
overwrite-mode() {
zle ".$WIDGET"
update-mode
}
zle -N overwrite-mode
zle -N zle-keymap-select update-mode
Isso minimizaria o número de garfos desnecessários e redesenho de solicitações e permitiria que o shell desenhasse o prompt corretamente em todas as circunstâncias, inclusive quando as janelas estiverem sendo redimensionadas.
Screenshot: