zshプロンプトをviモードでモードを表示する


44

私はbindkey -v(bash-ers set -o viではzshでも動作すると思います)またはvi(m)モードを使用します。しかし、挿入モードなのかコマンドモードなのかを判断する視覚的な手がかりがないというのは、私を悩ませています。プロンプトにモードを表示させる方法を知っている人はいますか?

回答:


25

私が見つかりました。これを介して、SU。基本的な例を次に示しますが、私はまだ自分用にカスタマイズしています。

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

まだ本当に理解していないことを除いて説明します


1
このアプローチを試しましたが、1つの問題が見つかりました。CTRL+Cviコマンドモードのときに何かをすると、プロンプトはリセットされますが、実際に挿入モードになっているときにコマンドモードになっていることを示します。zle-line-initインジケーターを常に挿入モードに変更する必要があります。何らかの理由$KEYMAPで、zle-line-initが呼び出されたときに適切に更新されません。
パトリック

2
zle reset-prompt(あなたのプロンプトが複数行の場合)再描画すると:(これは私にとって致命あるプロンプト上1(またはそれ以上)の行を削除します。
パヴェルGościcki

@PawełGościckiPS1が2行以上ある場合は問題のようです。
Metaphox

@Metaphox知っている、なぜ(あなたのプロンプトが複数行の場合)と言ったのか。その修正はありますか?
パウェウゴイチッキ

@PawełGościckiawwすみません、かっこ内の言葉を何とかスキップしました、悪い習慣。いいえ、その修正は見つかりませんでした。どのプラットフォームを使用していますか?これがOS X固有かどうか疑問に思っていました。
Metaphox

18

zle-keymap-selectモードが変更されるたびに実行されるものはすでに見つかりました。端末がサポートしているものに応じて、プロンプト以外の視覚的なインジケータを設定するために使用できます(もちろん、モードインジケータ表示の好みも)。

カーソルの形状を変更する標準のterminfo機能があります。ただし、一部の端末では、両方のモードで同じカーソルが表示されます。Xtermの見にくいカーソルの概念は、カーソルを点滅させることです(これは-bcコマンドライン引数またはcursorBlinkリソースで有効にする必要があります)。

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

一部の端末では、print -n '\e]12;pink\a'(色名による)またはprint -n '\e]12;#abcdef\a'(RGB仕様による)でカーソルの色を変更することもできます。これらのシーケンスは、ctlseqsファイル内のxtermのドキュメントで説明されています。最近の端末エミュレータは通常、xtermをエミュレートしますが、すべての機能をサポートしているわけではありません。


何らかの理由で、代わりにを取得mainします。理由はわかりません。KEYMAPviins
グレアム14

1
@Graemeはmainの別名であるviinsemacsかどうかに応じて、zshのは思ったが起動時にお気に入りのエディタはviやなかったです。viinsモードをからvicmdに戻すときに使用すると考えましたが、main代わりに使用するようです。更新しました。
ジル 'SO-悪であるのをやめる' 14

1
Enterキーを押すとキーマップが変更されても呼び出されないためzle-line-init、まだ(または他の方法で)ダブルアップする必要がありzle-keymap-selectます。
グレアム14

9

複数行のプロンプトでreset-promptを使用する際に問題が発生した場合、これは私のために機能しました:http : //zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html https://と組み合わせてstackoverflow.com/questions/3622943/zsh-vi-mode-status-line私がやったこと:

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

VimModeを試すことができます


4
私は少しリンクが少なく、もう少し説明的なものを望んでいました。物事の仕組みを知りたいです。
xenoterracide

1
実際にはすべてです。関数のコメントと、それらがモード変更イベントにどのようにバインドされているかを見てください。
マーティン

5

これは、zshで「ブロック」と「ビーム」の形状の間でカーソルを変更するために使用するものです。

シロアリgnome-terminalmate-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'
}

これは、ターミナルおよびDECSCUSRを理解するターミナルエミュレータでのみ機能します。
JdeBP

1
私はこれが好き。私はそれがわずかに使用するように変更して、私は、他の用途でpreexecかもしれない相互作用への書き込みを心配add-zsh-hook:とても似gist.github.com/MatrixManAtYrService/...
MatrixManAtYrService

4

Iビームとブロックの間でカーソルの形状を変更する別のソリューション(アンダースコアの場合はを使用\033[4 q)。これをに追加します~/.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

https://bbs.archlinux.org/viewtopic.php?id=95078から変更されました。gnome-terminal 3.22でテスト済み。


更新

カーソルの形状を変更するためのさらに別の解決策は、ここにあります。これはiTerm2で動作するようです。iTerm2にはテストする手段がありませんが、他の人に役立つ場合に備えてここに追加します。あなたへの最後の追加~/.zshrc

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
iTerm2用の更新されたスクリプトが実際に機能することを確認しました。
ジェイソンデニー

最初のスクリプトは、ターミナルおよびDECSCUSRを理解するターミナルエミュレータでのみ機能します。
JdeBP

これは本当にエレガントなソリューションで、シェルを
散らかし

3

私は現在、新幹線をテーマにしたZshを使用しています。Sebastian Blaskの答えで与えられた例に従って、私は以下のコードになりました

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

これは、デフォルトの$を文字Nから通常モードに、Iを挿入モードに変更するだけです。

この画像は、通常モードでCtrl+ を押したときの例ですC

ここに画像の説明を入力してください


2

Sebastian Blaskの投稿に基づいた、さらに別のバージョンがあります。私が見つけることができる他のすべてのソリューションが余分な行、右側のステータス、または追加された文字を使用したため、これは可能な限り邪魔にならないように意図されていました。

これにより、$通常モードが有効になっているときに、単に白から赤に色が変わります。お好みに合わせてプロンプトを編集します

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

zshの-VIM-モードプラグインは、インサート、コマンド、検索、置き換え、および視覚的なモードの指標を表示することができます。他の回答の基本的な手法を使用して、さまざまなZLEフック(zle-keymap-select、zle-isearch-updateなど)にフックします。[[ $ZLE_STATE = *overwrite* ]]置換モードをチェックします。$REGION_ACTIVE視覚モードを識別するためにチェックします。

論理は、isearchモードを終了するときにZSHがイベントを起動する方法のいくつかの癖によって複雑になります。

モジュールのもう1つの優れた機能は、モードに基づいてカーソルの形状と色を変更できることです。たとえば、INSERTモードでは垂直バーを使用し、SEARCHモードでは点滅する下線を使用できます。


このプラグインは素晴らしいです。
jdhao
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.