Vimのカバレッジを見る
この記事はVim Advent Calendar 2017の2日目の記事です。
Vimのカバレッジはcoveralls.ioやcodecov.io上で見ることができますが、手元で見たくなることもあると思います。
そんな時はMakefileに書いてある通り、次のようにしてカバレッジを計測し、生成されたhtmlから見ることができます。
# Vimのリポジトリ直下に移動 # 各種フラグに--coverageをつけてビルド、他はお好みで CFLAGS=--coverage LDFLAGS=--coverage ./configure --with-features=huge && make cd ./src # まずはゼロカバレッジの初期データを作る lcov -c -i -b . -d objects -o objects/coverage_base.info # テストを走らせてカバレッジ情報を作る make test lcov -c -b . -d objects/ -o objects/coverage_test.info # 初期データとテストのカバレッジ情報を結合する lcov -a objects/coverage_base.info -a objects/coverage_test.info -o objects/coverage_total.info # 結果をobjects/index.htmlとして生成する genhtml objects/coverage_total.info -o objects
ビルド時に--coverage
をつけることでgcovが有効になり、実行された行が記録されるようになります。
lcov(と付属のgenhtml)はそのフロントエンドツールです。
さて、実行された行が記録されるということは、Vimで特定の操作をした際にどの関数が呼ばれたのか調べることができる、ということです。
しかし、gcovはプログラムの終了直前に保存処理を行うため、目的の操作だけの結果を知るには
の順で操作をしつつ、1と3は除外する必要があります。
幸いgenhtmlには-b(--baseline-file)
オプションがあるので次のようにすれば実現できます。
# 上と同じ lcov -c -i -b . -d objects -o objects/coverage_base.info # 起動と終了のカバレッジを取得 VIMRUNTIME=../runtime ./vim --clean -c 'q' lcov -c -b . -d objects/ -o objects/coverage_quit.info lcov -a objects/coverage_base.info -a objects/coverage_quit.info -o objects/coverage_baseline.info # カバレッジをリセット lcov -z -d objects/ # 起動と:smileと終了のカバレッジを取得 VIMRUNTIME=../runtime ./vim --clean -c 'smile | q' lcov -c -b . -d objects/ -o objects/coverage_smile.info lcov -a objects/coverage_base.info -a objects/coverage_smile.info -o objects/coverage_result.info # 生成されるのはcoverage_result.infoからcoverage_baseline.info分のカウントを減らした結果 genhtml -b objects/coverage_baseline.info objects/coverage_result.info -o objects
というわけで:smile
*1にはsyntax.c
以下のソースが使われていることがわかりました。
処理を正確に追うにはデバッガを使うのが確実だとは思いますが、ソースの構造がある程度わかっていないと難しかったりもします。
なので、さらっと概要と知りたい時やソースコードリーディングのお供にでも是非カバレッジを活用してみてください。
:smile oooo$$$$$$$$$$$$oooo oo$$$$$$$$$$$$$$$$$$$$$$$$o oo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o o$ $$ o$ o $ oo o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o $$ $$ $$o$ oo $ $ "$ o$$$$$$$$$ $$$$$$$$$$$$$ $$$$$$$$$o $$$o$$o$ "$$$$$$o$ o$$$$$$$$$ $$$$$$$$$$$ $$$$$$$$$$o $$$$$$$$ $$$$$$$ $$$$$$$$$$$ $$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$ $$$$$$$$$$$$$$ """$$$ "$$$""""$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ "$$$ $$$ o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ "$$$o o$$" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$o $$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" "$$$$$$ooooo$$$$o o$$$oooo$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ o$$$$$$$$$$$$$$$$$ $$$$$$$$"$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$"""""""" """" $$$$ "$$$$$$$$$$$$$$$$$$$$$$$$$$$$" o$$$ "$$$o """$$$$$$$$$$$$$$$$$$"$$" $$$ $$$o "$$""$$$$$$"""" o$$$ $$$$o o$$$" "$$$$o o$$$$$$o"$$$$o o$$$$ "$$$$$oo ""$$$$o$$$$$o o$$$$"" ""$$$$$oooo "$$$o$$$$$$$$$""" ""$$$$$$$oo $$$$$$$$$$ """"$$$$$$$$$$$ $$$$$$$$$$$$ $$$$$$$$$$" "$$$"""" Press ENTER or type command to continue
*1:v8.0.1362
VimConf 2017でコントリビューターになる話をしてきた
VimConf 2017 - An international Vim Conferenceで
という発表をしてきました。
最初は25分も話すことなんてあるかな?なんて思ってたら意外と良い感じの時間になりました。
少し足りなかったところを少し補足しておくと、
gitコマンド
- v8.0.0512の調査で使ったgit bisect
# <bad> <good>の順番で指定する git bisect start v8.0.0104 v8.0.0000
あとは都度makeし、手動で補完させてgoodかbadを判定していきました。
※コマンドからの補完だと再現しなかったため
活動時間帯について
- 不具合の発見〜1次調査・応急処置
- 職場
- 2次調査〜パッチ作成
- 自宅・Meguro.vim
patchを送った後について
- 質問とかツッコミは無かったの?
- 全く無かった
- パッチが小さかったからかも
- もしくはタイミングが良かったからとか
場合によってはなかなか取り込まれないこともあったりするようです。
MacVimの不具合って?
マルチバイト文字が潰れて表示されてしまうという問題を修正しました。 github.com
コントリビュートする内容について
- 新機能を追加したいんだけど
- 色々大変だと思いますが、新機能を作れるくらいのパッションがあれば大丈夫だと思います!
- ドキュメントや軽微な(typo・インデント)修正でも良いの?
- OKです!
ちなみにコントリビュートに対するスタンスは最近聴いた
にすごく共感するものがあります。
vim-jpについて
「vim-jpに気軽に相談してみましょう」なんて勝手に言ってしまって良いのかな?
とか思っていたんですが、なんと本日vim-jpのメンバー入りをしました。
もし何かあれば出来る範囲でサポートしていきたいです!
ということを本番でも話せれば良かったんですが、アドリブ力が無く。。。
という感じです。
スライドの英訳を助けてくれた ujihisa さん、
発表の翻訳をしてくださった sandkatt さん、
そしてスタッフのみなさま、
ありがとうございました!お疲れ様でした。
Meguro.vim #4でプラグインを作った
Meguro.vim #4で自分用の:VimFilerSimple
に代わるプラグインを作りました。
vimfilerは機能が豊富でそこまで不満があったわけではないのですが、
- 常に全ての機能を必要としているわけではない
- unite.vimに依存している
ので、一番使う頻度の高い ファイルをツリー形式で表示する だけのプラグインが欲しかったからです。
実装としてはtreeコマンドの結果を
- dirvish.vimのように
conceal
で表示し、 - ディレクトリの階層を
folding
で表す
というものです。
マッピングは一切用意していないため、ファイルを開く時には標準機能のgf
などを使うことになります。
また、プラグインの起動もTree
コマンドしか提供していないため、使い方に合わせたマッピングをvimrcに追加していくというデザインにしています。
" Example: " 垂直分割してツリーを表示し、ウィンドウの幅を32にする nnoremap <silent> <Leader>vt \ :<C-u>execute 'vertical '. v:count .'Tree' \ <Bar> vertical resize 32 \ <CR> " ツリーを閉じずにファイルを開く nnoremap <silent> <C-w>e \ :<C-u>let @a = fnameescape(expand('<cfile>')) \ <Bar> wincmd w \ <Bar> execute 'edit ' . @a \ <CR>
Vimでファイルを開く方法(基本編)
この記事はVim Advent Calendar 2016の4日目の記事です。
Vimでファイルを開くのに
のプラグインを使っている人はたくさんいると思います。
これらのプラグインは大変便利なインターフェースを提供してくれているのですが、
依存しすぎてしまうと標準機能でファイルを開く方法を忘れてしまうかもしれません。
...さすがにそんなVimmerはいないと思いますが、ファイルを開く
- コマンド
- キーマッピング
をおさらいしてみましょう。
コマンドで開く
以下のコマンド*1の引数としてファイル名を指定します。
コマンド | 説明 |
---|---|
:e[dit] | 現在のバッファでファイルを開く |
:sp[lit] | 水平分割してファイルを開く |
:vs[plit] | 垂直分割してファイルを開く |
:tabe[dit] | 新しいタブページを作成してファイルを開く |
このとき、
<Tab>
(または<CTRL-I>
)でファイル名の補完- 動作は
wildmode
(:help wildmode)で変更可能
- 動作は
<CTRL-D>
で入力にマッチするファイル名の一覧表示
をすることができます。
また、対象のファイル名を探すのに
*
や**
などのワイルドカード(:help wildcard):p
や:h
などのファイル名修飾子(:help filename-modifiers)
を用いることもできます。
例
" <CTRL-D>で一覧を表示し、 :e */index<CTRL-D> public/index.html src/index.css src/index.js " <Tab>を押すと最初の候補が選択される :e */index<Tab> :e public/index.html " もう1度<Tab>を押すと次の候補が選択される :e public/index.html<Tab> :e src/index.css
- /usr/lib/golang/src/配下のreader.goを探す
:e /usr/lib/golang/src/**/reader.go<CTRL-D> /usr/lib/golang/src/archive/tar/reader.go /usr/lib/golang/src/archive/zip/reader.go /usr/lib/golang/src/bytes/reader.go /usr/lib/golang/src/compress/lzw/reader.go /usr/lib/golang/src/compress/zlib/reader.go /usr/lib/golang/src/debug/elf/reader.go /usr/lib/golang/src/encoding/csv/reader.go /usr/lib/golang/src/go/doc/reader.go /usr/lib/golang/src/image/gif/reader.go /usr/lib/golang/src/image/jpeg/reader.go /usr/lib/golang/src/image/png/reader.go /usr/lib/golang/src/mime/quotedprintable/reader.go /usr/lib/golang/src/net/textproto/reader.go /usr/lib/golang/src/strings/reader.go /usr/lib/golang/src/testing/iotest/reader.go
" カレントディレクトリが/rootの状態で :pwd /root " swagger-codegen/samples/server/petstore/go-api-server/main.goを開いている時 :echo expand('%:p') /root/swagger-codegen/samples/server/petstore/go-api-server/main.go " 最初の:hで"/main.go"、次の:hで"/go-api-server"が除去される :e %:h:h/**/pom.xml<CTRL-D> swagger-codegen/samples/server/petstore/java-inflector/pom.xml swagger-codegen/samples/server/petstore/java-msf4j/pom.xml swagger-codegen/samples/server/petstore/jaxrs/jersey1/pom.xml swagger-codegen/samples/server/petstore/jaxrs/jersey2/pom.xml swagger-codegen/samples/server/petstore/jaxrs-cxf/pom.xml swagger-codegen/samples/server/petstore/jaxrs-cxf-cdi/pom.xml swagger-codegen/samples/server/petstore/jaxrs-resteasy/default/pom.xml swagger-codegen/samples/server/petstore/jaxrs-resteasy/joda/pom.xml swagger-codegen/samples/server/petstore/jaxrs-spec/pom.xml swagger-codegen/samples/server/petstore/scalatra/pom.xml swagger-codegen/samples/server/petstore/spring-mvc/pom.xml swagger-codegen/samples/server/petstore/spring-mvc-j8-async/pom.xml swagger-codegen/samples/server/petstore/springboot/pom.xml swagger-codegen/samples/server/petstore/undertow/pom.xml
キーマッピングで開く
ファイル名がある場所にカーソルを移動し、以下のキー*2を入力します。
キー | 説明 |
---|---|
gf |
現在のバッファでファイルを開く |
CTRL-W f |
水平分割してファイルを開く |
CTRL-W CTRL-F |
|
CTRL-W gf |
新しいタブページを作成してファイルを開く |
現在開いているバッファにファイル名があれば良いですが、無い場合は:r!
と
ls
、find
などの外部コマンドを用いてファイル一覧を作成してしまいましょう。
" 新しいバッファにカレントディレクトリのファイル一覧を作成 :new | r! ls
なお、:new
でバッファを作成した場合、デフォルトではgf
でファイルを開く際にエラー(E37
)になってしまいます。
その場合、
set hidden
... ウィンドウ内に表示されなくなる際にバッファを隠す- 全てのバッファが対象
- Vim終了時に未保存バッファが残っているとエラーになる
set bufhidden=hide
... ウィンドウ内に表示されなくなる際にバッファを隠す- カレントバッファのみが対象
- Vim終了時に当該バッファが未保存だとエラーになる
set buftype=nofile
... バッファを書き込まれる予定のないバッファにする- カレントバッファのみが対象
- Vim終了時に当該バッファが未保存でもエラーにならない
などの設定でバッファを保存せずに切り替えられるようにしてあげる必要があります。
また、ファイル一覧に大量のファイルが表示されてしまった場合
/{pattern}
で検索したり、:g/{pattern}/d
でフィルタしてあげると
目的のファイルが探しやすくなります。
例
- カレントディレクトリ配下のファイル一覧を作成
:new | r! find . -type f " Windowsの場合 :new | r! dir . /b /s /a-d
- 現在開いているファイルがあるディレクトリ配下のファイル一覧を作成
" findの引数は実行前に<Tab>で展開しておく :new | r! find %:p:h<Tab> -type f " Windowsの場合 :new | r! dir %:p:h<Tab> /b /s /a-d
- ファイル一覧を作成するユーザコマンドの定義
上記のコマンドを毎回入力するのが面倒な場合、.vimrc
に以下のようなコマンドを追加しておくと便利です。
" 新しいscratchバッファ(:help special-buffers 参照)を作成する command! -bar NewScratch new | setlocal buftype=nofile bufhidden=hide noswapfile " :NewScratchで作成したバッファにfindコマンドの出力内容を挿入する " FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます) command! -nargs=1 -complete=dir Files NewScratch | r! find "<args>" -type f " Windowsの場合 " FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます) " command! -nargs=1 -complete=dir Files NewScratch | r! dir "<args>" /b /a-d /s " %:p:hを引数として:Filesを実行する(<args>には%:p:hが展開された状態で渡される) command! FilesBuffer Files %:p:h " .を引数として:Filesを実行する command! FilesCurrent Files .
まとめ
Vimの標準の機能でファイルを開く方法を紹介しました。
単にファイルを開くだけなら十分ですが、インタラクティブ性や非同期性が必要な場面になると物足りないところがあるかもしれません。
そういった時には組み込み関数と合わせて使ってみたり、プラグインを活用すると良いと思います。
VimConf 2016 に行ってきた
VimConf 2016に行ってきた。
発表メモ
Introduction to Vim 8.0 by Ken Takata
- 最近Vimに入った機能の中で
job
,timer
,packages
は使ったけど *1 *2Partial
,lambda
,closure
はまだ触っていないので試してみたい - 日本人VimmerがVim本体に多くのパッチを送っているのは知っていたけど改めて数字で見てみると予想以上にすごかった
- Vimのテストが充実してきたおかげで新機能の使用例としても参考にできてありがたい
Vim as the MAIN text editor by bird_nitryn
Denite.nvim ~The next generation of unite~ by Shougo
- unite.vimを使っていてパフォーマンス的な不満は特になかったけどデモに触発されてMacVimでDenite.nvimを試してみたらすごく速かった
- Decoupled UIはちょっと気になるのでそのうち試してみたい
Go、C、Pythonのためのdeoplete.nvimのソースの紹介と、Neovim専用にpure Goでvim-goをスクラッチした話 by zchee
- neovimに全然興味なかったけど発表を聞いてとりあえずインストールしてみることにした
- nvim-goの作りが気になるのでソースを見てみる
エディタの壁を越えるGoの開発ツールの文化と作成法 by tenntenn
- 自分の近くでは「Goやったことある方」でほとんどの人が手を挙げていた
- gofmt(ごーふむと)、GOOS(ぐーす)、GOARCH(ごーち)
- ファイルを生成するツール *3 は作ったから次はファイルを書き換えるツールと思っていたのでgorenameのところがとても参考になった
vim-mode-plus for Atom editor by t9md
- vim-mode-plusのアーキテクチャとそこに到るまでの考え方がただただすごかった
- Vimでテキストを編集するということへの捉え方
- モーションやオペレータの表現
- persistence-selectionはVimにも欲しい
Vimの日本語ドキュメント by MURAOKA Taro
- 「翻訳作業に手と目と知恵を貸してくれる人募集中」
- リファレンス&ユーザー・マニュアル
- メッセージ
- メニュー
- など
- 脱線しかけたのはAho-Corasick法(文字列探索アルゴリズム)
- 技術者はSPOFは排除したいはず
Vim script parser written in Go by haya14busa
- Fixer、Formatterに期待!
- stacktrace便利そう
- これがあればthemisでカバレッジ取れる!?
- Vim8とV8(node)は紛らわしい?
僕の友達を紹介するよ by aiya000
- aref-web.vim使ってみる
Best practices for building Vim plugins by thinca
:help design-goals
は知らなかった- シャイで有名なthincaさんがハイテンションで発表に懸ける強い想いが感じられた
感想
- 「Vimハラスメント」に気をつけようと思った
- 今回はチームのメンバ(2名)に参加してもらう事に成功した
- 楽しんでもらえたようで良かった
終わりに
発表者のみなさま、スタッフのみなさま、会場を提供してくださったミクシィさん、
ありがとうございました。
来年も是非参加したいです。
neocompleteとneobundleを捨てた
半年ほど使っていなかったのでvimrcを整理するタイミングで完全に消すことにした。
ただ長年ツートップだったプラグインなので消すに至った経緯を軽くメモっておく。
neocomplete
今の自分にはVim標準の補完機能(ins-completion
)で十分だった。
- 自動補完が発動するとVimが固まって使い物にならなくなることがある
- 特定の環境でたまにしか発生しないけど発生するとすごくストレス
- 自動補完されないと補完自体ができないと思ってしまう
- そんなことはなく、基本的には常に手動補完可能
- そもそも自動補完の対象になっていない補完機能もある
- if_luaが必須
昔は自動補完が必須だと思っていたけどVimの熟練度が上がったからか、
「補完したくなったらその時に
CTRL-X
(orN
,P
)押せばいいじゃん」
と思うようになった。
CTRL-X
が押しにくいと感じていたのもいつの間にか全然気にならなくなっていた。
neobundle
Vim標準のパッケージ機能(packages
)を使うことにした。
どうもプラグインを管理するプラグインに依存するのに疲れたっぽい。
決定版が出るまでは当分これでいくつもり。
次は脱unite!?
インターフェースは便利なんだけどやっぱり安定性はイマイチ...
(今までできていたことが急にできなくなったりすることがあるし)
いつ無くなっても困らないくらいには依存度を減らすようにしておくかな。