ホーム > タグ > lv2

lv2

Hack #168: シェル以外から立ち上げたVimでもシェル側の環境変数PATHを考慮したコマンドの呼び出しを行う

問題

:!ruby %

このコマンドが呼び出すrubyとして期待されるものは、/usr/bin/rubyであったり、/usr/local/bin/rubyであったり、はたまた~/git/ruby/local/bin/rubyのように独自で用意したものであったりします。

zshなどのシェルでは、~/.zshrcなどの設定ファイルに

export PATH=~/git/ruby/local/bin/ruby:$PATH

などと記述することによって、単にrubyなどとしてコマンドを呼び出したときに実際にどの場所のコマンドが呼び出されるか制御でき、またそのシェルから起動したVimもそれに準拠します。これはCUIでもGUIでも同様です。

しかしながら、シェルを経由せずVimを起動した場合。~/.zshrcなどに記述したロードパスに関する情報は得られません。MacのDockなどから起動しつつ、そのVimであなたのホームディレクトリ以下にあるrubyなどを呼び出すにはどうすればいいのでしょうか。

解決法

vimprocを用います。vimprocはVimの変数$PATHを参照してコマンドを実行します。

vimprocを用いてのコマンドの実行とVimのデフォルトの機能との対応は以下のようになります。

  • コマンドを単に実行する

    • Vim: :!command
    • vimproc: :call vimproc#system('command')
  • コマンドを実行した結果をバッファに書き足す

    • Vim: :r!command
    • vimproc: :call append(line('.'), vimproc#system('command'))
  • コマンドを実行した結果を変数に格納する

    • Vim: :let x = system('command')
    • vimproc: :let x = vimproc#system('command')
  • コマンドをバックグラウンドで実行する

    • Vim: :!command &
    • vimproc: :call vimproc#system_bg('command')

冗長で不便なので、キーマッピングを追加するか、あるいは:!の使用をさけてかわりにvimshellを用いるとよいでしょう。

nnoremap :! :call vimproc#system('

さて、:!system()を間接的にもっとも頻繁に使うのはなんといってもquickrunでしょう。quickrunでvimprocを用いるためには、以下の設定を~/.vimrcに記述します。

let g:quickrun_config['*'].runmode = "async:remote:vimproc"}

余談ですが、著者はこれにquickrun分割場所指定もあわせ、以下のように指定しています。

let g:quickrun_config['*'] = {'runmode': "async:remote:vimproc", 'split': 'below'}

これで、quickrunで好きなrubyを使いたい放題です。

補足

本Hackは一般的な外部コマンドの実行について述べましたが、この方法は特に、Rubyのような複数の同名のコマンドをインストールする必要があるようなコマンドで役に立ちます。著者はRuby 1.8.6, 1.8.7, 1.9.2, 1.9.3をすべて使用しているため、本設定が大変効いてきています。

なおVimによるRubyプログラミングをより効率的かつ快適に行うための方法については、"Vim" at RubyKaigiに参加し、基調講演を聞く、ライトニングトークの発表を聞く、ライトニングトークで発表する、そしてほかの参加者とその場で情報交換することによって、活き活きとした生の情報を大量に得ることができることは疑いの余地がないでしょう。

参考文献

ujihisa

Hack #165: neocomplcache Hacks(6) インクルード補完

今回はインクルード補完です。neocomplcacheに実装されたインクルード補完はあらかじめ設定しておく必要がありますが、使いこなせばタグ補完を越えた使い勝手となります。

インクルード補完とは

インクルード補完とは、バッファ中のインクルード文を解析して、補完候補に加える補完のことです。Vim自体にもインクルード補完が備わっていますが、Perlなど'path'が多数のディレクトリに設定されている言語では重すぎて使いものになりません。neocomplcacheのインクルード補完は結果をキャッシュすることで、Vim標準のインクルード補完に存在する欠点を補うために開発されました。タグ補完と比較すると、インクルードしているファイルだけ解析するので補完候補が多すぎる問題が発生しにくい、あらかじめタグファイルを生成する必要がない、といった利点があります。

