Vim

Vimの挿入モード抜けるとき英数モードにするアレ(Karabiner設定例)

Vimの挿入モード抜けるとき英数モードにしたい問題

古代からあるアレです。

我々日本人はVimで日本語を入力することがあるわけですが、そのままノーマルモードに復帰すると、ノーマルモードのコマンドを入力したとき、変換されてしまいンアーッってなるやつです。

この対策として、キーリマップアプリを利用して、EscキーにEsc+英数キーを割り当てるという方法が知られています。

このジャンルではKeyRemap4MacBookというアプリが著名でしたが、現在は改名してKarabinerになっています。

今回、Karabinerの設定がまとまりましたので、記事にしてみます。

private.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"?>
<root>
<list>
<item>
<name>LeaveInsMode with EISUU(Terminal)</name>
<identifier>private.app_terminal_esc_with_eisuu</identifier>
<only>TERMINAL</only>
<autogen>--KeyToKey-- KeyCode::ESCAPE, KeyCode::ESCAPE, KeyCode::JIS_EISUU</autogen>
<autogen>--KeyToKey-- KeyCode::N, VK_OPTION, KeyCode::ESCAPE, KeyCode::JIS_EISUU</autogen>
<autogen>
__SimultaneousKeyPresses__
KeyCode::J, KeyCode::K,
KeyCode::ESCAPE, KeyCode::JIS_EISUU,
Option::SIMULTANEOUSKEYPRESSES_RAW
</autogen>
</item>
</list>
</root>

only要素でTERMINALを指定した場合、各種ターミナルエミュレータ(で実行されるVim)はもちろんのこと、MacVimでも有効になるようです。

指定内容は以下の通りです。

入力 出力
Esc Esc+英数
⌥n Esc+英数
jk同時押し Esc+英数

徐々にめんどくさくなっていった歴史ともいう。

なお、SimultaneousKeyPressesのオプションをOption::SIMULTANEOUSKEYPRESSES_STRICT_KEY_ORDERにすると、指定した順序で押した場合のみ有効になります。

Key Repeat

ただ、初期設定だと同時押し判定が厳しすぎて押しづらいので調整します。

「Preferences > Key Repeat > Simultaneous Key Presses > Delay Threshold of Key」を50msから200msにしました。

これで、サクッとノーマルモードに復帰できるようになります。

シェル関数や自作スクリプトをサクッと定義する

新しいコマンド(シェル関数や自作スクリプト)をガンガン書いていきたいという時に。

なお、コマンド名にスペースを含むことを想定していません。

前提

管理を楽にするために、あらかじめ設定ファイルを分割しておきます。

シェル関数

以下の関数を定義しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
afunction () {
tmp=/tmp/$(date '+%s').sh #一時ファイルパスを定義
# 一時ファイルにテンプレートを書き込み
echo "$1 () {
}" > $tmp
vim $tmp +2 # Vimで一時ファイルを開き2行目に移動
echo "Add this function? [Y/n]" # 編集結果をファイルに書き込むか確認
read ANSWER
ANSWER=`echo $ANSWER | tr y Y | tr -d '[\[\]]'` # どっかから拾ったANSWER整形ワンライナー
case $ANSWER in # そのままエンターまたはyesとかなら
""|Y* )
cat $tmp >> ${bash_conf}/function-init.bash # 一時ファイルの内容を設定ファイルに追記
source ~/.bashrc # 設定ファイルを再読み込み
;;
* )
echo "Canceled"
;;
esac
}

aFunction hogeとするとhoge関数を書き始めることができます。

スクリプトファイル

以下の関数を定義しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
csh () {
if [ $1 ];then # 引数がある場合
tmp=/tmp/$(date '+%s')_$1.sh # 一時ファイルパスを定義
echo "#!/bin/bash" > ${tmp} # シバンを書き込み
echo "" >> ${tmp} # 空行を書き込み
vim ${tmp} +2 # Vimで開いて2行目に移動
echo "Add this script? [Y/n]" # 確認メッセージ
read ANSWER
ANSWER=`echo $ANSWER | tr y Y | tr -d '[\[\]]'`
case $ANSWER in
Y* ) # y入力時のみ
mv ${tmp} ~/scripts/$1.sh # 一時ファイルをスクリプト用ディレクトリに移動
chmod +x ~/scripts/$1.sh # 実行権限を与える
ln -s ~/scripts/$1.sh /usr/local/bin/$1 # パスの通ったディレクトリにシンボリックリンクを張る
echo "Script created"
;;
* )
echo "Canceled"
;;
esac
else
echo Input script name
fi
}

csh hogeとするとスクリプトファイルを書き始めることができます。

こっちはより慎重にやるべきだから、作成とリンクを分けたほうがいいかな?

分けてみよう

こんな感じかな?

1
2
3
4
5
6
7
8
9
10
11
# スクリプトファイルを作成
csh () {
if [ $1 ];then # 引数がある場合
file=~/sctipts/$1.sh # ファイルパスを定義
echo "#!/bin/bash" > ${file} # シバンを書き込み
echo "" >> ${file} # 空行を書き込み
vim ${file} +2 # Vimで開いて2行目に移動
else
echo Input script name
fi
}
1
2
3
4
5
6
7
# スクリプトディレクトリ内のファイルをパスの通ったディレクトリにシンボリックリンク
lsh () {
for file in `ls`
do
ls -s file /usr/local/bin/${file%.sh} >& /dev/null # リンク済みのファイルがエラーを吐くので捨てる
done
}

Vimでbash IDEするのにコマンド定義してみた

bashスクリプトを書きすぎていて、Vimで書きながら実行したいとか思ったのでやってみました。

結論としては.vimrcに以下を記述。

1
:command! Run :w !sh

:Runでバッファ内容を実行します。

キーリマップでやってもよかったのですが、元のキーバインドをろくすっぽ把握していないのでとりあえずコマンド定義で。

ファイルとして保存しない無名バッファにコマンドを書き捨てる用途を想定しているので、作業が終わったら:q!で保存しないで終了します。

homebrewで何かインストールするときとか、複数行のコマンドを微妙に調整しつつ実行する際に非常に便利です。