VimConf 2018に行ってきた

VimConf 2018に行ってきました。

今年は@mattn_jpさんだけじゃなく、Vim作者のBramさんも発表するという超豪華Keynoteでした。
また、今年は去年以上に国際色高まるカンファレンスだったんじゃないかなと思います。
運営のみなさま、とても大変だったと思いますがすごく楽しい1日を過ごすことができました。
本当にありがとうございます。

以下セッションの一言感想です。

What is the next feature? by Yasuhiro Matsumoto

vim-jpについてのエモい話。
自分もVimにパッチを送る時、vim-jpにはとてもお世話になりました。
それにしても(ある程度形になった)パッチを用意してプレゼンに臨むのは流石です。

Vim: From hjkl to a platform for plugins by Bram Moolenaar

Vimの新機能について作者本人から話が聴けるというすごく貴重な発表でした。
プラグイン管理やVimの表現力がさらに充実していきそうで今後がとても楽しみです。
もちろんVim scriptのパフォーマンス向上も!

Migrating plugins to standard features by daisuzu

自分の発表。
Shougo wareを標準機能で置き換える話をしてきました。

Modes by Tatsuhiro Ujihisa

:Termdebugを使ったモードの実装の解説。
前にMeguro.vim:Termdebugを使っているところを見せてもらいましたが、とても便利そうでした。

A day in the life of (ordinary) Vimmer by OKURA Masafumi

Ordinary Vimmerは毎朝アップデートしますよね。
Learn once, use anywhere.
自分の発表で言いたかったことはこれです。

Modern editor-independent development environment for PHP by USAMI Kenta

普段はEmacsを使っていらっしゃる。
自分でHackできるツールが良いというのは完全に同意です。

Effective Modern Vim scripting by Alisue

Create your own plugin!
すごくわかります。
vital-Whiskyの中にあるRxがすごく気になりました。

Oni - The GUI-fication of Neovim by Akin

Electron(React + TypeScript)製のneovimクライアントの紹介。
バッファを分割してブラウザを開けるのはとても便利そうでした。

Vim ported to WebAssembly by rhysd

今日1番濃い発表だったんじゃないか...?
Vimの内部処理の解説がとても詳しくてすごく勉強になりました。
それにしても8日でやってしまうのが本当にすごい。

リポジトリごとにGOPATHを切る環境でのvim-go

↓のようなリポジトリごとにその直下をGOPATHにする環境でGoを書く時、

.
├── github.com/daisuzu/bar
│     ├── bin
│     ├── pkg
│     └── src
│         └── bar
│              └── main.go
└── github.com/daisuzu/foo
       ├── bin
       ├── pkg
       └── src
           └── foo
                └── main.go

両方のリポジトリのファイルを同時に開いて行ったり来たりするのを少し楽にするためにvim-goの設定を切り替える関数を作ることにした。

function! SwitchRepo()
  let toplevel = trim(system('git rev-parse --show-toplevel'))
  if toplevel =~# '^fatal'
    return
  endif

  " GOPATHをリポジトリ直下に変更する
  execute 'GoPath ' . toplevel

  " リポジトリ名をgoimportsの'-local'フラグに渡す
  let g:go_fmt_options = { 'goimports': '-local ' . fnamemodify(toplevel, ':t') }
endfunction

*1

これで他のリポジトリのファイルを開いたらcdした後にcall SwitchRepo()すれば:GoDefでちゃんと飛べるし、
:GoImportsした時もサブパッケージを標準パッケージとは異なるグループにしてくれる。

  • Before
import (
    "bar/handler"
    "bar/model"
    "fmt"
)
  • After
import (
    "fmt"

    "bar/handler"
    "bar/model"
)

autocmdを組み合わせればもっと便利になるかもしれないけど、今のところは必要ない。

*1:普段はg:go_fmt_optionsを使っていないので都度上書き

Meguro.vim #8 に行ってきた

Meguro.vim #8 で久しぶりにvimrcを整理し、不要なプラグインや設定なんかを削ったら300行くらい短くすることができた。
ついでにリファクタリングをして、次のような任意のEXコマンドの結果を新しいバッファに表示するコマンド*1を作ってみた。
(今までは特定のEXコマンドに限定していたものを使っていた)