インクルード補完の制限

インクルード補完は強力ですが、万能ではありません。'path''includeexpr', 'include'といったオプションが適切に設定されている必要があります。特にWindows環境では、ftpluginなどで設定する必要があるかもしれません。インクルード補完ではctagsを利用するので、システムにインストールされている必要があります。ctagsが存在しなかったり、ctagsに対応していない言語の場合(D言語など)はバッファをそのまま解析するので、buffer_completeと動作が同じになります。

今後のインクルード補完

現在実装されているインクルード補完はまだ実験的な意味合いが強いです。 今後は、gtagsへの対応やechodocへの対応、遅延キャッシュなどを考えています。 ただしgtagsはカレントディレクトリにタグファイルを作るらしく、ctagsのように簡単に解析するのは難しそうです。

参考文献

neocomplcache.vim のインクルード補完の使い方 thincaさんのインクルード補完解説記事。neocomplcache Ver.3.06を対象としていて、neocomplcache Ver.5.0がリリースされた現在では変数名等が古くなっていますが、参考になると思います。

Shougo

Hack #163: VimをVimスクリプトインタプリタとして使う

viの前身であるedは、シェルスクリプトなどで文字列置き換えのために使うことができます。 (fileというファイルの中身を全行逆転させる例です)

ed - file <<EOS
g/^/m0
write
qall!
EOS

g/^/m0^にマッチする行に対して:m0という操作を適用するコマンドです。 :m0は分かりやすく書くと:move 0で、引数の行の下に現在の行を持っていくという動作をします。 ^はどの行にもマッチするので、:m0で全部の行に対して上からマッチした順に1行目に持っていきます。 操作が終わると全行が逆になっているというわけです。

また:write:qall!は全行逆になったバッファをfileに書き込むために必要です。

VimについてくるexというコマンドはedのVim版とも言えるものですのでもちろん上のようなことができます。 しかしデフォルトでは.vimrcやプラグインなども読み込んでしまうため、 「素のex」として使いたい場合は「-u NORC –noplugin」を指定する必要があります。 さらにVimmerとしてはVimの機能が使えず戸惑わないように「-N」も指定する必要があります。 よってexをVimスクリプトインタプリタとして使うには以下のように起動すればできそうです。

ex -N -u NORC --noplugin

冒頭の例のex版はこのようになります。

ex -N -u NORC --noplugin file <<EOS
g/^/m0
write
qall!
EOS

デフォルトでもこのようにVimスクリプトインタプリタのように使えなくはないのですが、以下のような難点があります。

  1. ファイルに対して実行するには末尾に必ず:write:qall!をつけなければならず面倒
  2. ファイルに対して実行する際に元のデータを壊してしまう
  3. いくつかの定型的なオプションを付けるのが面倒
  4. 標準入力からスクリプトを読み込むのでファイルを標準入力から読み込めない

解決

iexを使います。 これはVimスクリプトをPerl、Ruby、Pythonなどの多くのLLのインタプリタと同じ感覚でVimスクリプトを実行させることができる優れ物です。

$ echo 'g/^/m0' >reverse.vim
$ cat ~/.vimrc | iex reverse.vim -

# -eオプションで指定することも可能
$ cat ~/.vimrc | iex -e 'g/^/m0' -

$ iex    # /bin/exが開く

詳しくはiex -hを見てください。

いくつかのVimスクリプト

おまけとしていくつかのUNIXコマンドをVimスクリプトで実装します。

tac

$ cat tac.vim
g/^/m0
$ iex tac.vim file

sort

$ cat sort.vim
sort
$ iex sort.vim file

sort -u (sort | uniq)

$ cat uniq.vim
sort u
$ iex uniq.vim file

grep

$ cat grep.vim
edit `=ARGS[1]`
execute 'v/' . ARGS[2] . '/d'
$ iex -s grep.vim ~/.vimrc vim

("vim"のみを含んだ行が表示される)

また-eオプションを使ったやり方を示すと

