Come personalizzo la modalità vim di zsh?


25

Ok, quindi ho finalmente apportato il grande cambiamento. Nel mio .zshenv, ho cambiato il mio EDITOR:

export EDITOR=vim

Ci sono un paio di domande che sono così minori che non volevo iniziare domande separate per loro. Eccoli:

  1. Come faccio a far distinguere zsh tra la modalità di inserimento e la modalità di comando come in vim? Preferibilmente questo cambierebbe il cursore da una sottolineatura a un blocco come in vim, ma anche la visualizzazione del testo in basso funzionerebbe.

  2. Come posso farlo agire più come Vim? Ad esempio, preferirei essere in modalità comando per impostazione predefinita e non uscirne dopo un comando.


//, hai avuto comportamenti strani con le modifiche alla riga di comando? Mi sono imbattuto nel ~personaggio che viene inserito quando premo il Deletetasto zsh. Ho fatto una domanda al riguardo qui: superuser.com/questions/997593/…
Nathan Basanese

Risposte:


25

1. ) (vedi http://zshwiki.org/home/examples/zlewidgets e http://pthree.org/2009/03/28/add-vim-editing-mode-to-your-zsh-prompt/ ) :

funzione 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

Dove:

2. ) Sospetto che tu debba scrivere un altro widget zsh per farlo, lasciati ispirare dal primo dei due link per il primo problema.


22

La soluzione di Akira presenta il seguente problema quando si utilizzano i prompt multilinea: quando si passa da ins a modalità cmd, il prompt ridisegna provoca l'eliminazione di poche righe dall'output precedente (e il nuovo prompt viene visualizzato poche righe sopra). Quante linee dipende da quante linee hai nel tuo prompt.

Il modo di gestirlo è usare zle-line-finish, senza usarlo zle reset-prompt. Un esempio:

# perform parameter expansion/command substitution in prompt
setopt PROMPT_SUBST

vim_ins_mode="[INS]"
vim_cmd_mode="[CMD]"
vim_mode=$vim_ins_mode

function zle-keymap-select {
  vim_mode="${${KEYMAP/vicmd/${vim_cmd_mode}}/(main|viins)/${vim_ins_mode}}"
  zle reset-prompt
}
zle -N zle-keymap-select

function zle-line-finish {
  vim_mode=$vim_ins_mode
}
zle -N zle-line-finish

E quindi puoi aggiungerlo al prompt di destra, ad esempio:

RPROMPT='${vim_mode}'

Questo è direttamente dal mio post sul blog a riguardo:


Questa risposta dovrebbe ottenere molti voti. Questa è la prima volta che vedo questa soluzione e funziona dove gli altri no. Ho passato un'ora a giocherellare con il zle-line-initwidget senza alcun risultato. Modificato per adattarsi a ciò che Pawel ha fornito e al bingo!
Colin R,

Grazie! Non è ancora al 100% a prova di proiettile - di tanto in tanto ho una situazione in cui alcune righe del mio precedente output vengono eliminate - ma succede così raramente che lo ignoro.
Paweł Gościcki,

1
RPROMPT2dovrebbe essere impostato anche in modo tale che lo stato sia visualizzato nelle righe di continuazione. Inoltre, quando si utilizza questo, è possibile che si desideri setopt transient_rpromptche le modalità per le linee precedentemente accettate non vengano visualizzate.
qqx

Una cosa che manca ancora: se torno alla modalità emacs ( bindkey -e), mostra ancora [INS].
Daniel,

1
@cheflo puoi vedere la mia versione attuale di questa configurazione qui: github.com/pjg/dotfiles/blob/master/.zshrc#L518-L584 - forse questo ti aiuterà
Paweł Gościcki

5
zle-line-init() { zle -K vicmd; }
zle -N zle-line-init

queste due linee assicurano che inizi in modalità comando


Non funziona, zsh inizia comunque in modalità inserimento
baldrs

0

Di seguito ti verrà impostato con un cursore modificato e un prompt che mostra in quale modalità ti trovi. Puoi passare DEFAULT_VI_MODEa viinso vicmd. .zshrcPer iniziare, basta incollare il codice sottostante in uno nuovo :

# Prefer vi shortcuts
bindkey -v
DEFAULT_VI_MODE=viins
KEYTIMEOUT=1

__set_cursor() {
    local style
    case $1 in
        reset) style=0;; # The terminal emulator's default
        blink-block) style=1;;
        block) style=2;;
        blink-underline) style=3;;
        underline) style=4;;
        blink-vertical-line) style=5;;
        vertical-line) style=6;;
    esac

    [ $style -ge 0 ] && print -n -- "\e[${style} q"
}

# Set your desired cursors here...
__set_vi_mode_cursor() {
    case $KEYMAP in
        vicmd)
          __set_cursor block
          ;;
        main|viins)
          __set_cursor vertical-line
          ;;
    esac
}

__get_vi_mode() {
    local mode
    case $KEYMAP in
        vicmd)
          mode=NORMAL
          ;;
        main|viins)
          mode=INSERT
          ;;
    esac
    print -n -- $mode
}

zle-keymap-select() {
    __set_vi_mode_cursor
    zle reset-prompt
}

zle-line-init() {
    zle -K $DEFAULT_VI_MODE
}

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

# Optional: allows you to open the in-progress command inside of $EDITOR
autoload -Uz edit-command-line
bindkey -M vicmd 'v' edit-command-line
zle -N edit-command-line

# PROMPT_SUBST enables functions and variables to re-run everytime the prompt
# is rendered
setopt PROMPT_SUBST

# Single quotes are important so that function is not run immediately and saved
# in the variable
RPROMPT='$(__get_vi_mode)'

Nota: l'ho provato solo in Terminal.app (2.7.3) su MacOS (10.12.6) con zsh (5.3.1). Inoltre, se lo aggiungi, anche edit-command-linela modalità verrà impostata correttamente.

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.