Zsh prompt preenchendo toda a largura com entrada do usuário na próxima linha

5

Eu gostaria de ter o prompt esquerdo e direito em uma linha e uma cor de plano de fundo abrangendo toda a linha. A entrada do usuário deve estar na próxima linha.

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

Para o quebra de linha, tentei usar $'\n' em PS1 , mas isso faz com que o prompt direito seja desenhado na segunda linha também.

Para colorir a linha inteira, tentei ter %K{green} em PS1 sem fechá-la, mas a cor do plano de fundo pára logo após o último caractere do prompt esquerdo.

Como posso perceber esse aviso?

    
por danijar 19.12.2015 / 21:57

1 resposta

6

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:

    
por 19.12.2015 / 22:51

Tags