$ iex -s -e 'edit `=ARGS[1]' -e 'execute "v/" . ARGS[2] . "/d"' ~/.vimrc vim

のようになります。
これは一般のLLインタプリタと同じようにワンライナーのようなものを書くのに適しています。

また-sを与えることで引数の扱いを変えています。
-sを与えると中身を読み込まずにg:ARGSというListに代入するだけにします。
その他細かい違いなどはiex -hを見てください。

tyru

Hack #162: Vimを終了しても undo 履歴を復元する

Hack #8: 作業の履歴を辿るでも紹介したように Vim には編集履歴を辿る機能が充実していますが、Vim を終了したりファイルを開きなおしたりするとこの undo 履歴は消えてしまいます。

undo-persistence

現在開発中の Vim 7.3 から、新しく undo-persistence (:help undo-persistence) と言う機能が追加されました。これを使うと undo の情報をファイルに保存し、Vim を終了しても次に起動したときに undo の履歴を復元してくれるようになります。

設定

'undodir'

まず、undo 履歴を保存するファイルが作成されるディレクトリを 'undodir' オプションに設定します。これにはディレクトリをカンマ区切りのリストで指定します。 ディレクトリの指定に "." を使うと、対象ファイルのあるディレクトリを指します。デフォルトはこれです。

指定したディレクトリの中で、最初に存在したディレクトリに undo 履歴のファイルが保存されます。また、復元する際は最初に見付かったファイルから履歴を復元します。

例えば、ファイルと同じディレクトリに .vimundo と言うディレクトリがあったらそのディレクトリへ、なければ ~/.vimundo へ保存するには、以下のように設定します。

set undodir=./.vimundo,~/.vimundo

'undofile'

これはバッファローカルなオプションで、これが on のバッファはバッファの保存時に undo 履歴をファイルに保存します。また、読み込み時に undo 履歴を復元します。

全てのファイルで有効にしたい場合は単に :set undofile とすれば良いでしょう。特定のファイル、例えばホームディレクトリ以下のファイルのみで設定したい場合は以下のようにします。

