Skip to content

Vi (Vim) 編集モード

Koichi Murase edited this page Mar 29, 2024 · 13 revisions

[ 日本語 | English ]

1. Vi/Vim編集モードを有効にする

次に挙げる方法の内、何れか一つを用いて Vi/Vim 編集モードを有効にしていただくことができます。

~/.bashrc 内で set -o vi を用いる

或いは、set -o vi~/.bashrc 内に記述することもできます。

# bashrc

if [[ $- == *i* ]]; then # 対話セッション内か判定
  set -o vi
fi

ble.sh セッションのみで Vim 編集モードを有効にしたい場合は、~/.blerc (また は ~/.config/blesh/init.sh) の中に set -o vi を記述できます。

# blerc

set -o vi

~/.blerc 内で ble.sh 設定を用いる

次の設定を ~/.blerc に記述することでも Vi/Vim 編集モードを有効にできます。 この設定は、これ以前に説明した方法による設定を全て上書きします。 つまり set -o emacs といった設定等は全て上書きされます。

bleopt default_keymap=vi

inputrc設定

~/.inputrc 内に以下を記述します。

$if Bash
  set editing-mode vi
$endif

~/.bashrc 内で bind を用いる

又は、次の設定でも Vi/Vim 編集モードを有効にできます。

if [[ $- == *i* ]]; then # 対話セッション内か判定
  bind 'set editing-mode vi'
fi

2. ESC に対するタイムアウトの設定

ESC に対するタイムアウト時間は、端末からBashまでの経路の全てのタイムアウトを合計したものになります。 各タイムアウトの設定を次に示します。

sttyにおけるタイムアウト

擬似端末の入力処理におけるタイムアウトは stty コマンドで制御します。 通常、既定のタイムアウトは 0 です。 次のコマンドでタイムアウトを変更できます。 指定は0.1秒単位です。

# ~/.bashrc 内
stty time 0

Bash 4.3におけるタイムアウト

Bash 4.3以降にでは、readline 変数 keyseq-timeout によって Readline のタイムアウトを設定できます。 readline 変数はファイル ~/.inputrc において指定できます。 指定はミリ秒単位です。

# ~/.inputrc 内
$if Bash
  set keyseq-timeout 1
$endif

~/.inputrc 内で指定する代わりに、~/.bashrc 内でも次のコマンドを用いて readline 変数の値を変更できます。

# ~/.bashrc 内
bind 'set keyseq-timeout 1'

GNU Screen におけるタイムアウト

端末マルチプレクサ (terminal multiplexer) を用いている場合、その端末マルチプレクサにもタイムアウトがあります。 GNU Screen のタイムアウトは、~/.screenrc で次のように設定できます。 指定はミリ秒単位です。 この時、エスケープ文字で始まるキー束縛を bindkey -t によって定義しないようにご注意ください。 -t オプションを使用するとエスケープ文字のタイムアウトが無効になるためです。

# ~/.screenrc 内
maptimeout 1

Tmuxのタイムアウト

Tmuxのタイムアウトは ~/.tmux.conf で設定できます。 指定はミリ秒単位です。

# ~/.tmux.conf 内
set -sg escape-time 1

3. お好み設定例

Vi/Vim 編集モードの設定は keymap_vi_load フックを通して登録します。以下の様に記述してください。

# blerc

function blerc/kyemap-vi-load-hook {

  # Vi/Vim 編集モードの設定はここに書く

}
blehook/eval-after-load keymap_vi blerc/kyemap-vi-load-hook
# ble-0.3以前
# ble/array#push _ble_keymap_vi_load_hook blerc/vim-load-hook

モード行表示

Vi/Vim 編集モードでは、-- INSERT --(挿入モードの時)~(ノーマルモードの時)といったモード行が表示されます。 モード行を非表示にしたい場合には以下の設定を記述します。

# ble-0.4
bleopt keymap_vi_mode_show=

ノーマルモードに対するモード名を変更するには keymap_vi_mode_string_nmapオプションを使用します。

