Zsh 提示在下一行中用用户输入填充整个宽度

Zsh 提示在下一行中用用户输入填充整个宽度

我希望将左右提示放在一行中,并且背景颜色跨越整行。用户输入应该在下一行。

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

对于换行符,我尝试使用$'\n'inPS1但这会导致在第二行中绘制正确的提示。

为了给整行着色,我尝试在不关闭它的情况下加入%K{green}PS1但背景着色在左侧提示的最后一个字符之后停止。

怎么才能实现这个提示呢?

答案1

你可以这样做:

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/ Ai/ Ic/ Cs/ 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

这将最大限度地减少不必要的分叉和提示符重绘的数量,并允许 shell 在所有情况下(包括调整窗口大小时)正确绘制提示符。

截屏:

在此输入图像描述

相关内容