augroup vimrc-undofile
  autocmd!
  autocmd BufReadPre ~/* setlocal undofile
augroup END

+persistent_undo

これらの機能は +persistent_undo がないと利用できないので、if で囲っておくと良いでしょう。

if has('persistent_undo')
  set undodir=./.vimundo,~/.vimundo
  augroup vimrc-undofile
    autocmd!
    autocmd BufReadPre ~/* setlocal undofile
  augroup END
endif

注意点

undo 履歴ファイルは 'undodir' で指定したディレクトリが "." 以外だった場合は対象のディレクトリに、フルパスのパスの区切りを "%" で置き換えたファイル名で保存されます。つまり、ファイルを移動すると履歴ファイルの名前を手動で変更しない限り undo 履歴は失われます。

また、この機能は現在開発中の Vim に含まれているものです。利用する場合は自己責任で利用してください。

thinca

Hack #161: Command-line windowを使いこなす

普段我々が何げなく使っているCommand-line modeですが、使いこなすうちに様々な欠点が目につきます。このHackでは、Command-line modeを捨て去ってしまうことを提唱します。

Command-line modeの欠点

なぜCommand-line modeが使えないかというと、次のような欠点があるからです。

編集能力が貧弱

Command-line modeは基本的にラインエディタなので、シェル並の編集しかできません。テキストオブジェクトといった便利な機能も使えないのです。

自動補完ができない

もはや筆者は自動補完のある環境が普通になってしまい、neocomplcacheがないと仕事になりませんが、残念ながらCommand-line modeでは使えません。さらに、Command-line modeは補完も貧弱なので、困ったものです。

設定が分散する

Insert modeとCommand-line modeは独立しているので、キーマップ等は別々に定義しなければなりません。これは不便です。

履歴検索が面倒

Command-line modeでは、履歴検索が簡単にはできません。

cnoremap <C-n>          <Down>
cnoremap <C-p>          <Up>

とキーマップを定義する手はあります。これなら現在入力されているものにマッチする候補を検索することができます。しかしvimshellのように一覧から履歴を検索する方法はなく、そもそも設定が面倒です。検索にはfuzzyfinderkuを使うという手もありますが、この程度のことで外部プラグインに依存するというのもどうでしょうか。

Command-line window

そこで、本HackではCommand-line modeの代わりに、Command-line windowという機能を使うことを提案します。 Command-line windowとは何かというと、Vimに組み込まれている、Ex commandを実行できるバッファのことです。 Command-line windowは'filetype'がvimであるため、Vimのvim filetype pluginがすべて使えます。 特にneocomplcacheはVimのオムニ補完を搭載し、ユーザー定義のコマンドも解析できるため、併用するとneocomplcacheのパワーを存分に発揮することができます。 neocomplcacheは補完だけでなく、コマンドの引数情報をエコー領域に表示することもできます。 neocomplcacheに実装されている、Vimのオムニ補完は仕組みが複雑なので、今後のVim Hacksで詳しく解説する予定です。 Command-line windowについて詳しい情報は、:help cmdwinを参照してください。

Command-line windowを設定する

Command-line windowはウインドウに入ったときにInsert modeにならなかったり、neocomplcacheと相性が悪かったりして使いづらいので、カスタマイズする必要があります。筆者は.vimrc中で、次のように設定しています。この設定では:を入力したときにCommand-line windowに遷移するようにしています。CmdwinEnterにautocmdを設定すれば簡単にカスタマイズできるので、皆さんも最適な設定を探してみてください。

nnoremap <sid>(command-line-enter) q:
xnoremap <sid>(command-line-enter) q:
nnoremap <sid>(command-line-norange) q:<C-u>

nmap :  <sid>(command-line-enter)
xmap :  <sid>(command-line-enter)

autocmd MyAutoCmd CmdwinEnter * call s:init_cmdwin()
function! s:init_cmdwin()
  nnoremap <buffer> q :<C-u>quit<CR>
  nnoremap <buffer> <TAB> :<C-u>quit<CR>
  inoremap <buffer><expr><CR> pumvisible() ? "\<C-y>\<CR>" : "\<CR>"
  inoremap <buffer><expr><C-h> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"
  inoremap <buffer><expr><BS> pumvisible() ? "\<C-y>\<C-h>" : "\<C-h>"

  " Completion.
  inoremap <buffer><expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"

  startinsert!
endfunction

追記: Command-line windowでは、altercmdが使用できません。これでは不便なので、tyruさんがCommand-line windowでも使えるように改造したものを公開しているので、こちらを使ってください。 私は次のように設定しています。

function! s:init_cmdwin()
        call altercmd#define('b', 'gr[ep]', 'Grep', 'i')
        " AlterCommand <buffer><mode:i> gr[ep] Grepでも可
endfunction
Shougo

Hack #157: neocomplcache Hacks(5) タグ補完 ディクショナリ補完

今回はタグ補完とディクショナリ補完です。タグ補完は微妙ですが、ディクショナリ補完は便利に使えるでしょう。

タグ補完とは

タグ補完とは、’tags’から補完候補を取ってくることで補完することです。 Vim標準では<C-x><C-v>を用います。 neocomplcacheではtags_completeというプラグインによって実装されています。 .->といったg:neocomplcache_member_prefix_patterns[&filetype]にマッチする入力のあるときに補完を行うと、 クラスのメンバのみが補完候補となる機能を持っています。 要望があったので実装しましたが、私は個人的にタグ補完が好きではありません。なぜなら、タグ補完は候補が多くなりすぎるからです。 候補が多いとneocomplcacheのキャッシュや補完動作が明らかに遅くなります。 そこでtags_complete.vimでは、g:neocomplcache_caching_limit_file_sizeよりも大きいタグファイルは自動的にキャッシュしません。 どうしても使いたいならば、:NeoComplCacheCachingTagsコマンドを実行してください。 ctagsではタグを生成できない言語も多いので、現在ではより高機能なインクルード補完を用いるべきでしょう。インクルード補完については、今後のVim Hacksで解説予定です。

ディクショナリ補完とは

ディクショナリ補完とは、登録された辞書ファイルから補完候補を取ってくることで補完することです。 前回解説したシンタックス補完も一種のディクショナリ補完と言えます。 Vim標準では<C-x><C-k>を用います。 neocomplcacheではdictionary_completeというプラグインによって実装されています。 g:neocomplcache_dictionary_filetype_lists[&filetype]に辞書ファイルを登録しておけば、自動的にキャッシュされます。 例えば、vimshellでは履歴ファイルを辞書ファイルとして登録しておけば便利です。 g:neocomplcache_dictionary_filetype_lists[&filetype]が存在していない場合、自動的に’dictionary’の値が使われます。

Shougo

Hack #156: PHPで配列リテラルを楽に入力する

問題

プログラミング言語Ruby, JavaScript, Vim scriptにおける配列は角括弧のみで構成された配列リテラルを用いて[1, 2, 3]のように表現することができます。一方、PHPというプログラミング言語ではarray(1, 2, 3)のように、arrayという予約語を用いて表現する必要があり、このことがRuby, JavaScript, Vim scriptプログラマを当惑させてきたという伝統があります。

<?php [1, 2, 3] ?>
#=> Parse error: syntax error, unexpected '[' in a.php on line 1

<?php array(1, 2, 3) ?>
#=> (nothing)

解決法

[array(と入力するようにします。ただしこのままだと[自体を入力したいときに困りますので、文脈に応じて挙動を変化させます。

PHPのFiletype Pluginファイルに以下のコードを追加します。

function! s:last_char()
  return matchstr(getline('.'), '.', col('.')-2)
endfunction
inoremap <buffer><expr> [ a:last_char =~ '\w\\|]' ? '[' : 'array(')

Filetyle Pluginは~/.vim/ftplugin/{filetype}.vimあるいは~/.vim/ftplugin/{filetype}/*.vimです。とりあえずすぐに上記機能を導入したいのであれば、

~/.vim/ftplugin/php/ujihisa.vim

に上記4行のみを記述すればよいでしょう。

上記設定を導入すると、英数文字あるいは]の直後に[を打鍵すると[がそのまま入力され、そうでない文字の直後ならばarray(に展開されます。

もう少し詳しく説明しましょう。そもそもPHPで[という記号を入力する必要があるのは、配列の要素を参照するときでしょう。配列の要素を参照するのは、カーソル位置を_で示すとして

print($aaa_

のように変数名の直後か、

print($aaa['bbb']_

このように配列の要素の参照の直後です。なお、fff()['aaa']といった書き方は言語仕様上Syntax Errorとなるので)の直後に[がくることはないと仮定できます。

それ以外の場合は[が必要ないので、全てarray(に展開します。

補足1

PHPのarray()はてっきり関数だと思っていたのですが、公式ドキュメントによるとリテラルとのことです。

Note: array() is a language construct used to represent literal arrays, and not a regular function.

http://www.php.net/manual/en/function.array.php

補足2

s:last_char()という関数で定義した、カーソルの直前位置の文字を取得する機能に関連して、カーソル位置の文字を取得する機能の実装が以下のページで議論されています。Vim scriptを書く人は参考にしてみてはいかがでしょうか。

http://gist.github.com/444017

補足3

はじめは[1, 2, 3]といった記法でも配列となるようにPHPのパーサの方をいじろうと思ったのですが、PHPをビルドするためにはかなり古いバージョンのautoconfが必要で、それをインストールするのが大変面倒そうであったため、挫折しました。

補足4

冒頭のサンプルコード

<?php array(1, 2, 3) ?>

はセミコロンがないことからエラーになりそうで、実はエラーになりません。

補足5

いろいろあって、いま著者の~/.vim/ftplugin/php.vimの該当部分以下のようになっています。

function! s:last_char()
  return matchstr(getline('.'), '.', col('.')-2)
endfunction

function! s:php_smart_bracket(last_char)
  if a:last_char == '['
    return "\<BS>("
  elseif a:last_char =~ '\w\|]'
    return '['
  else
    return 'array('
  endif
endfunction

inoremap <buffer><expr> [ <SID>php_smart_bracket(<SID>last_char())
inoremap <buffer><expr> ] smartchr#one_of(']', ')')

smartchrプラグインと組み合わせ、[を二回打鍵すると(になるようにしています。そもそもPHPでは[[は必ず出現しないため、わざわざ(を打鍵するよりもより容易な[[を用いるのが合理的と判断したためです。

ujihisa

Hack #154: タグジャンプをさらに活用する

タグジャンプをさらに活用する

Hack #43ではタグについての基本的な使用方法をまとめました。 本稿ではさらに踏み込んだタグジャンプの活用法をまとめます。

親ディレクトリにあるタグファイルを指定

もし自分が/project/a/src/というディレクトリにいた場合に、できれば/project/a/tagsや、 または全てのプロジェクト用のタグファイル(ライブラリの関数など)もタグジャンプに使いたいとします。

/project/a/src/ (現在のディレクトリ)
/project/a/tags (指定したいタグファイル)
/project/tags   (指定したいライブラリ関数のタグファイル)

その場合、.vimrcには以下のように書くことで可能になります。

if has('path_extra')
    set tags+=tags;
endif

こうすることで、もしタグファイルが存在するなら /project/a/tags/project/tagsにある関数も<C-]>で飛ぶことが可能になります。 また;+path_extra機能がサポートされていない場合では使えないため、 has('path_extra')で機能の有無をチェックしています。

階層数を指定

ただ;をつけただけではルートディレクトリまでさかのぼってしまいます。 そこで;の後に上限となる親ディレクトリを指定することができます。

if has('path_extra')
    set tags+=tags;/project/a
endif

こうすることで/project/aまでで検索を終了し、/project/tagsは見つかりません。

子ディレクトリにあるタグファイルを指定

前項では親ディレクトリのtagsを指定しましたが、 今度はある特定のディレクトリにあるタグファイルを 現在のディレクトリから指定したい場合はどうすればいいでしょう。

/project/a/src/          (現在のディレクトリ)
/project/a/src/libA/tags (指定したいタグファイル)
/project/a/src/libB/tags (指定したいタグファイル2)

その場合、以下を.vimrcに書けばいいでしょう。

if has('path_extra')
    set tags+=./*/tags;
