コマンドラインで長いコマンドを打ち込む

ばよえ〜ん(訳:Vim Advent Calendar 2012への8回目の投稿です)

この記事はVim Advent Calendar 85日目の記事です。
前回は@mittanさんのVimmer養成ギプスでした。

目次

  • 長いコマンドを打ち込むのを省力化する
  • 方法その1: マッピング
  • 方法その2: altercmd
  • 方法その3: ambicmd

長いコマンドを打ち込むのを省力化する

コマンドラインで長いコマンド打つの、だるいですよね。
特にプラグインのユーザ定義コマンドは、被らないようprefixとしてプラグイン名を付けるため、かなり長かったりします。


試しに長いコマンドトップ10を列挙してみました。(capture.vimが必要です)

:if exists(':Capture') != 2 | echomsg 'please install http://github.com/tyru/capture.vim' | finish | endif
" ユーザ定義コマンドをバッファに出力
:Capture command
" 各行にコマンド名のみを置く形に整形
:1delete
:%s/^\s*\%(\S\+\)\?\s\+\([A-Z]\w*\).*/\1
" コマンド名の文字数 + 半角空白を行頭に追記
:%s/^/\=len(getline("."))." "/
" 文字で逆順にソート (!をつけると逆順)
:sort! n
" 行頭の文字を削除
:%s/^\d\+\s\+//
" トップ10以降を削除
:10,$delete

シェルスクリプトみたいですね。
余談になりますが、シェルスクリプトみたいにパイプは使えないですが、以下の理由からシェルスクリプトより試行錯誤はしやすいと思います。

  • バッファに対して副作用を与えながら「対話的に」書き換えていく
  • リダイレクトするまでもなく、バッファに結果が残る&undoで直前の結果を取り消せる

なので私は、複雑なテキスト整形はVim上でやることがあります。


自分のVimでも試したい!って方は上記をファイルにコピペして保存してファイルを開いたまま「:so %」すると結果を出力できます。
自分のVimだとこんな結果になりました。(やはりネオコンがランクインしたか...)

TextobjJabracesDefaultKeyMappings
TextobjFunctionDefaultKeyMappings
NeoComplCacheAutoCompletionLength
TextobjBetweenDefaultKeyMappings
TextobjSyntaxDefaultKeyMappings
TextobjIndentDefaultKeyMappings
TextobjEntireDefaultKeyMappings
NeoComplCacheCachingDictionary
TextobjLineDefaultKeyMappings
閑話休題

こんな長いコマンド打ってられないですよね。
今回はそんな長いコマンドを打つのを省力化する方法を3つほど紹介します。

方法その1: マッピング

長いコマンドを打ち込むのを省力化する基本的な方法は、マッピングを割り当てることです。
でも

  1. 全ての長いコマンドにいちいちマッピングを割り当てるのはもったいない
  2. マッピングには引数を与えられない
  3. コマンドラインの方が現在何を打ち込んでいるか見えるため安心感がある
  4. コマンドラインならバックスペースなどで入力中のコマンドを修正できる

3は'showcmd'オプションで解決する問題ではあります。
ただ4の理由のために私は次のaltercmdというVimプラグインを用いた方法が好きです。

方法その2: altercmd

kana氏作のaltercmdというVimプラグインがあります。
kana/vim-altercmd · GitHub

現在altercmdには複数のバージョンが存在します。
オリジナルのkana氏のバージョンと、魔改造を加えた私のバージョンです。
それぞれの違いはwikiにまとめてあるので、どっちを使っていいか迷う方は参照してみてください。
(ただ今見ると例がなかったり手抜き感満載で分かりにくいですね...直します...)

オリジナルのkana版とtyru版の違い · tyru/vim-altercmd Wiki · GitHub

私のバージョンのリポジトリは以下です。
tyru/vim-altercmd · GitHub

設定例

自分の.vimrcからaltercmd関係のものを(「:Capture g/MapAlterCommand」して)抜き出してみました。
MapAlterCommandは私の.vimrcで定義したコマンドなので、altercmd.vimが提供しているコマンドではありません。

call altercmd#load()
command!
\   -bar -nargs=+
\   MapAlterCommand
\   CAlterCommand <args> | AlterCommand <cmdwin> <args>

" 組込みコマンド
MapAlterCommand th     tab help
MapAlterCommand t      tabedit
MapAlterCommand sf     setf
MapAlterCommand hg     helpgrep
MapAlterCommand ds     diffsplit
MapAlterCommand do     diffoff!

" For typo.
MapAlterCommand qw     wq
MapAlterCommand amp    map

" 自作コマンド
MapAlterCommand epa EchoPath
MapAlterCommand rtp EchoPath<Space>&rtp
MapAlterCommand ep Expand
MapAlterCommand has Has
MapAlterCommand gp GlobPath
MapAlterCommand qf QuickFix
MapAlterCommand h[elp] Help
MapAlterCommand ctags Ctags

" restart.vim
MapAlterCommand res[tart] Restart
MapAlterCommand ers[tart] Restart
MapAlterCommand rse[tart] Restart

" open-browser.vim
MapAlterCommand o[pen] OpenBrowserSmartSearch
MapAlterCommand alc OpenBrowserSmartSearch -alc

" ku.vim
MapAlterCommand ku Ku

" vimshell
MapAlterCommand sh[ell] VimShell

" ref.vim
MapAlterCommand ref         Ref

" MapAlterCommand alc         Ref -new alc
MapAlterCommand rfc         Ref -new rfc
MapAlterCommand man         Ref -new man
MapAlterCommand pdoc        Ref -new perldoc
MapAlterCommand cppref      Ref -new cppref
MapAlterCommand cpp         Ref -new cppref
MapAlterCommand py[doc]     Ref -new pydoc

" prettyprint.vim
MapAlterCommand pp PP

" github.vim
MapAlterCommand gh Github
MapAlterCommand ghi Github issues

" ohmygrep.vim
MapAlterCommand gr[ep] OMGrep
MapAlterCommand re[place] OMReplace

" fileutils.vim
MapAlterCommand rm Delete
MapAlterCommand del[ete] Delete
MapAlterCommand mv Rename
MapAlterCommand ren[ame] Rename
MapAlterCommand mkd[ir] Mkdir
MapAlterCommand mkc[d] Mkcd

" capture.vim
MapAlterCommand c[apture] Capture

上記の設定例を見ると分かりますが、

MapAlterCommand h[elp] Help

のようなhelpでもよく見かける記法を使うことができます。
上記の例は「h」「he」「hel」「help」を「Help」に展開する設定です。

方法その3: ambicmd

thinca氏作のambicmdというVimプラグインがあります。
thinca/vim-ambicmd · GitHub

これはaliasを.vimrcで設定する必要もなく、

  • 存在しないコマンドを打ち込み
  • 既存のユーザ定義コマンドに似たコマンドがあるなら

altercmdのようにコマンドを展開してくれます。


「似たコマンド」はどのように判断されるのか分かりづらい(というかアルゴリズム的な部分は私も分かっていない)ので、例を挙げると「:nccl -> :NeoComplCacheLock」のような展開が行われるようです。
上で「ようです」と書いたように、実は私はambicmdは使っていません。
altercmdのように明示的にaliasを追加する方が何が展開されるのか分かって安心感があるからです。
ただaltercmdのように設定を書く必要がなく、マッピングやaliasを忘れる心配がないため、こちらの方法が好きな方もいると思い、紹介しました。

:wqa!

次のVim Advent Calendarは@manga_osyoさんです。