Zsh запрашивает полную ширину с пользовательским вводом в следующей строке

Я хотел бы иметь левое и правое приглашение в одной строке и цвет фона, охватывающий всю строку. Вход пользователя должен быть в следующей строке.

hostname | ~/path/to/cwd branch master | insert mode $ _ 

Для linebreak я попытался использовать $'\n' в PS1 но это приводит к тому, что правильное приглашение также будет показано во второй строке.

Для окрашивания всей строки я попытался иметь %K{green} в PS1 не закрывая ее, но окраска фона останавливается сразу после последнего символа левого приглашения.

Как я могу реализовать эту подсказку?

Вы могли бы сделать что-то вроде:

 branch=master mode=insert setopt promptsubst left='%m | %~' PS1='%K{green}$left${(l,COLUMNS-${#${(%)left}},)${${:-$branch | $mode}//[%]/%%}}%k$ ' 

Мы используем оператор ${(l,length,)...} left-pad, чтобы вставить правую часть подсказки в $COLUMNS за вычетом длины того, что было показано с левой стороны.

Чтобы $mode обновлялся при нажатии Insert , вы должны:

 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 

Это вызывает повторную переадресацию при переключении режима.

Для режима vi вам также необходимо рассмотреть все случаи, когда введен режим вставки (в режиме вставки ( a / A , i / I , c / C , s / S ) или перезаписать ( R )), которые вы можно сделать с помощью специального виджета-крючка zle-keymap-select (как вы выяснили):

 zle -N zle-keymap-select update-mode 

Я бы переписал ваше окончательное решение как:

 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 , 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 

Это позволит свести к минимуму количество ненужных вилок и повторных перерисовок и позволить оболочке правильно отображать подсказку при любых обстоятельствах, в том числе при изменении размеров окон.

Скриншот:

введите описание изображения здесь