Home > Vim Hacks
Vim Hacks Archive
Hack #120: gVim でウィンドウの位置とサイズを記憶する
- 2010-01-28 (木)
- Vim Hacks
GUI アプリケーションではよく終了時にウィンドウの位置とサイズを記憶し、次回起動時に復元するものを見かけます。Vim でも設定次第で同様のことが可能です。
設定
.gvimrc に以下のように書きます。
let g:save_window_file = expand('~/.vimwinpos')
augroup SaveWindow
autocmd!
autocmd VimLeavePre * call s:save_window()
function! s:save_window()
let options = [
\ 'set columns=' . &columns,
\ 'set lines=' . &lines,
\ 'winpos ' . getwinposx() . ' ' . getwinposy(),
\ ]
call writefile(options, g:save_window_file)
endfunction
augroup END
if filereadable(g:save_window_file)
execute 'source' g:save_window_file
endif
解説
g:save_window_file
この変数で指定するファイルにウィンドウの位置やサイズを保存します。expand() は ~ を $HOME に展開するのに必要で、その必要がない場合はなくても問題ありません。
設定の書き出し
augroup SaveWindow 〜 augroup END で、Vim の終了時に発生するイベントを登録しています。
ここでは Vim の終了時に s:save_window() と言う関数を呼ぶようにしています。そしてこの関数のなかで、g:save_window_file にウィンドウの位置とサイズの情報を Vim スクリプトの形式で書き出しています。
設定の読み出し
最後の if でウィンドウ情報ファイルが存在するかをチェックし、存在した場合はそのファイルを :source で読み込みます。情報ファイルは Vim スクリプトとして書き出されているので、:source するだけで位置とサイズが復元されます。
- Comments: 0
- Trackbacks: 0
Hack #119: neocomplcache Hacks(2) オムニ補完
- 2010-01-24 (日)
- Vim Hacks
二回目の今回はオムニ補完です。AutoComplPopでも自動呼び出しが可能ですが、neocomplcacheでは、それに改良を加え、設定しやすくなっています。
オムニ補完とは
オムニ補完とは、Vim組み込みで用意されている補完とは違い、文脈を解析して行う補完です。関数を'omnifunc'に設定し、<C-x><C-o>のキーシーケンスを入力することで呼び出されます。標準でもいくつかの言語のオムニ補完関数が用意されていますが、ユーザーが自分で定義することができます。
inoremap <expr><C-x><C-o> &filetype == 'vim' ? "\<C-x><C-v><C-p>" : neocomplcache#manual_omni_complete()
私はこのようにキーマッピングを設定し、Vim組み込みのオムニ補完を置き換えています。
拡張機能
neocomplcacheのオムニ補完には次のような拡張機能があります。
自動補完の文脈定義
g:NeoComplCache_OmniPatterns[filetype]を設定すれば、呼び出し条件をカスタマイズしたり、呼び出しを無効化することができます。
多数の言語に対応
AutoComplPopでは標準でPerl/Ruby/html/CSS/Pythoのオムニ補完が可能です。neocomplcacheではPerl以外の確認できたすべての言語に対応しています。キーワードパターンに追加するだけなので、新たな言語に対応させることが容易です。
補完スキップ
g:NeoComplCache_EnableSkipCompletionが1ならば(デフォルト)、候補の取得に時間がかかりすぎる場合、補完をスキップすることができます。
ワイルドカード
ほかの補完と同様、ワイルドカードによる絞り込みに対応しています。
エラーを出さない
特定のオムニ補完では、変な場所で呼び出すとエラーを出したりすることがあります。neocomplcacheではエラーをcatchしているので、neocomplcache内部にバグがない限り、オムニ補完中にエラーになることはありません。
補完環境の厳密な判定
PythonやRubyのオムニ補完は:pythonや:rubyが正常に動作する環境でなければ動作しません。よって、内部で判定しています。
ファイル名補完やバッファ名補完との同時呼び出し
オムニ補完とほかの補完を同時に呼び出せないAutoComplPopとは違い、neocomplcacheのオムニ補完はほかの補完と統合されています。 よって、同時に候補を出すことができるので、さらに便利に使えます。 ただし、オムニ補完の開始パターンが先にマッチした場合、オムニ補完の候補のみが計算されて表示されます。 これはVim自体の仕様です。これを防ぐためには、一度補完のポップアップを閉じて、補完を再呼び出しするしかありません。
キーワードの収集
空文字列でオムニ補完を呼び出してキーワードを収集してキャッシュし、オムニ補完候補として利用することができます。
neocomplcacheからオムニ補完関数を呼び出すときの注意
neocomplcacheは大抵のオムニ補完関数に対応していますが、オムニ補完関数を内部で無理矢理呼んで変換するという動作を行っているので、呼び出す関数によっては補完がうまく働かないことがあります。現在、complete_add()関数を内部で呼んでいる場合には動作がおかしくなることがわかっています。これはオムニ補完関数側がcomplete_add()を呼ばないようにするしかありません。
他に、Rubyのオムニ補完は時々フリーズする現象があることが報告されています。
これはRubyのオムニ補完が外部インタフェースを内部で使用しているためだと思われます。
Vimの外部インタフェース機能は不安定なので、時々エラーをはいたりフリーズすることがあります。
無効にしたい場合は.vimrcで
if !exists('g:NeoComplCache_OmniPatterns')
let g:NeoComplCache_OmniPatterns = {}
endif
let g:NeoComplCache_OmniPatterns['ruby'] = ''
と設定すると、無効にできます。これでは不便なので、Rubyのオムニ補完を書き直してくれる人を現在募集中です。
Shougo- Comments: 0
- Trackbacks: 0
Hack #118: ホームディレクトリをラクに入力する
- 2010-01-20 (水)
- Vim Hacks
問題
Vimのコマンドラインでホームディレクトリを入力する機会は比較的多いものの、~/という文字列を見ただけで小指に疲労が走ってくるのは、ほとんどのVimユーザに共通するのではないでしょうか。
もしも入力しやすいキー、例えばバックスラッシュなどで一発で~/が入力できれば、どんなに素晴らしいことでしょうか。
解決
以下のコードを~/.vimrcに記述することで、コマンドラインモードでバックスラッシュで~/が入力できる上、~/が来て欲しくなさそうなところではそのままバックスラッシュが入力されます。
function! HomedirOrBackslash()
if getcmdtype() == ':' && (getcmdline() =~# '^e ' || getcmdline() =~? '^r\?!' || getcmdline() =~? '^cd ')
return '~/'
else
return '\'
endif
endfunction
cnoremap <expr> <Bslash> HomedirOrBackslash()
この設定を有効にしたVimで:e \と打鍵すると、ただちに:e ~/に展開されます。
また、:s/\と打鍵した場合は、:s/\とそのままになります。(:s/~/のように展開されません)
発展
本Hackはcho45さんの.zshrcへのハックへのアナロジーで考案されました。
残念ながら現在cho45さんの最新版の.zshrcにはそのコードは存在していないようですが、
少し古いところに残っています。
著者の手元の.zshrcから引用すると、以下のようなコードでした。
expand-to-home-or-insert () {
if [ "$LBUFFER" = "" -o "$LBUFFER[-1]" = " " ]; then
LBUFFER+="~/"
else
zle self-insert
fi
}
zle -N expand-to-home-or-insert
bindkey "\\" expand-to-home-or-insert
ujihisa
- Comments: 0
- Trackbacks: 0
Hack #117: 置換行為を繰り返す
- 2010-01-16 (土)
- Vim Hacks
問題
:substitute (:s)による置換処理は頻繁に使います。
バッファ全体を対象にする場合は:%s/foo/bar/gなどでできますし、
特定範囲のみを対象にする場合はVisual modeで選択しておいて
:s/foo/bar/gでできます。
では飛び飛びの場所で置換を行なう場合はどうでしょうか。
例えばソースコード中の特定の関数3つに対して置換を行なうとしましょう。
この場合は3箇所それぞれを対象として置換を実行することになりますが、
毎回
:s/foo/bar/g
のような長ったらしいコマンドを入力したくはありません。
<Up>/<Down>
でコマンドの入力履歴を辿って実行してもいいのですが、
これらのキーは概して遠い位置にあるため押下が面倒ですし、
押し易いキーバインドを設定することも面倒です。
どうにかして最小の手数で置換行為を繰り返せないでしょうか。
解決方法
以下のコマンドを実行します:
:s
通常、:sには検索パターンと置換文字列を指定しますが、
それらを省略した場合は最後に実行された
:sと同じ検索パターンと置換文字列で置換が行なわれます。
なお:sでは
:s/foo/bar/gc
などのフラグは無視されます。
フラグまで同一にする場合は:sの代わりに
:&&
を使います。
また1行だけ繰り返す場合には:sの代わりに
&
を使うこともできます。
参考資料
kana- Comments: 6
- Trackbacks: 0
Hack #116: 機能を割り当てるキーを探す際のヒント
- 2010-01-12 (火)
- Vim Hacks
Vim に新しくプラグインをインストールした際や、自分で便利な設定を書いた場合、それらの機能を素早く呼び出すために Key mapping を定義したいと思うでしょう。しかし、Vim では標準で多くの機能が各キーに割り当てられていて新しい機能を割り当てる場所が見つからないことがあります。本 hack ではそういった場合の手助けをします。
キーボードを眺める
キーボードを眺めて Vim における各キーの機能を思い出してください。思い出せないキーがあった場合、それはつまりあなたがそのキーの機能を使っていないということです。まずは :help でそのキーの機能を確認し、本当に必要ないと思えばそのキーには新しい便利な別の機能を割り当てられます。
プレフィックスキーを活用する
プレフィックスキーを使うことで、より多くの機能を割り当てることができます。ストローク数は 1 つ増えてしまいますが、キーボードのキーの数を考えるとこれは仕方がないでしょう。
以下にプレフィックスキーとして使えそうなキーを紹介します。
\
\ キーは標準の mapleader キーです。つまり、最初からプレフィックスキーとして使えるように空けられています。
<Space>
<Space> は非常に押し易い位置にあるにも関わらず、Normal mode ではカーソルを右に移動させるだけで、これは l と同じなので使われることは滅多にありません。これを使わない手はないでしょう。
m
m には標準でマークを付けると言う機能が割り当てられていますが、今は Visual mode もあるのでそれほど使われません。これをプレフィックスキーにしてしまうのも良いでしょう。
q
q はキーボードマクロの記録を開始するキーです。キーボードマクロは便利な機能なので潰すべきではありませんが、マクロとして記録できる場所は a から z まで 26 個もあります。そして、大抵はどこに記録したかなどは覚えていられないので、使い慣れた特定のキーを使うと思います。その場合、残りの使わないキーに対して機能を割り当てることができます。
また、再生用の @ キーも同様に使えるでしょう。
あまり使わないキーを退避させる
人によっては、たまにしか使わない、けれどたまには使うので使えないと困る、というキーがある場合があります。s f t などがその例です。 その場合、それらのキーをプレフィックス付きの場所に再マップすることでプレフィックスキーとして使えます。
nnoremap s <Nop>
nnoremap ss s
nnoremap sa func-a
nnoremap sb func-b
thinca
- Comments: 0
- Trackbacks: 0
Hack#115: Vimのバージョンや拡張機能をチェックする
- 2010-01-08 (金)
- Vim Hacks
自分でプラグインを書く場合、プラグインが動作しているVimのバージョンやVimで有効になっている機能を確認したい場合があります。ここでは、そんなときに役立つ関数について解説します。
Vimのバージョンをチェックする方法
Vimのバージョンをチェックするには、v:version変数をチェックすればよいです。百の位がVimのメジャーバージョン、十の位と一の位がマイナーバージョンを表します。例えばVim 7.2で:echo v:versionすると、702が表示されます。720ではありません。Vimがバージョン7以上であることをチェックするには次のようにします。
if v:version < 700
echoerr 'Does not work this version of Vim "' . v:version . '".'
finish
endif
ちなみに、パッチレベルはhas('patch100')などでチェックします。詳しくは、:help has-patchを参照してください。
有効になっている拡張機能をチェックする方法
自分のVimがどのような拡張機能を持っているかは、:versionを実行するのが早いですが、
プラグインがチェックする場合には使えません。スクリプトでチェックするには、has()を用います。
たとえば、Windowsかどうかをチェックするには、
if has('win32') || has('win64')
" Windowsの場合の処理
endif
です。GVimかどうかをチェックするには、has('gui_running')です。これはhas('gui')と間違えやすいので気をつけてください。has('gui')はGUI機能付きでコンパイルされているかどうかをチェックします。has('gui_running')でうまく条件を切り分ければ、.gvimrcを用いずにGVim用の設定を.vimrcだけで完結させることも可能です。
ただし、最初vimで起動して:guiでGUIになる場合は.vimrcのhas('gui_running')設定は読み込まれません。注意してください。(mattnさん情報)
使用上の注意
Vim6以下の場合はスクリプト機能が全然違うので、切り捨てても良いですが、Vim7以降の差異はそこまでありません。 本当にそのバージョンをチェックするべきなのかをよく考えましょう。 拡張機能も本当に必要なものだけを使うようにしましょう。
Shougo- Comments: 0
- Trackbacks: 0
Hack #114: Vimを再起動することなくロードパス$PATHを書き換える
- 2010-01-04 (月)
- Vim Hacks
Vimとそれ以外のソフトウェアを組み合わせて使うにあたって、:!と:r!が非常に重要な役割を果たしています。
このとき、:!lsとすることで/bin/lsが呼ばれるのは、$PATHに/binが含まれているためです。
$PATHはVimを起動したシェルから与えられます。シェルの$PATHを上書きしても、既に起動したVimの$PATHは変化しません。
Vimを起動したまま$PATHに新たなロードパスを追加するにはどうすればいいのでしょうか。
解決
let $PATH="/the/new/path:".$PATH
とします。
ただし、~は使えません。フルパスを指定する必要があります。
解説
let $PATH="/the/new/path:$PATH"
としたいところですが、$PATHは""の中で展開されません。また、
set path="/the/new/path,."
というのもありますが、これは:!用ではなく、gfなどのためです。詳しくは:h をご覧ください。'path'
謝辞
本Hackはnb1839さんにlingrで教えていただいた情報を元に執筆しています。
ujihisa- Comments: 0
- Trackbacks: 0
Hack #113: grex – 特定パターンにマッチする行をまとめて取り扱う
- 2009-12-31 (木)
- Vim Hacks
問題
Vimで大量のデータを取り扱う場合、 特にCSVなどの1レコード1行の形式のデータを取り扱うとき、 特定の条件にマッチする行を抽出するなど、 まとめて編集したいことがしばしばあります。
例えばバッファの内容が以下のようになっていたとします:
Name Creator First release Cost License Open source
Diakonos Pistos 2004 Free MIT Yes
GNU Emacs Richard Stallman 1984 Free GPL Yes
JED John E. Davis 1992 Free GPL Yes
Metapad Alexander Davidson 1999 Free GPL Yes
Notepad Microsoft 1985 - Proprietary No
RText Fifesoft 2003 Free GPL Yes
SciTE Neil Hodgson 1999 Free HPND Yes
Vim Bram Moolenaar 1991 Free GPL - compatible Yes
Yi Don Stewart 2005 Free GPL Yes
この中から
「19XX年にリリースされたエディタ(に対応する行)を削除する」
としましょう。
これは:globalを利用して行うことができます
(:g/\<19\d\d>/d)。
では
「19XX年にリリースされたエディタ(に対応する行)をヤンクする」
としたらどうでしょうか。
すぐに思いつくのは:g/\<19\d\d>/yですが、
これはマッチする行で毎回ヤンクを行うため、
レジスタに残るのは最後にマッチした行のテキストだけになります。
つまり、ヤンクしたいテキストは以下の通りなのですが、
GNU Emacs Richard Stallman 1984 Free GPL Yes
JED John E. Davis 1992 Free GPL Yes
Metapad Alexander Davidson 1999 Free GPL Yes
Notepad Microsoft 1985 - Proprietary No
SciTE Neil Hodgson 1999 Free HPND Yes
Vim Bram Moolenaar 1991 Free GPL - compatible Yes
実際にヤンクされるのは以下の1行だけになります。
Vim Bram Moolenaar 1991 Free GPL - compatible Yes
この観点で考えると、最初の「削除」についても同様のことが言えます。 つまり、削除されたテキストを別の箇所にペーストした場合、 ペーストされるのは最後にマッチした行のテキストだけになります。
上記のように、特定パターンにマッチする行をまとめて削除/ヤンクして ペーストするにはどうすればよいでしょうか。
解決方法
ベタな解決方法としては、
削除/ヤンクされるテキストをレジスタに上書きするのではなく、
レジスタに追加するようにします。
これには"A-"Zなどの大文字のレジスタを使います。
例えば:g/{pattern}/y Aとすると、
"aレジスタにマッチする各行のテキストが追記されるので、
"ap (操作直後であればpだけ)で
各行のテキストを一度にペーストできます。
ところが既に"aに何か別のテキストが入っていた場合、
それに対してテキストが追加されていくため、
実際には:let @a = ''などとして
操作前にレジスタの内容を空にする必要があります。
これは結構面倒です。
幸いなことに、上記のような操作パターンをまとめたコマンドを提供する grex というプラグインがありますので、これを使うと簡単に行うことができます。
例えば特定パターンにマッチする行をまとめて削除する場合、
/\<19\d\d>などとしてマッチするかどうかを確認した後、
:Gredで行うことができます。
ヤンクであれば:Greyで行うことができます。
なお、各コマンドは:g/{pattern}/[cmd]と
同様の形式では実行できません。
これは通常の操作では
検索パターンを含むコマンドを一度に入力して実行することはなく、
('incsearch'および'hlsearch'を有効にした上で)/{pattern}により
期待通りの検索パターンができたかどうかをインタラクティブに確認してから
実際のコマンドを入力・実行することがほとんどだからです。
参考資料
kana- Comments: 0
- Trackbacks: 0
Hack #112: 場所ごとに設定を用意する
- 2009-12-27 (日)
- Vim Hacks
Vim はファイルの種類によって独自の設定を自動的に読み込むことができます。しかしそれとは別に、ファイルの置いてある場所に応じて何かしら設定を行ないたい場合もあるでしょう。そのための方法を紹介します。
設定
以下の記述を vimrc ファイルに追記します。これは、ファイルを開いた際に、開いたファイルとその上位階層にある設定ファイルを探してそれを読み込むための設定です。 ここでは設定ファイルとして .vimrc.local と言うファイル名を使っていますが、ここは何でも構いません。ワイルドカードも使用可能です。
" Load settings for eacy location.
augroup vimrc-local
autocmd!
autocmd BufNewFile,BufReadPost * call s:vimrc_local(expand('<afile>:p:h'))
augroup END
function! s:vimrc_local(loc)
let files = findfile('.vimrc.local', escape(a:loc, ' ') . ';', -1)
for i in reverse(filter(files, 'filereadable(v:val)'))
source `=i`
endfor
endfunction
使用例
設定ファイルには、例えば以下のようなことを書いておきます。
lcd <sfile>:h
この例ではカレントディレクトリを設定ファイルがある階層に移動しています。これによってこの設定ファイルが置いてあるより下の階層のファイルのカレントディレクトリが統一できます。
他にもプロジェクト用にインデントの設定を変更したり、バッファローカルな Key mapping を定義したり、プラグインの設定用にバッファローカルな変数を定義したりと、応用範囲はかなり広いです。 また、この例の設定では複数の設定ファイルが見つかった場合ファイルシステムのルートに近いファイルから順に読み込むので、より深い階層で設定を上書きする、と言ったこともできます。
thinca- Comments: 0
- Trackbacks: 0
Hack #111: neocomplcache Hacks(1) ファイル名補完
- 2009-12-23 (水)
- Vim Hacks
neocomplcache Hacksでは、neocomplcacheの機能を詳細に解説していきます。一回目の今回はファイル名補完です。一見地味な補完ですが、うまく活用すると非常に便利です。
ファイル名補完とは
ファイル名補完とは、Vim組み込みで用意されているファイル名補完を置き換えるためにneocomplcache上で実装した補完です。Ver.3.0より機能が分離され、neocomplcacheの1プラグインとなっています。を解析して候補を出すため、組み込みのファイル名補完と同じように動作しますが、機能が大幅に拡張されています。特にファイル名を指定するときや、シェル拡張系のプラグインを使用するときに効果を発揮します。
inoremap <expr><C-x><<C-f> neocomplcache#manual_filename_complete()
私はこのようにキーマッピングを設定し、Vim組み込みのファイル名補完を置き換えています。
拡張機能
neocomplcacheのファイル名補完には次のような拡張機能があります。
ワイルドカードに対応
*.txtのような、ワイルドカード文字が補完に使えます。 実行ファイル、読み取り専用ファイル、ディレクトリの表示 表示をわかりやすくするため、ファイルの種類を判別し、実行ファイルには*を、読み取り専用ファイルには[-]を、ディレクトリには/をそれぞれ付加します。 Windowsでは$PATHEXTを参照するので、より正確な判別が可能です。
短縮ファイル名補完
/u/s/lのようにディレクトリの先頭名だけ入力することで、/u*/s*/lのように解釈されます。素早く補完したいときに便利ですが、候補が多いと重くなります。
補完スキップ
g:NeoComplCache_EnableSkipCompletionが1ならば(デフォルト)、ファイル名の取得に時間がかかりすぎる場合、補完をスキップすることができます。
Cygwin対応
Vim組み込みのファイル名補完では/cygdrive/の入力で補完が重くなってしまいますが、neocomplcacheのファイル名補完では対策されています。
…->../..変換
…を../..に変換して解釈することができます。上のディレクトリを参照するときに便利です。
_, -, .による区切り補完
_, -, .を区切り文字として曖昧補完ができます。たとえば、h_.txtはh_.txtと同じ意味です。
環境変数を展開しない
組み込みのファイル名補完の場合、環境変数が勝手に展開されてしまうので、逆に邪魔になってしまうことが多々あります。neocomplcacheのファイル名補完は環境変数とマッチする部分はそのままにするので、便利に使うことができます。
zshとの比較
neocomplcacheのファイル名補完は自動的に候補が表示できるのが一番の魅力で、特にvimshellとの連携はすばらしいです。zshでも設定すれば自動補完ができないことはないのですが、誤爆の可能性も高く、おすすめできません。自動でファイル名補完ができることに慣れてしまうと、いちいち<TAB>を連打しなくてはいけないシェルの補完が煩わしく感じることでしょう。
vimshellとの併用
neocomplcacheのファイル名補完は元々vimshell上で利用するために作られました。vimshellとはVim上でシェルを実装したプラグインです。neocomplcacheとは独立していますが、neocomplcacheがインストールされている場合、補完時にneocomplcacheの機能を使用します。vimshellはneocomplcacheと比較しても複雑なプラグインなので、機会があれば詳しく解説したいと思います。
Shougo- Comments: 0
- Trackbacks: 0
ホーム > Vim Hacks
- Search
- Feeds
- Links

