2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VimAdvent Calendar 2024

Day 16

vimのメニューの本来の力を発揮させてプラグイン並(?)にする設定

Last updated at Posted at 2024-12-14

vimの戦闘力の上昇の弊害

みなさん、vimのプラグインを使っていますか?きっと使っているでしょう。僕もです。けれど、けれどね!vimrcは肥大化し、プラグインが星の数になると下記の弊害が出てくるのです。

  • vimrcの保守がダルくなる
  • vimが重くなる
  • 他の環境に移行しにくくなる
  • プラグインがEOLを迎えると戦闘力が落ちる

そこで、意図的にvimの戦闘力を落す事を考える事にします。(プラグインを書いてるお前が言うなと言われそうですが。)
で、思いついてコード書いてみました。

ただし、この方法は弊害もあります。メニューのような答があるもの以外には使えません。ま、正直プラグインレベルにはならないかもしれないけれど、僕は満足していますよ。

vimのメニュー

どれだけの人が使っているのかわからないけれど、vimにはメニューがあります。これの事です。

:emenu

このメニューを中心に操作体系を見直そうと思いました。

設定無しのこのメニューの問題点

無設定だった場合、このメニューはgvimじゃないと動きません。そして、補完はきくもののタブキーを何度も押さないといけません。これじゃあプラグイン入れる事になりますよね。
何が悪かったのでしょうか?これはきっと、キーストロークが多いのが問題なのです。そこで、menuのキーストロークを可能な限り減らす事を考えます。

eコマンドのキーストローク

ファイルを開けますよね。この時にeコマンドを使うはずです。ですが、eコマンドを使って普通にタブで補完する場合のキーストロークは下記の通りです。

:e <TAB>

4ストロークですね。ですが、補完する事を前提とするならば、このうち必須の情報は

:e

の2ストローク、つまり「コマンドラインに入るよー」「使うコマンドはeだよー」になります。という事は、他を全てマップして自動補完できるようなコードをさしこめば完成です。

自動補完

自動補完のコードはお行儀を気にしなければ簡単です。

function! BusyCmdComplete(num=1)
  for c in 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
    exec $"cnoremap {c} {c}<Tab>"
  endfor
endfunction

ひでえ!全てのキーストロークにTABを付けてるだけじゃん!極めてお行儀がわるいので、これはコマンドラインから抜けた時に解除するし、タブじゃないキーにも対応したりするべきなのですが、ま、本格的にプラグイン開発しないならこんなものでいいでしょう。

素の補完とメニューの設定

ここは、ま、こんな感じでしょう。ごく普通のvimrcです。ここでmenu.vimをsourceしてメニューをかさまししていますが、完全に好みです。

set wildignorecase
set wildmenu
set wildmode=longest:full,full
set wildoptions=pum,tagfile
source $VIMRUNTIME/menu.vim
set cpo-=<
set wcm=<TAB>

自動補完付きコマンドラインメニュー完成

上記の考えにより、このように書きました。

function! BusyCmdComplete(num=1)
  for c in 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
    exec $"cnoremap {c} {c}{repeat(GetWildcharm(),a:num)}"
  endfor
endfunction

function! GetWildcharm()
  return split(trim(execute('set wildchar?')), '=')[1]
endfunction

function! OneShotComplete(tabnum=1)
  exec "set wildmode=full:longest,full"
  exec "au CmdlineLeave * cmapclear" 
  exec $"au CmdlineLeave * ++once set {trim(execute('set wildmode?'))}" 
  exec $"call BusyCmdComplete({a:tabnum})"
endfunction

function! WrapOneShotComplete(command, tabnum=1)
  return $":call OneShotComplete({a:tabnum})<CR>"
        \.$":{a:command} {GetWildcharm()}"
endfunction

function! CompNoremap(trigger, command, tabnum=1)
  exec $"noremap {a:trigger} {WrapOneShotComplete(a:command, a:tabnum)}"
endfunction

command! -nargs=* CompNoremap call CompNoremap(<f-args>)

使い方 emenu(タブ2回パターン)

例えば、Ctr-pでメニューを表示したければこんな感じ。

CompNoremap <C-p> emenu 2

emenuコマンドをCtr-pで呼び出して、自動補完。この自動補完の時にタブは2回押すことで、サクサクメニューを掘っていけます。
例えば、エンコードの方法を変えたりするコマンド、覚えていますか?僕は覚えていないというか、++enc=utf-8なのか++enc=UTF8なのかで混乱するから、vimrcにこうかきます。

menu File.Encoding.UTF-8 :e ++enc=utf-8<CR>
menu File.Encoding.SJIS :e ++enc=sjis<CR>
menu File.Encoding.CP932 :e ++enc=cp932<CR>

これも先程の自動補完でたどっていけますね。

使い方 e(タブ1回パターン)

例えばファイルを開きたいならこんな感じ。

CompNoremap <C-p>e e

今回は自動補完の時にタブを2回押すとディレクトリを勝手に辿ってしまって不都合なこともあるから、タブの数は1回。(デフォルトで1回なので書いてないです)

もちろん、!とかbとかもできます。つまり、このインターフェイスがあればこんな簡易なvimrcでほぼ全てのコマンドを網羅的にサクッと補完できるわけですね。
キーストロークが減るのでプラグインには勝てないけれどバッファ管理、タブ管理、ディレクトリのファイル確認等もできますね。

候補が複数出た時に辿れないよ!

おちつくんだ。
Ctr-mを押せばいいから。

おわりに

僕「あ、またvimrcが肥大化した。しかたない、このコードはプラグインにでもしておくか。」

そして今日も彼がインストールしているvimプラグインが一つ増えたのであった。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?