command! -nargs=1 -complete=command L
      \ <mods> new
      \ | setlocal buftype=nofile bufhidden=hide noswapfile
      \ | call setline(1, split(execute(<q-args>), '\n'))

:scriptnamesとか:buffers用のつもりだったけど、ちょうど同じタイミングで開催された Osaka.vim #12@koturn さんが発表しているのを見て、:registers:marksで使っても良さそうだなと思った。

*1:実際はもう少し色々とやっている

Vimのカバレッジを見る

この記事はVim Advent Calendar 2017の2日目の記事です。

Vimカバレッジcoveralls.iocodecov.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. Vimの起動
  2. コマンドやキー入力
  3. Vimの終了

の順で操作をしつつ、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以下のソースが使われていることがわかりました。

f:id:daisuzu:20171202170437p:plain

処理を正確に追うにはデバッガを使うのが確実だとは思いますが、ソースの構造がある程度わかっていないと難しかったりもします。

f:id:daisuzu:20171202173329p:plain

なので、さらっと概要と知りたい時やソースコードリーディングのお供にでも是非カバレッジを活用してみてください。

: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

speakerdeck.com

という発表をしてきました。

最初は25分も話すことなんてあるかな?なんて思ってたら意外と良い感じの時間になりました。
少し足りなかったところを少し補足しておくと、

gitコマンド

  • v8.0.0512の調査で使ったgit bisect
# <bad> <good>の順番で指定する
git bisect start v8.0.0104 v8.0.0000

あとは都度makeし、手動で補完させてgoodかbadを判定していきました。
※コマンドからの補完だと再現しなかったため

活動時間帯について

  • 不具合の発見〜1次調査・応急処置
    • 職場
  • 2次調査〜パッチ作成

patchを送った後について

  • 質問とかツッコミは無かったの?
    • 全く無かった
    • パッチが小さかったからかも
    • もしくはタイミングが良かったからとか

場合によってはなかなか取り込まれないこともあったりするようです。

MacVimの不具合って?

マルチバイト文字が潰れて表示されてしまうという問題を修正しました。 github.com

コントリビュートする内容について

  • 新機能を追加したいんだけど
    • 色々大変だと思いますが、新機能を作れるくらいのパッションがあれば大丈夫だと思います!
  • ドキュメントや軽微な(typo・インデント)修正でも良いの?
    • OKです!

ちなみにコントリビュートに対するスタンスは最近聴いた

tech.gunosy.io

にすごく共感するものがあります。

vim-jpについて

vim-jpに気軽に相談してみましょう」なんて勝手に言ってしまって良いのかな?
とか思っていたんですが、なんと本日vim-jpのメンバー入りをしました。
もし何かあれば出来る範囲でサポートしていきたいです!
ということを本番でも話せれば良かったんですが、アドリブ力が無く。。。

     

という感じです。

スライドの英訳を助けてくれた ujihisa さん、
発表の翻訳をしてくださった sandkatt さん、
そしてスタッフのみなさま、
ありがとうございました!お疲れ様でした。

プレゼン資料にハイライトされたコードを貼り付ける

プレゼン資料を作っててコードを綺麗に表示させたくなったんだけど、 何かをインストールしたりとかは面倒だったのでvim*1を使ってやることにした。

以下のコマンドでブラウザが開くのでコピペするだけ。

" mac
:TOhtml | w | !open %

" win
:TOhtml | w | !start %

" linux
:TOhtml | w | !xdg-open %

調べてみたらプラグインが見つかったけどmac用だしインストールが面倒なので試していない…

github.com

*1:自分が使うPCには常にインストールされているし

Meguro.vim #4でプラグインを作った

Meguro.vim #4で自分用の:VimFilerSimpleに代わるプラグインを作りました。

github.com

vimfilerは機能が豊富でそこまで不満があったわけではないのですが、

  • 常に全ての機能を必要としているわけではない
  • unite.vimに依存している

ので、一番使う頻度の高い ファイルをツリー形式で表示する だけのプラグインが欲しかったからです。

f:id:daisuzu:20170715163006p:plain

実装としてはtreeコマンドの結果を

というものです。

マッピングは一切用意していないため、ファイルを開く時には標準機能の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>