endif

また、/project/a/src/libA/tagsなどの1階層下のディレクトリにあるタグファイルだけではなく /project/a/src/libA/src/tagsなどの何階層か下のタグファイルを指定するには以下のようにできます。

if has('path_extra')
    set tags+=./**/tags;
endif

階層数を指定

ただ**は30階層までの深さのディレクトリにマッチするということになっています。 なので場合によっては非常に重くなるかもしれません。 その場合は階層の深さの最大値を次のように指定することができます。 (この例では3階層下のディレクトリまでマッチするように設定しています)

if has('path_extra')
    set tags+=./**3/tags;
endif

親ディレクトリから**を使う

これは前項と前々項の合わせ技です。 現在のディレクトリが/project/a/srcの時に

set tags=**;

とすると、

/project/tags
/project/a/tags
/project/a/libA/src/tags
/project/a/libB/src/tags
/project/b/tags
/project/c/tags

これら全てが指定されることになります。 つまり**;とは、現在のディレクトリが/project/a/srcの時には

/project/a/src/**
/project/a/**
/project/**
/**

という場合に展開され、それぞれの場所から検索されます。 またこの指定は上記全ての場所から検索されるので重い処理となります。

その他色々

  1. この設定はHack #112: 場所ごとに設定を用意すると組み合わせると非常に相性がいいです。ぜひ合わせて使いましょう。また必ず:setでなく:setlocalを使いましょう。
  2. これらの指定方法は’path’, ‘cdpath’などでも使うことができます。
  3. 詳しくは:help file-searchingを当たってください。
tyru

Hack #149: コーディングスタイルを切り替える

プログラミングでは様々なコーディングスタイルがあり、Vimにはそれに沿った編集をするための様々なオプションがあります。
他人のソースコードを編集する時はそれらのオプションを切り替えられると便利です。

解決

このようなコマンド:CodingStyleを定義します。

let s:coding_styles = {}
let s:coding_styles['My style']      = 'set expandtab   tabstop=4 shiftwidth=4 softtabstop&'
let s:coding_styles['Short indent']  = 'set expandtab   tabstop=2 shiftwidth=2 softtabstop&'
let s:coding_styles['GNU']           = 'set expandtab   tabstop=8 shiftwidth=2 softtabstop=2'
let s:coding_styles['BSD']           = 'set noexpandtab tabstop=8 shiftwidth=4 softtabstop&'    " XXX
let s:coding_styles['Linux']         = 'set noexpandtab tabstop=8 shiftwidth=8 softtabstop&'

command!
\   -bar -nargs=1 -complete=customlist,s:coding_style_complete
\   CodingStyle
\   execute get(s:coding_styles, <f-args>, '')

function! s:coding_style_complete(...) "{{{
    return keys(s:coding_styles)
endfunction "}}}

するとこのようにコーディングスタイルを切り替えられます。(もちろん引数は補完が効きます)

CodingStyle Short indent
# または
CodingStyle My style

宣言的に記述できるので.vimrcが見やすくなります。
Hack #112: 場所ごとに設定を用意すると組み合わせて場所ごとのファイルに書くといいでしょう。

関連リンク

coding_style.vim yaifa.vim

tyru

Hack #148: Key mappingの設定を確認する

Vim を操作していると、たまにキー操作に対して意図しない挙動が発生することがあります。これは多くの場合、把握していない Key mapping が設定されているからです。 例えば、プラグインによって知らないうちに設定されていたり、自分で設定していて忘れてしまっていたり、自分で間違えて設定していた場合などです。 こういう時は Key mapping の設定を確認すると解決することが多いです。

:map コマンド

:map 系のコマンドは Key mapping を定義するコマンドですが、設定の確認にも使えます。引数なしで実行すると、コマンドに対応するモードで定義されている Key mapping の一覧が表示されます。例えば、

:imap

を実行すると Insert mode で定義されている Key mapping の一覧が表示されます。

一覧表示の見方

一覧表示は 1 行に 1 つの設定が書かれています。 最初の 3 文字は設定されているモードです。以下の文字のうち最大で 3 文字が表示されます。

文字モード
(空白)ノーマル、ビジュアル、セレクト、演算待ち状態モード
nノーマルモード
vビジュアルモード、セレクトモード
sセレクトモード
xビジュアルモード
o演算待ち状態モード
!挿入モード、コマンドラインモード
i挿入モード
lLang-Argモード
cコマンドラインモード

続いて、展開前の文字列と展開後の文字列が書かれています。展開後の文字列の前には記号が表示されている場合があり、それらは以下の意味になります。

文字意味
*再マップされません。つまり、noremap 系で定義された Key mapping です。
@バッファローカルなマップです。<buffer> 付きで定義された Key mapping です。
&スクリプトローカルなマップだけが再マップされます。<script> 付きで定義された Key mapping です。

特定のキーの設定を調べる

:map 系のコマンドに 1 つだけ引数を与えると、そのキーシーケンスで始まる Key mapping のみを表示します。

定義された場所を調べる

:verbose 付きで :map コマンドを実行すると、その設定を定義したファイルが確認できます。例えば以下のように表示されます。

:verbose map gj
   gj          * j
        Last set from ~/.vimrc

これにより、意図しない設定を行った元凶を調べることができます。

thinca

Home > Tags > lv2

Search
Feeds
Links
  • 公式
  • 勉強会
  • 情報
  • コミュニティ
  • プラグイン
  • vimrc
  • Meta
    Etc
    Creative Commons License
    This blog is licensed under a Creative Commons License.

    Return to page top