4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[VimとEmacsの共存] VimでEmacsキーバインドを使えるようにしてみた

Posted at

なぜEmacsキーバインドが良いのか?

どのキーボードもだいたい方向キーDelキーはホームポジションを崩さないと押せない位置にあります
これは少しの差ではありますが塵も積もれば多大なロス
いち早く改善すべき習慣であると思ってます

その点、EmacsのキーバインドはCtrlキーとの組み合わせで操作するので
ホームポジションを崩さずにカーソルの移動や削除が出来ます

マスターするととっても楽ちん
手の動きも少なくなり疲労軽減、作業効率増大、これなしではテキスト入力出来なくなるレベルです
(前の職場のWindowsPCでもキーマッピング登録して使ってたほど中毒性があります)

しかも幸いなことにMacのほとんどのアプリケーションではデフォルトでこのキーバインドが使えます
なのでSlackの返信やGoogleでの検索、報告書の作成など、Emacsキーバインドをめちゃくちゃ多用してます

使わない手はないのです!!

Vimとの共存

話は変わりまして、よく宗教論争として争っているVimももちろんホームポジションを崩さず様々な操作が出来ます
私自身も今ではすっかりVimメインの生活になりVim無しでは生きていけなくなりつつあります
しかし唯一不満なのがInsertモードでの操作
今のVimは方向キーでの操作も出来るのですが方向キーまで手を伸ばす気にはなれません
独自のキーマッピングを定義するのも考えましたが普段使ってるEmacsキーバインドとの脳の切り替えコストがしんどい

そこでVim + Emacsを実現出来ないかと考えました

EmacsキーバインドはCtrlキーを組み合わせるのでVimのInsertモードとの相性も良さそう

さっそく取り掛かろう!と考えたものの
検索ワードが抽象的過ぎて同じような事をしようとしてる人をググっても見つけられず、、、

結局自力で考えて導入しました
なんとか問題なく動くようになったと思います

今回移植するEmacsキーバインド

Ctrl + p   # カーソルを上へ(↑矢印)
Ctrl + n   # カーソルを下へ(↓矢印)
Ctrl + f   # カーソルを右へ(→矢印)
Ctrl + b   # カーソルを左へ(←矢印)
Ctrl + a   # カーソル行の行頭へ移動
Ctrl + e   # カーソル行の行末へ移動
Ctrl + h   # 左の文字を削除(BackSpece)
Ctrl + d   # 右の文字を削除(Del)
Ctrl + k   # カーソルから右を全て削除

なるべくVimの機能で完結させたいのでよく使うキーバインドだけに絞りました

当然もともとあるキーマッピングを上書きしてます
コピーする際は再マッピングする等しっかり検討してください
私の場合は衝突する既存のVimキーマッピングは使わないものなのでOKです

導入

実際にVimの設定ファイル(vimrcかinit.vim)に書き込んでいきます
下記をコピペでOKです

vimrc
" Emacsキーバインド
inoremap <silent> <C-p> <Up>
inoremap <silent> <C-n> <Down>
inoremap <silent> <C-f> <Right>
inoremap <silent> <C-b> <Left>
inoremap <silent> <C-a> <Home>
inoremap <silent> <C-e> <End>
inoremap <silent> <C-h> <BS>
inoremap <silent> <C-d> <Del>
inoremap <silent> <C-k> <ESC>:EmacsKillCommand<CR>a

" <C-k>自作コマンド
command! -nargs=0 EmacsKillCommand call EmacsKillCommand()
function! EmacsKillCommand()
  let s:currentLine = getline('.')
  let s:nextLine = getline(line('.')+1)
  let s:currentCol = col('.')
  let s:endCol = col('$')-1

  if s:currentLine == ""        " 現在の行が空白か判定
    :normal dd
  else
    if s:currentCol == s:endCol " カーソルが最終位置かどうか判定
      if s:nextLine == ""       " 次の行が空行か判定
        :normal J
      else
        :normal Jh
      endif
    elseif s:currentCol == 1    " 行の頭か判定
      normal D
    else
      :normal lD
    endif
  endif
endfunction

これでInseertモードの際にEmacsキーバインドを駆使して操作出来るようになります
ちなみに<C-k>だけ本来の動作にするにはちょっと複雑だったのでスクリプト書きました(初Vimスクリプト)
力不足で完全なる<C-k>の動きにはなってませんがほぼほぼコピー出来ているので実用上はとりあえずいいことにしてます^^;

とりあえず快適〜!

改善の余地がある部分

  • 2文字目で<C-k>を実行すると1文字目判定されてしまう
example
t|est  # tとeの間(2文字目)で実行

期待してる動作: t   # estが削除される
実際の動作:       # すべて削除されてしまう

原因: InsertからESCでNormalモードに戻った際に1文字目と同じ位置になるため
  • 現在行が空白且つ次行が1文字目から存在する場合、<C-k>を実行するとカーソル位置が2文字目になってしまう
example
|    # 空き行
test

期待してる動作:
|test  # testの前にカーソル
実際の動作:
t|est # tとeの間にカーソル
原因: 最後にaでInsertモードに戻っているため
(これをやらないと他の箇所で実行の際に1文字前にカーソルが行ってしまうためしかたなく…)

良い改善案ある方、助言頂けると嬉しいです🙇‍♂️

番外編1 CommandモードでもEmacsキーバインドを使う

Commandモード(EXモード、コマンドラインモード)でも使いたいと思って作成しました

下記をコピペでOKです

cnoremap <C-p> <Up>
cnoremap <C-n> <Down>
cnoremap <C-f> <Right>
cnoremap <C-b> <Left>
cnoremap <C-a> <Home>
cnoremap <C-e> <End>
cnoremap <C-h> <BS>
cnoremap <C-d> <Del>
cnoremap <C-k> <Right><C-\>egetcmdline()[:getcmdpos()-2]<CR><BS>

個人的には革命レベルで使いやすくなりました
特に<C-a>からの<C-k>での全削除<C-p><C-n>での履歴遡れるが最高!

InsertモードではVim本来のNormalモードで移動で問題ないよ!っていう生粋のVimmerの方でも
これはあった方が便利なんじゃないかな、と思います😄

そしてまたしても<C-k>の記述が難関
コチラのStackOverFlowを参考に改良してみました
(そのままでは行頭では期待動作にならなかったので右移動→<C-k>→BackSpeceさせてます。力技w)

番外編2 さらにEmacs化!?

ここからは更に意見が分かれると思いますが
VisualモードとNormalモードでもEmacsキーバインド使えるようにした設定も置いておきます

" VisualモードとNormalモードはお好みで
vnoremap <silent> <C-a> <Home>
vnoremap <silent> <C-e> <End>
nnoremap <silent> <C-f> <Right>
nnoremap <silent> <C-b> <Left>
nnoremap <silent> <C-a> <Home>
nnoremap <silent> <C-e> <End>
nnoremap <silent> <C-k> :EmacsKillCommand<CR>
nnoremap <silent> <C-y> p

個人的にはNormalモードやVisualモードでは
Vim本来のキーバインドやモーションが使いやすいのでそれを使うようにしています
利用頻度が高いとか好みに合わせてどうぞ!

参考URL

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?