faire mon mode show rapide zsh en mode vi


44

J'utilise bindkey -v(pour les bashers, set -o vije pense que ça marche aussi en zsh) ou en mode vi (m). mais cela ne me permet pas de savoir si je suis en mode insertion ou en mode commande. Est-ce que quelqu'un sait comment je peux faire en sorte que mon invite affiche le mode?

Réponses:


25

J'ai trouvé cela via SU . Voici l'exemple de base, même si je le personnalise moi-même:

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

Je l'expliquerais sauf que je ne le comprends pas encore


1
J'ai essayé cette approche, mais j'ai trouvé un problème. Si vous faites quelque chose comme CTRL+Cen mode vi-commande, l'invite se réinitialisera, mais vous indiquera que vous êtes en mode commande lorsque vous êtes vraiment en mode insertion. zle-line-initdevrait toujours changer l'indicateur en mode insertion. Pour une raison quelconque, $KEYMAPn’est pas mis à jour correctement lors de l’appel de zle-line-init.
Patrick

2
zle reset-promptsupprimera 1 (ou plusieurs) lignes au-dessus de l'invite (si votre invite est multiligne) lors du redessinage :( Ceci est un obstacle pour moi.
Paweł Gościcki

@ PawełGościcki, cela semble être un problème lorsque vous avez deux lignes ou plus de PS1.
Métaphox

@Metaphox Je sais, c'est pourquoi j'ai dit "(si votre invite est multiligne)". Une solution pour ça?
Paweł Gościcki

@ PawełGościcki aww désolé j'ai en quelque sorte sauté les mots entre parenthèses, mauvaise habitude. Non, je n'ai pas trouvé de solution pour ça. Sur quelle plateforme es-tu? Je me demandais si cela est spécifique à OS X.
Métaphox

18

Vous avez déjà trouvé zle-keymap-selectce qui est exécuté à chaque changement de mode. Vous pouvez l'utiliser pour définir un autre indicateur visuel que l'invite, selon ce que votre terminal prend en charge (et votre goût de l'affichage de l'indicateur de mode, bien sûr).

Il existe une capacité standard terminfo pour changer la forme du curseur. Cependant, certains terminaux affichent le même curseur dans les deux modes. La notion de Xterm d'un curseur moins visible consiste à le faire clignoter (et cela doit être activé avec l' -bcargument de ligne de commande ou la cursorBlinkressource).

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

Avec certains terminaux, vous pouvez également changer la couleur du curseur avec print -n '\e]12;pink\a'(par nom de couleur) ou print -n '\e]12;#abcdef\a'(par spécification RGB). Ces séquences sont décrites dans la documentation xterm, dans le ctlseqsfichier; Les émulateurs de terminaux modernes émulent généralement xterm, même s’ils ne prennent peut-être pas en charge toutes ses fonctionnalités.


Pour une raison quelconque, je suis mainpour KEYMAPau lieu de viins, je ne sais pas pourquoi.
Graeme

1
@Graeme mainest un alias pour viinsou emacsselon si zsh pensait que votre éditeur favori était vi ou non quand il a commencé. Je pensais qu'il serait utile de viinschanger de mode vicmd, mais il semble que ce soit le cas main. Mis à jour.
Gilles 'SO- arrête d'être méchant'

1
Vous avez encore besoin de doubler avec zle-line-init(ou toute autre alternative) car zle-keymap-selectne pas être appelé si frapper entrer change le clavier.
Graeme

9

Pour les personnes ayant des problèmes d'utilisation de reset-prompt avec des invites multilignes, cela a fonctionné pour moi: http://zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html En combinaison avec https: // stackoverflow.com/questions/3622943/zsh-vi-mode-status-line J'ai fini par faire:

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

vous pouvez essayer VimMode


4
J'espérais quelque chose d'un peu moins linkish et un peu plus explicatif. J'aime savoir comment les choses fonctionnent.
Xenoterracide

1
En fait, tout y est. Examinez les commentaires des fonctions et leur lien avec les événements de changement de mode.
Martin

5

C'est ce que j'utilise pour changer le curseur entre les formes 'Block' et 'Beam' dans zsh:

(Testé avec Termite , gnome-terminal et 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'
}

Cela ne fonctionnera que sur les terminaux et les émulateurs de terminaux qui comprennent DECSCUSR.
JdeBP

1
J'aime ça. Je crains que l' écriture Interagir de puissance preexec avec d' autres usages, donc je l' ai modifié légèrement à utiliser add-zsh-hookcomme ceci: gist.github.com/MatrixManAtYrService/...
MatrixManAtYrService

4

Une autre solution pour changer la forme du curseur entre I-beam et block (pour le trait de soulignement, utilisez \033[4 q). Ajoutez ceci à votre ~/.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

Modifié à partir de https://bbs.archlinux.org/viewtopic.php?id=95078 . Testé dans gnome-terminal 3.22.


Mise à jour

Une autre solution pour changer les formes du curseur peut être trouvée ici . Celui-ci fonctionne apparemment pour iTerm2, ce que je n'ai pas les moyens de tester, mais l'ajouter ici au cas où il serait utile à quelqu'un d'autre. Le dernier ajout à votre ~/.zshrcserait

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
J'ai confirmé que le script mis à jour pour iTerm2 fonctionnait effectivement.
Jason Denney

Le premier script ne fonctionnera que sur les terminaux et les émulateurs de terminaux qui comprennent DECSCUSR.
JdeBP

C'est une solution vraiment élégante qui n'encombre pas ma coquille
tsturzl

3

J'utilise actuellement le thème Zsh with Bullet Train . Suivant l'exemple donné par la réponse de Sebastian Blask , je me suis retrouvé avec le code ci-dessous

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

Ceci ne changera que les valeurs par défaut de $ par les lettres N en mode normal et I en mode insertion.

Cette image est un exemple lorsque, en mode normal, j'appuie sur Ctrl+ C:

entrez la description de l'image ici


2

Voici encore une autre version, basée sur le post de Sebastian Blask . Cela devait être aussi peu intrusif que possible, car toutes les autres solutions utilisaient des lignes supplémentaires, un statut à droite ou des caractères ajoutés.

Cela change simplement la couleur $du blanc au rouge lorsque le mode normal est activé. Modifiez l'invite à votre convenance

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

Le plug - in zsh-vim-mode est capable d'afficher un indicateur pour les modes d'insertion, de commande, de recherche, de remplacement et visuel. Il utilise la technique de base des autres réponses pour se connecter aux différents hooks ZLE (zle-keymap-select, zle-isearch-update, etc.). Il vérifie le [[ $ZLE_STATE = *overwrite* ]]mode de remplacement. Il vérifie $REGION_ACTIVEpour identifier le mode visuel.

La logique est compliquée par certaines bizarreries sur la façon dont ZSH déclenche des événements en quittant le mode isearch.

Une autre fonctionnalité intéressante du module est la possibilité de changer la forme et la couleur du curseur en fonction du mode. Par exemple, vous pouvez utiliser une barre verticale en mode INSERT et un soulignement clignotant en mode SEARCH.


Ce plugin est génial.
Jdhao
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.