Blank File

LinuxとかPythonとかVimとか、趣味でいじる感じで

端末上のvimでctrl+space(ついでにプラグインの上書き回避)

最近はコードや英文を書く時はもっぱらVimを使っています。

Vim以外のエディタでもCtrl+Spaceキーの組み合わせでキーワード補完したり便利なショートカットが割り当てられたりしていると思います。私もこの組み合わせは押しやすいのでCtrl+Spaceにsnippet展開を割り当てています。

snippetは、例えば

class|

カーソルが|の位置にあるときにCtrl+Spaceを押すと

class <name>(object):
    def __init__(self):
        |

とか一気に展開してくれるやつです。vimプラグインneosnippetを使わせて頂いてます。これが非常に便利で重宝しています。

ところが、端末(konsole)上のvimだとこのキーの組み合わせが正常に認識されませんでした。これがなんとなく解決できたので書き残しておきます。

OSはDebian (wheezy)で端末はkonsoleです。

1. Nulをctrl+spaceにmapする

これは結構情報が多かったのですぐにわかりました。

(参考: vim のkeymapでCtrl-Spaceが設定できなかったので調べてみた。 - dgdgの日記

端末上ではCtrl+Spaceが押された時に<Nul>が送出されているそうです。なのでこれを.vimrcでmapしてしまえば解決するはずです。

imap <Nul> <C-Space>

・・・ダメでした。端末のvimを起動してもこの設定が反映されていませんでした。:map <Nul>を見ると、imapは残っていません。プラグインか何かで消されてしまっているようです。

2.プラグインの上書きに負けない

プラグインで設定(特にキーマップ)を上書きされることはよくあります。そして困ることが頻繁にありました。なんとなく強引ですが、こちら(Avoid the escape key - Vim Tips Wiki)にちょうどいい対策が載っていたので使わせてもらいました。

autocmd VimEnter * imap <Nul> <C-Space>

autocmdのイベントでVimEnterを指定すれば基本的にプラグインより後に読み込まれるので、プラグインでの上書きはある程度回避できます。今回はこれで無事にCtrl+Spaceが端末上のvimでも使えるようになりました。

条件分岐なども含めて、結局.vimrcには以下のように書きました。

if !has('gui_running')
  augroup term_vim_c_space
    autocmd!
    autocmd VimEnter * map <Nul> <C-Space>
    autocmd VimEnter * map! <Nul> <C-Space>
  augroup END
endif

あとで使うかもしれないので片っ端からmapしています。mapでnmapとvmapとomap、map!でimapとcmapに相当するらしいので、通常使う範囲ではこれで十分なはずです。(※mapではなくnoremapにしてしまうと<C-Space>以降のマッピングが反映されないので注意。)これでimap <C-Space> hogehogeなどのマッピングが端末上でも有効になります。

一応augroupに入れましたが、今回はVimEnterしかイベントに指定していないのであまり意味ないと思います。後で設定を追加するかもしれないのと、なんとなく保険のつもりで入れておきました。(autocmd, augroupについてはこちらにわかりやすい説明があります:Vim - おさらい autocmd/augroup - Qiita [キータ]

よく考えたらafterディレクトリに入れてもよかったのかも。今回はとりあえず期待する設定になったのでこのままにしておきます。