bleopt keymap_vi_mode_string_nmap=$'\e[1m-- NORMAL --\e[m'

ノーマルモードにおいてモード名を表示したくない場合は、代わりに次のように設定して下さい。

bleopt keymap_vi_mode_string_nmap=

各モードに対するカーソル形状

各モードに移行した際に送られる制御シーケンスを ble-bind -m KEYMAP --cursor NUM で指定できます。 例えば、DECSCUSRに幾らか対応している端末を使用している場合、次のように設定することでモード毎にカーソル形状が切り替わるようにできます。

# ble-0.4+
ble-bind -m vi_nmap --cursor 2
ble-bind -m vi_imap --cursor 5
ble-bind -m vi_omap --cursor 4
ble-bind -m vi_xmap --cursor 2
ble-bind -m vi_cmap --cursor 0

# 旧形式 (ble-0.2 または 0.3)
bleopt keymap_vi_nmap_cursor:=2
bleopt keymap_vi_imap_cursor:=5
bleopt keymap_vi_omap_cursor:=4
bleopt keymap_vi_xmap_cursor:=2
bleopt keymap_vi_cmap_cursor:=0

terminfo の項目 Ss に登録されていなくても、実際には端末が制御機能 DECSCUSR に対応していることもあります。 その場合、次のように ble.sh の端末情報を上書きしてカーソル形状を有効にすることができます。

_ble_term_Ss=$'\e[@1 q'

その他の詳細については ble-bind -m KEYMAP --cursor NUM を参照してください。

【挿入モード】 キーの Meta 修飾を有効化

以下の設定によりキー入力の Meta 修飾を有効化できます。 例えば、M-RET を使ってコマンドラインに改行文字を挿入することができるようになります。

# hook:keymap_vi_load

ble-decode/keymap:vi_imap/define-meta-bindings

追加で C-RET によってコマンドを強制的に実行するように設定することも可能です。

ble-bind -m vi_imap -f 'C-RET' 'accept-line'

M-backspace は既定では直前のシェル単語をキルリングにコピーします。 代わりに以下の設定によって、直前のシェル単語を切り取る動作に変更することができます。 複数の設定をするのは、端末およびその設定によって M-backspace が実際に送信するキーシーケンスに複数の可能性があるためです。

ble-bind -m vi_imap -f 'M-C-?' kill-backward-cword
ble-bind -m vi_imap -f 'M-DEL' kill-backward-cword
ble-bind -m vi_imap -f 'M-C-h' kill-backward-cword
ble-bind -m vi_imap -f 'M-BS'  kill-backward-cword

【挿入モード】 SP: 多機能空白 vs 単純空白挿入

SPへは既定でmagic-spaceが割り当てられており、空白を挿入する前に履歴展開・静的略語展開が実行されます。 各種展開なしに単に空白を挿入したい場合は、次の設定を追加してください。

ble-bind -m vi_imap -f 'SP' 'self-insert'

【挿入モード】 /: 多機能スラッシュ vs 単純スラッシュ挿入

/へは既定でmagic-slashが割り当てられており、スラッシュを挿入する前に ~ で始まる静的略語展開が実行されます。 静的略語展開なしに単にスラッシュを挿入したい場合は、次の設定を追加してください。

ble-bind -m vi_imap -f '/' 'self-insert'

【ノーマル/挿入モード】 RET & C-m: 多機能改行 vs コマンド強制実行

挿入モードでは RET または C-m は、現在のコマンドが複数行または不完全の時に、既定でコマンド実行の代わりに改行を挿入します。 ノーマルモードでは RET または C-m は、既定でカーソルを次の行へ移動します。 代わりに GNU Readline と同様に (コマンドが複数行または不完全でも) 強制的にコマンドを実行したい時には以下の設定を追加してください。

ble-bind -m vi_imap -f 'C-m' accept-line
ble-bind -m vi_imap -f 'RET' accept-line
ble-bind -m vi_nmap -f 'C-m' accept-line
ble-bind -m vi_nmap -f 'RET' accept-line

【挿入モード】 C-k: 前方行削除 vs ダイグラフ

