最新版のjvgrepをコンパイルするにはgo言語とMercurialが必要だった
# go get github.com/mattn/jvgrep
というコマンドを実行するにはThe Go Programming Languageが必要だった。
しかも$GOROOT
$GOPATH
という意味不明な環境変数を設定しなければいけなかった。
さらに、それに使われているmahonia - Mahonia—a character-set conversion library for Go - Google Project Hostingを得るためには水銀の元素記号hgでおなじみ、もう一つのバージョン管理システムであるJapaneseMercurial - Mercurialが必要だった。
インストーラでインストールするのが嫌だったのでMercurial Cmd Portable 1.5.1 Development test 1 | PortableApps.com - Portable software for USB, portable and cloud drivesを適当なディレクトリに展開した上で、Mercurialにパスを通すことで対応した。
悲しいお知らせ
ここまで苦労して導入しても、Vimの'encoding'オプションを'utf-8'にしている場合、Windowsではなすすべもなく使えないらしい。
set grepprg=jvgrepにして:grepしたいのですが、日本語が通りません。
Vim側がutf-8で吐いた文字をコマンドプロンプトがcp932として呼んでしまうからですが、解消する方法を知りませんか?
http://lingr.com/room/vim/archives/2013/12/05#message-17739621
絶望
つまり現状ではコマンドプロンプトを使うのをやめるか、qfixgrepを使うしか解決策がないわけですね。
http://lingr.com/room/vim/archives/2013/12/05#message-17740433
qfixgrepは余計なことを色々しているから好きにはなれないのですが。
光明
qfixgrepの中身を見てみたが、つまり最悪、外部コマンドに渡すときにiconv()でエンコードを変換してやれば何とか出来るっぽい。
http://lingr.com/room/vim/archives/2013/12/05#message-17740591
おし。
http://lingr.com/room/vim/archives/2013/12/05#message-17740802
exe 'grep '. iconv('ファイル', 'utf-8', 'cp932'). ' %'だと正常機能した。
つまり渡すときエンコードしてくれるラッパーコマンドを定義してそれを使えば当面は解決できる問題になった。
コマンドラインで :b を実行するときにバッファリストを表示する
Vim - hjklマスターに薦める意外と便利な機能 - Qiita [キータ]
の
バッファを選択する際に、同時にリストを表示する
nnoremap B :ls<CR>:b
という設定を見て閃いた。
cnoreabb <expr>b getcmdtype()==':' && getcmdline()=='b' ? 'ls<CR>:b' : 'b'
こうすればコマンドラインで:b
を打ってから<Space>
キーを打つと勝手に:ls
が表示されるようになる。
nebula.vimを使ってneobundle#tap()をより高速に書く
Shougo/neobundle.vim に ももんが流NeoBundle管理術 | かなりすごいブログ から機能が取り込まれneobundle#tap()
neobundle#untap()
が使えるようになりました。
これを利用するとだいたいこんな感じで非常にすっきりとプラグインの設定が書けます。
ここでは LeafCage/nebula.vim を使って、より楽に高速にneobundle#tap()
を記述する方法を紹介します。
vimrcのNeoBundle 'repository/pluginname'
のある行で:NebulaYankTap
を呼び出すと、
if neobundle#tap('pluginname') endif
がレジスタにセットされます。
:NebulaYankTap!
のように、!
付きで呼ぶと
if neobundle#tap('pluginname') "{{{ endif "}}}
のようにfoldingmarker付きでヤンクされます。
これを記述したい場所にカーソルを持ってきて貼り付ければよいのです。
中身のneobundle#config()
を書くときにはShougo/neosnippet.vimなどで
snippet neobundleconfig alias nbc call neobundle#config(${1})
みたいなsnippetを定義しておいて、オプションを:NebulaYankOptions
で生成すると捗ります。
コマンドラインからシームレスにover.vimの全体置き換えを使う
私は今まで:s
について以下の設定をしていた。
cnoreabb <expr>s getcmdtype()==':' && getcmdline()=~'^s' ? '%s/<C-r>=Eat_whitespace(''\s\\|;\\|:'')<CR>' : 's' function! Eat_whitespace(pat) "{{{ let c = nr2char(getchar(0)) if c=~a:pat return '' elseif c=~'\r' return '' end return c endfunction "}}}
こうしておくと、コマンドラインでs
と打ってから<Space>キーで %s/
という具合に展開されていたので、全体置き換えをするときに打ちにくい %
を打たなくて済むという利点があった。
そんな折、osyo-manga/vim-over がリリースされた。
結果をプレビューする機能はCoolだがぶっちゃけそんなに要らなかったが、置き換え実行後にカーソルが動くことがないというのに魅力を感じたので、上記の操作を over.vim で置き換えることにした。
以下のように設定することでコマンドラインで s
を打ってから<Space>を打つと、そのままover.vimで %s/
が入力された状態になる。
cnoreabb <silent><expr>s getcmdtype()==':' && getcmdline()=~'^s' ? 'OverCommandLine<CR><C-u>%s/<C-r>=get([], getchar(0), '')<CR>' : 's'
Vimのabbreviate(短縮入力)機能によって、行頭でのs
をOverCommandLine<CR><C-u>%s/
に置き換えているわけである。
その際、トリガーに使った<Space>は不要なのでgetchar(0)に食わせている。
<C-r>=get([], getchar(0), '')<CR>
の部分はトリガーに使った文字の処分である。
別にトリガーは短縮入力を展開できる文字なら何でも良いので<Space>でなくて<CR>でも良い。
'nobuflisted' なバッファの作り方
Vim Advent Calendar 2012 356日目の記事です。
バッファをバッファリストに登録したくないときがあります。
バッファリストに登録されていないバッファは:ls
では表示されず、:bnext
:bprevious
でのバッファ切換の対象になりません。
また、Vim終了時に次回起動時のための情報を書き込むviminfo
ファイルのバッファリスト保存・復元から除外されます。つまりVim終了時にはそのバッファは破棄され次回起動に持ち越しません。
このオプションは通常、その場限りの情報を表示するだけで、書き込む予定のない、使い捨てのバッファに設定します。
しかし、せっかく'buflisted'
オプションをオフに設定しても、バッファの内容を変更すると勝手に'buflisted'
がオンに設定し直されてしまいます。
正しくは「バッファの編集を始めると」オンになるのでした。:edit
や:split
:vsplit
:new
などで切り替えるとオンにされるみたいです。つまり:edit
などを使わず:buffer
でバッファを切り替えるのなら:setlocal nobuflisted
を設定するだけでよいです。
ここではいかにして、何らかの形で意図せず'buflisted'
オンになっても'buflisted'
をオフに保つようにするバッファを作るのかを解説します。また、特別なバッファに設定するべき他のオプションも併せて説明します。
変更の予定のないバッファの場合
バッファを変更する予定がなければ、ただ単に'nobuflisted'
オプションを設定すればいいです。
その際、ユーザにバッファの内容を変更を禁止させるように'nomodifiable'
オプション、読み込み専用だということをユーザに示すために'readonly'
オプションもセットしましょう。
edit examplebuf setlocal nobuflisted nomodifiable readonly
※これらはバッファにローカルなオプションなので:setlocal
ではなく通常の:set
で設定しても問題ありません。
:edit
に+cmd
オプションを与えればこのコマンドを1行で表せます。
edit +setlocal\ nobuflisted\ nomodifiable\ readonly examplebuf
変更の予定があるバッファの場合
編集が禁止されたバッファでスクリプトがバッファの内容を変更するのなら、そのときに一時的にこれらのオプションを変更し、内容変更後に元に戻せばいいでしょう。
setlocal buflisted modifiable noreadonly call setline(1, '==example==') setlocal nobuflisted nomodifiable readonly
ユーザが自由に編集できるバッファをバッファリストに登録させたくない場合は、そのバッファを抜けるときに'nobuflisted'
に設定しなおすバッファローカルなautocmdをそのバッファに設定しておきます。
また、たまたまそのバッファにいるときにVimを終了させようとしたときにもバッファリストから除外するようにVimLeavePre
イベントのautocmdも設定します。
edit examplebuf augroup example_local autocmd! autocmd BufLeave <buffer> setlocal nobuflisted autocmd VimLeavePre <buffer> setlocal nobuflisted augroup END
需要があるか分かりませんが、現在Vimではbuflisted
にしておきたいが、Vim終了時にはnobuflisted
にして次回起動時のバッファに残させないときの設定です。この場合そのバッファのバッファ番号を何らかの形で記憶しておき、autocmd VimLeavePre \*
でそれらのバッファにnobuflisted
オプションを設定します。
augroup example_local autocmd! autocmd VimLeavePre * call <SID>make_bufs_nobuflisted() augroup END let s:bufnrs = [] function! s:make_bufs_nobuflisted() for bufnr in s:bufnrs if buflisted(bufnr) call setbufvar(bufnr, "&bl", 0) endif endfor endfunction
edit examplebuf call add(s:bufnrs, bufnr('%'))
特別なバッファに設定するべき他のオプション
readonly, nomodifiable
説明済み
buftype
ファイルと関連がなく、書き込まれる予定のない仮想的なバッファにはset buftype=nofile
を設定します。
buftype=nofile
を設定すると:write
が禁止されます。しかし、バッファの編集変更自体は出来るので、それを禁止させたければ前述のnomodifiable
も設定しましょう。
bufhidden
バッファの使い捨てという正確を強めたいときに利用します。
バッファがウィンドウに表示されなくなったときの挙動を指定するオプションですが、そのバッファを閉じたらバッファの内容を破棄させたいのならbufhidden=unload
、削除や完全削除をしたいのならbufhidden=delete
(←これはまだ:b
でバッファ指定するなどしたらアクセスできる)やbufhidden=wipe
(←完全に削除される)を使います。
例えばkien/ctrlp.vimでbufhidden=unload
が利用されています。ctrlp.vimの作るバッファは刹那的な性格が強いですし、無駄なメモリも解放されるからでしょう。
活用例
例えばShougo/vimfiler.vimの作るバッファをバッファリストに残したくない時には.vimrc
に次の設定を書きます。
autocmd FileType vimfiler setlocal nobuflisted \ | autocmd BufLeave <buffer> setlocal nobuflisted \ | autocmd VimLeavePre <buffer> setlocal nobuflisted
これでバッファを閉じたときにはバッファリストのサイクルから外れますし、次回起動時にvimfilerのバッファが残っているということもありません。
Vimスクリプトのファイル先頭にscriptencodingを書く意味
LeafCage
ファイルの先頭でscriptencoding を書くのはどういった利点があるのでしょうか?今までscriptencodingを書いてこなかったのですが、書いておくとVimがencodingを調べることがなくなって読み込み速度がアップするのでしょうか?
thinca
マルチバイト文字がスクリプト内に含まれている場合は、scriptencoding がないと、'encoding' とファイルのエンコーディングが異なる場合に文字化けします
LeafCage
echoで日本語を表示させるときならscriptencodingは必須と言うことでしょうか?
コメントに日本語が含まれている場合には大丈夫ですか
thinca
http://lingr.com/room/vim/archives/2013/11/07#message-17304879
> echoで日本語を表示させるときならscriptencodingは必須と言うことでしょうか?
そうなります
コメントでも、改行文字が食われるような化け方をする可能性を考えると、書いておいた方がいいです
set encodingよりも後に書かなければいけないらしい。
thinca
scriptencoding は set encoding よりも後にやる必要があり、しかしマルチバイト文字が出てくる前に scriptencoding は実行しないと意味がない
http://lingr.com/room/vim/archives/2013/11/23#message-17465700
README.mdをVimのヘルプファイルから生成する
この記事はVim Advent Calendar 2012の341日目の記事です。
前回(84日前)Vimプラグインのスクリプトファイルからヘルプファイルを生成するというのをやりました。
しかしGitHubではREADME.md
ファイルがリポジトリの窓口であり、説明であり、これによってそのプラグインの概要を知り、それを導入するかどうかが判断されます。
README.md
を置いていないとプラグインの詳細を知るためには、リポジトリトップから2クリックもかかるdoc/xxx.txt
を見に行かなければいけませんし、リポジトリトップにはGitHubがREADME.md
を置けと勧めてきます。
つまり我々はREADME.md
を書くことを暗に強いられているのです。
しかし、すでにhelpに概要含め色々書いているのにさらに別の場所で二重に概要を書かなければいけないなんて苦痛です。
なぜhelpに書いたことを改めて書かなければいけないのでしょうか。
そこでLeafCage/vimhelpgeneratorに:HelpIntoMarkdown
というコマンドを追加しました。*1
ヘルプファイル内でREADME.md
に含めたいところをビジュアル行選択(“概要”や“使い方”などを選択すると良いでしょう)して、
:HelpIntoMarkdown
を実行すると、
そのヘルプファイルの上にあるREADME.md
ファイルが開かれます。*2
ここでP
すると、先ほど行選択されたテキストがmarkdown形式に変換されてput
されます。(README.md
を初めて作成するときにはプラグイン名と説明もhelpファイルの第1行目から生成されます。)
手直しした後、:write
しましょう。
:HelpIntoMarkdown
はアンダースコア(_)のエスケープには対応していません*3。自力で対応させて下さい。
もしもヘルプファイルを改修したときには改修した箇所をビジュアル行選択して:HelpIntoMarkdown
して下さい。その部分の変換結果がレジスタにセットされるのでREADME.md
にて貼り付けて手直しして下さい。
これでヘルプファイルとREADME.md
を管理する手間を大幅に減らすことが出来ました。
:VimHelpGeneratorVirtualでヘルプを仮想バッファに出力する
vimhelpgeneratorには、:VimHelpGeneratorVirtual
というコマンドも加わっています。
:VimHelpGenerator
が生成したバッファをそのまま書き込むのに対し、:VimHelpGeneratorVirtual
は仮想バッファに出力します。
これにより、vimhelpgenerator
の、ヘルプファイルを初めて作るときにしか使えなかったという欠点を解消しました。
プラグインに機能を追加するなどしてヘルプの改修の必要性が生じたとき、:VimHelpGeneratorVirtual
を実行して、出力された仮想バッファ内で必要な部分だけを、既存のヘルプファイルにコピーペースト(Vim風に言うとヤンクプット)すれば良いのです。
単純にVimHelpGenerator
の出力を確認したいときにも利用できます。
:VimHelpGenerator
を実行したときにすでにヘルプファイルが存在している場合もこのモードで出力されます。