Я хотел бы иметь левое и правое приглашение в одной строке и цвет фона, охватывающий всю строку. Вход пользователя должен быть в следующей строке.
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
Это позволит свести к минимуму количество ненужных вилок и повторных перерисовок и позволить оболочке правильно отображать подсказку при любых обстоятельствах, в том числе при изменении размеров окон.
Скриншот: