fai in modo che il mio prompt di zsh mostri la modalità in modalità vi


44

Io uso bindkey -v(per i basatori set -o vipenso che funzioni anche in zsh) o vi (m). ma mi dà fastidio che non ho alcun segnale visivo per dirmi se sono in modalità inserimento o modalità comando. Qualcuno sa come posso fare in modo che il mio prompt visualizzi la modalità?

Risposte:


25

Ho trovato questa via SU . Ecco l'esempio di base, anche se lo sto ancora personalizzando da solo:

function zle-line-init zle-keymap-select {
    RPS1="${${KEYMAP/vicmd/-- NORMAL --}/(main|viins)/-- INSERT --}"
    RPS2=$RPS1
    zle reset-prompt
}

zle -N zle-line-init
zle -N zle-keymap-select

Lo spiegherei, tranne che non lo capisco ancora


1
Ho provato questo approccio ma ho riscontrato un problema. Se fai qualcosa di simile CTRL+Cmentre sei in modalità vi-command, il prompt si reimposterà, ma indica che sei in modalità command quando sei veramente in modalità insert. zle-line-initdovrebbe sempre cambiare l'indicatore per inserire la modalità. Per qualche motivo $KEYMAPnon viene aggiornato correttamente quando viene chiamato zle-line-init.
Patrick,

2
zle reset-prompteliminerà 1 (o più) righe sopra il prompt (se il tuo prompt è multilinea) durante il ridisegno :( Questo è uno spettacolo per me.
Paweł Gościcki

@ PawełGościcki sembra essere un problema quando hai due o più linee di PS1.
Metaphox

@Metaphox Lo so, per questo ho detto "(se il tuo prompt è multilinea)". Qualche correzione per quello?
Paweł Gościcki

@ PawełGościcki aww scusa se in qualche modo ho saltato le parole tra parentesi, cattiva abitudine. No, non ho trovato una soluzione per questo. Quale piattaforma utilizzi? Mi chiedevo se questo è specifico per OS X.
Metaphox

18

Hai già trovato zle-keymap-selectche viene eseguito ogni volta che cambia la modalità. Potresti usarlo per impostare qualche altro indicatore visivo oltre al prompt, a seconda di ciò che il tuo terminale lo supporta (e i tuoi gusti nella visualizzazione dell'indicatore di modalità, ovviamente).

Esiste una funzionalità terminfo standard per modificare la forma del cursore. Tuttavia, alcuni terminali visualizzano lo stesso cursore in entrambe le modalità. L'idea di Xterm di un cursore meno visibile è di farlo lampeggiare (e questo deve essere abilitato con l' -bcargomento o la cursorBlinkrisorsa della riga di comando ).

zle-keymap-select () {
  case $KEYMAP in
    vicmd) print -rn -- $terminfo[cvvis];; # block cursor
    viins|main) print -rn -- $terminfo[cnorm];; # less visible cursor
  esac
}

Con alcuni terminali, è anche possibile cambiare il colore del cursore con print -n '\e]12;pink\a'(per nome colore) o print -n '\e]12;#abcdef\a'(per specifica RGB). Queste sequenze sono descritte nella documentazione xterm, nel ctlseqsfile; i moderni emulatori di terminali in genere emulano xterm, sebbene potrebbero non supportare tutte le sue funzionalità.


Per qualche motivo ho mainper KEYMAPinvece di viins, non so perché.
Graeme,

1
@Graeme mainè un alias per viinso emacsdipende dal fatto che zsh pensasse che il tuo editor preferito fosse vi o meno quando è iniziato. Ho pensato che avrebbe usato viinsquando si torna dalla modalità vicmd, ma sembra che maininvece usi . Aggiornato.
Gilles 'SO- smetti di essere malvagio' il

1
Hai ancora bisogno di raddoppiare con zle-line-init(o qualunque altra alternativa) poiché zle-keymap-selectnon viene chiamato se premere invio cambia la mappa di tasti.
Graeme,

9

Per le persone che hanno problemi a utilizzare reset-prompt con prompt multilinea, questo ha funzionato per me: http://zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html In combinazione con https: // stackoverflow.com/questions/3622943/zsh-vi-mode-status-line Ho finito per fare:

terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1]

function insert-mode () { echo "-- INSERT --" }
function normal-mode () { echo "-- NORMAL --" }

precmd () {
    # yes, I actually like to have a new line, then some stuff and then 
    # the input line
    print -rP "
[%D{%a, %d %b %Y, %H:%M:%S}] %n %{$fg[blue]%}%m%{$reset_color%}"

    # this is required for initial prompt and a problem I had with Ctrl+C or
    # Enter when in normal mode (a new line would come up in insert mode,
    # but normal mode would be indicated)
    PS1="%{$terminfo_down_sc$(insert-mode)$terminfo[rc]%}%~ $ "
}
function set-prompt () {
    case ${KEYMAP} in
      (vicmd)      VI_MODE="$(normal-mode)" ;;
      (main|viins) VI_MODE="$(insert-mode)" ;;
      (*)          VI_MODE="$(insert-mode)" ;;
    esac
    PS1="%{$terminfo_down_sc$VI_MODE$terminfo[rc]%}%~ $ "
}

function zle-line-init zle-keymap-select {
    set-prompt
    zle reset-prompt
}
preexec () { print -rn -- $terminfo[el]; }

zle -N zle-line-init
zle -N zle-keymap-select

5

puoi provare VimMode


4
Speravo in qualcosa di un po 'meno linkish e un po' più esplicativo. Mi piace sapere come funzionano le cose.
xenoterracide,

1
In realtà è tutto lì. Guarda i commenti sulle funzioni e su come sono legati agli eventi di cambio modalità.
Martin,

5

Questo è quello che uso per cambiare il cursore tra 'Block' e 'Beam' in zsh:

(Testato con termite , gnome-terminal e mate-terminal )

# vim mode config
# ---------------

# Activate vim mode.
bindkey -v

# Remove mode switching delay.
KEYTIMEOUT=5

# Change cursor shape for different vi modes.
function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] ||
     [[ $1 = 'block' ]]; then
    echo -ne '\e[1 q'

  elif [[ ${KEYMAP} == main ]] ||
       [[ ${KEYMAP} == viins ]] ||
       [[ ${KEYMAP} = '' ]] ||
       [[ $1 = 'beam' ]]; then
    echo -ne '\e[5 q'
  fi
}
zle -N zle-keymap-select

# Use beam shape cursor on startup.
echo -ne '\e[5 q'

# Use beam shape cursor for each new prompt.
preexec() {
   echo -ne '\e[5 q'
}

Funzionerà solo su terminali ed emulatori di terminali che comprendono DECSCUSR.
JdeBP,

1
Mi piace questo. Temo che scrivere su preexec potrebbe interagire con altri usi, quindi l'ho modificato leggermente per usarlo in questo add-zsh-hookmodo: gist.github.com/MatrixManAtYrService/…
MatrixManAtYrService

4

Un'altra soluzione per cambiare la forma del cursore tra I-beam e block (per il trattino basso, usa \033[4 q). Aggiungi questo al tuo ~/.zshrc.

zle-keymap-select () {
if [ $KEYMAP = vicmd ]; then
    printf "\033[2 q"
else
    printf "\033[6 q"
fi
}
zle -N zle-keymap-select
zle-line-init () {
zle -K viins
printf "\033[6 q"
}
zle -N zle-line-init
bindkey -v

Modificato da https://bbs.archlinux.org/viewtopic.php?id=95078 . Testato su gnome-terminal 3.22.


Aggiornare

Ancora un'altra soluzione per cambiare le forme del cursore può essere trovata qui . Questo apparentemente funziona per iTerm2, che non ho i mezzi per testare, ma aggiungendolo qui nel caso sia utile per qualcun altro. L'ultima aggiunta al tuo ~/.zshrcsarebbe

function zle-keymap-select zle-line-init
{
    # change cursor shape in iTerm2
    case $KEYMAP in
        vicmd)      print -n -- "\E]50;CursorShape=0\C-G";;  # block cursor
        viins|main) print -n -- "\E]50;CursorShape=1\C-G";;  # line cursor
    esac

    zle reset-prompt
    zle -R
}

function zle-line-finish
{
    print -n -- "\E]50;CursorShape=0\C-G"  # block cursor
}

zle -N zle-line-init
zle -N zle-line-finish
zle -N zle-keymap-select

1
Ho confermato che lo script aggiornato per iTerm2 funzionava davvero.
Jason Denney,

Il primo script funziona solo su terminali ed emulatori di terminali che comprendono DECSCUSR.
JdeBP,

Questa è una soluzione davvero elegante che non ingombra il mio guscio
tsturzl

3

Attualmente sto usando Zsh con il tema Bullet Train . Seguendo l'esempio fornito dalla risposta di Sebastian Blask , ho finito con il codice qui sotto

bindkey -v
KEYTIMEOUT=1

function zle-line-init zle-keymap-select {
    case ${KEYMAP} in
        (vicmd)      BULLETTRAIN_PROMPT_CHAR="N" ;;
        (main|viins) BULLETTRAIN_PROMPT_CHAR="I" ;;
        (*)          BULLETTRAIN_PROMPT_CHAR="I" ;;
    esac
    zle reset-prompt
}

zle -N zle-line-init
zle -N zle-keymap-select

Questo cambierà di default $ alle lettere N in modalità normale e I per inserire la modalità.

Questa immagine è un esempio quando in modalità normale premo Ctrl+ C:

inserisci qui la descrizione dell'immagine


2

Ecco un'altra versione, basata sul post di Sebastian Blask . Questo doveva essere il più intrusivo possibile, poiché tutte le altre soluzioni che ho potuto trovare hanno usato righe extra, stato a destra o caratteri aggiunti.

Questo cambia semplicemente il colore $da bianco a rosso quando è abilitata la modalità normale. Modifica il prompt a tuo piacimento

bindkey -v
function zle-line-init zle-keymap-select {
    case ${KEYMAP} in
        (vicmd)      PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} %{\e[0;31m%}$%{\e[0m%} ' ;;
        (main|viins) PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} $ ' ;;
        (*)          PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} $ ' ;;
    esac
    zle reset-prompt
}

zle -N zle-line-init
zle -N zle-keymap-select


1

Il plug -in zsh-vim-mode è in grado di mostrare un indicatore per le modalità di inserimento, comando, ricerca, sostituzione e visualizzazione. Utilizza la tecnica di base di altre risposte per agganciarsi ai vari hook ZLE (zle-keymap-select, zle-isearch-update, ecc.). Verifica la [[ $ZLE_STATE = *overwrite* ]]modalità di sostituzione. Verifica $REGION_ACTIVEl'identificazione della modalità visiva.

La logica è complicata da alcune stranezze di come ZSH genera eventi quando esce dalla modalità isearch.

Un'altra caratteristica interessante del modulo è la possibilità di modificare la forma e il colore del cursore in base alla modalità. Ad esempio, è possibile utilizzare una barra verticale in modalità INSERISCI e una sottolineatura lampeggiante in modalità RICERCA.


Questo plugin è fantastico.
jdhao,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.