C-kには既定でkill-forward-lineが割り当てられています。 <C-k>{文字1}{文字2} としてダイグラフを入力したい場合は、次の設定を追加してください。

ble-bind -m vi_imap -f 'C-k' 'vi_imap/insert-digraph'

【挿入モード】 C-o: 挿入ノーマルモード vs 実行&次の履歴項目

C-oは既定でvi_imap/single-command-modeに割り当てられています。 C-oにより現在の編集内容を実行した後に次の履歴項目を読み込みたい場合、次の設定を追加してください。

ble-bind -m vi_imap -f 'C-o' 'accept-and-next'

または、C-oの替わりにC-@accept-and-nextに束縛していただくことも可能です。

ble-bind -m vi_imap -f 'C-@' 'accept-and-next'

【ノーマル/挿入モード】 C-c: モード中断 vs コマンドライン破棄

挿入モードでは C-c は既定で特殊動作なしでノーマルモードに移動します。 ノーマルモードでは C-c は既定で現在入力中のコマンドを中断します。 代わりに GNU Readline と同様に現在のコマンドラインを破棄して新しい行に移るようにしたい時は以下の設定を用います。

ble-bind -m vi_imap -f 'C-c' discard-line
ble-bind -m vi_nmap -f 'C-c' discard-line

g g & G: コマンド履歴移動 vs 現在のコマンド内での移動

g gG は既定ではコマンド履歴内の項目の間を移動します。 現在のコマンドの内部での移動をしたい場合には HL をお使いいただけます。 もし g gG でもコマンド内での移動をしたい場合は以下の設定を用いて下さい。

ble-bind -m vi_nmap -f 'g g' vi-command/first-nol
ble-bind -m vi_omap -f 'g g' vi-command/first-nol
ble-bind -m vi_xmap -f 'g g' vi-command/first-nol
ble-bind -m vi_nmap -f 'G' vi-command/last-line
ble-bind -m vi_omap -f 'G' vi-command/last-line
ble-bind -m vi_xmap -f 'G' vi-command/last-line

【ノーマルモード】 C-r: やり直し vs インクリメンタル検索

ノーマルモードでは C-r は既定でやり直しを実行します。 GNU Readline のようにノーマルモードでもインクリメンタル検索を用いたい場合は、以下の設定を使用します。

ble-bind -m vi_nmap -f 'C-r' history-isearch-backward

注意: インクリメンタル検索は Vim モーションとして実装はされていないので、レジスターやオペレーターとの協調動作はしません。

surround.vim

github.com:tpope/vim-surround に由来する一部の機能もお使いいただけます。 これらを利用するためには ~/.blerckeymap_vi_load フックで以下の設定を追加します。

# keymap_vi_load フック内
source "$_ble_base/lib/vim-surround.sh"'

現在、ys, yss, yS, ySS, cs, ds, vS, vgS にのみ対応しています。

この実装 vim-surround.sh では、 束縛 yscs で挿入される括弧(囲み文字列)の種類を ble 設定変数によって変更できます。 設定例を次に示します。

# keymap_vi_load フック内
bleopt vim_surround_45:=$'$( \r )' # ysiw- に対して
bleopt vim_surround_61:=$'$(( \r ))' # ysiw= に対して
bleopt vim_surround_q:=\' # ysiwq に対して
bleopt vim_surround_Q:=\" # ysiwQ に対して

これらの変数によって、ysiw等に続いて入力する文字に対応する囲み文字列を設定します。 vim_surround_〈数字〉 の形式の設定変数は、十進表記のUnicode番号 〈数字〉 で指定される文字に対する設定です。 vim_surround_〈英字〉 の形式の設定変数は、文字 〈英字〉 に対する設定です。 値に CR(Bashスクリプト中では$'\r' で指定できます)が含まれる場合、当値は最初に出現するCRを境に二分割され、それぞれが左右の囲み文字列に用いられます。 値に CR が含まれない場合は、この値がそのまま共通の左右の囲み文字列として使われます。


[ 日本語 | English ]

Clone this wiki locally