Unite.vimとwatsonを使ったワークフロー

最近、vim-unite-watsonを開発しました。

これが、watsonの作者であるnhmoodさんにも好評で、僕自身ワークフローが変化して、だいぶ作業しやすくなりました。

今回は、タスク管理をしたい人向けに、僕なりのワークフロー管理を紹介します。

ワークフローとVim

僕は普段、Webサービスの構築・保守を行う仕事をしています。

そこでは、基本的なフローは次のような流れです。

  1. 新機能・バグに対してIssueを発行する(あるいは既にTODOリストにある)
  2. トピックブランチを作る
  3. コードを書く
  4. コミット -> Pull-Requestを送る -> マージする

では、Vimを一度も閉じることなくこれらの作業をしてみます。

1. Issueの発行

1-1. TODOをコードに入力する

本番環境用にViewを作成すると記入する

1-2. IssueをGithubにあげる

インラインIssue管理のwatsonを使って、GithubにIssueをあげます

:Watsonのデモ

Watsonを使えば、Vimから簡単にIssue管理を行うことが出来ますね。

2. 作業の目処を立てる

さて、これでIssueは挙げられたので、次はコードの改修をしていきます。

2-1. トピックブランチを作る

ブランチの作業は、vim-unite-gitiを使います。

:Unite giti/branch

新しいブランチの名前を入力して、[checkout branch]の行を選択します。

Unite gitiのデモ

すると、新しいブランチが作られました。

2-2. コードの改修を行う場所に印をつけて行く

コードの改修は、多くの場合幾つかのファイルに跨がります。

そのため、経験から作業が必要な箇所に目処をつけて、コメントを書いて行きます。

todoの内容は、watsonによって管理されるので、vim-unite-watsonを使えば一覧としてみることができます。

:Unite watson/dirty

unite-watsonのdemo

これで、issueを解決するために必要な作業の一覧を自分で作ることが出来ました。

Unite上のコメントを選択すると、該当箇所に飛べます。

後は、

  1. 該当箇所に飛ぶ
  2. コードを修正する
  3. 解決したら、コメントを削除する

:Unite watson/dirtyが空になるまで繰り返します。

watsonの結果リストが空になれば、issueの問題を解決したことになり、次の作業に移ります。

3. GithubにPull-Requestする

これは、各々方法が分かれるかと思います。

Vimから出ないでPull-Requestを送るには、:!git push && :!hub pull-request -h ...というのが一番分かりやすいでしょうか。

僕は、:Unite giti/pull_requestで送るようにしています。

まとめ

Watsonやgitiはかなり便利です。

特に、watsonはコーディング作業をマネジメントしたい人に向いていると思います。 作業時間の見積もりや、タスク管理を考えながらコーディングする人には向いているプラグインなのではないでしょうか。

僕は経営学部にいるので、すっかりタスク管理や時間計測を気にしちゃうようになりました。。

今回紹介したプラグイン

NeoComplete vs YouCompleteMe

この記事はVim Advent Calendar 2013の10日目です。

先日は@Lindaさんの無数のパッチを組み合わせて君だけの MacVim を作ろう!でした。

大学卒業までに、自分専用Vimを作ろうと思っている自分にとって大変参考になる記事でした。

NeoComplete VS YouCompleteMe

さてさて、本日のAdvent CalendarではVimの補完プラグインの2大巨頭を比較してみようと思います。

元々、僕は大のShougo wareファンです。(Sourceや、本体への貢献も少ししています)

そんな僕もVimを探求する気持ちから、ついYouCompleteMeに手を出してしまいました!!!

「は…速いぞこいつ!!」

その補完速度の衝撃さることながら、他にも素晴らしいことが。

つい、NeoCompleteからの乗り換えが脳裏をよぎり、2週間使ってみることにしました。

何について書くの?

結論から言うと、NeoCompleteに戻ってきました。

しかし、NeoCompleteに改善の余地があることに気付きました。

「YCMのここが良かったから、NeoCompleteに取り入れよう!」という話をしたいと思います。

YouCompleteMeの良かった点

  • 補完が早い
  • ファイル補完が素晴らしい
  • 設定がほぼ不要
  • jedi.vim / clang-completeとの連携が容易
  • fuzzy補完が使いやすい!
  • YCM、と略しやすい。←

補完スピードに関しては、感動しました。

ファイル補完機能

特筆すべきはファイル補完機能についてです。

使ってわかる、YCMのファイル補完の素晴らしさ。

YCMのファイル補完機能

  • “[Dir], [File]”で、補完候補の種類を入力している
  • ファイル補完時、バッファ補完などのノイズが入らない

今まで、NeoCompleteで満足していたんですが、YCMを使って初めて改善の余地があることに気付きました。

YouCompleteMeの悪かった点

  • 補完の種類が少ない
  • カスタマイズができない。
  • 補完候補のdupフラグが全てオン

いや、一応カスタマイズしてNeoCompleteの移植できたんですけどね。疲れました。

NeoCompleteを改善する

さて、YCMを使って2週間。良いところをいくつか取り入れましょう。

(追記: ファイル補完に関する修正は、本家に取り込まれました)

1. file補完のノイズを改善する

デフォルトのNeoCompleteのfile補完のrankが低いため、ファイル補完時に他の候補が上にきてしまいます。

ファイル補完の優先順位をあげましょう。

call neocomplete#custom#source('file', 'rank', 10)

これに関しては、元々のファイル補完のrankがなぜ低いのか疑問です。理由があるのでしょうか。

2. file補完で[Dir], [File]を表示する

NeoCompleteにパッチをあてます。

これで、YouCompleteMeと同じファイル補完を実現できます。

3. 補完速度を向上する

YCMでは、補完が少し止まる感覚が一切ありませんでした。

NeoCompleteはsourceを駆け巡って、頑張って補完候補を取得しているのである程度は仕方ないです。

ただ、自分の環境にあわせれば、補完スピードはあがるはずです。

" 極端な例ですが、下記のような操作で補完をチューニングできます

" 補完を始めるキーワード長を長くする
let g:neocomplete#sources#syntax#min_keyword_length = 4
let g:neocomplete#auto_completion_start_length = 4

" 補完が止まった際に、スキップする長さを短くする
let g:neocomplete#skip_auto_completion_time = '0.2'

" 使用する補完の種類を減らす
" 現在のSourceの取得は `:echo keys(neocomplete#variables#get_sources())`
" デフォルト: ['file', 'tag', 'neosnippet', 'vim', 'dictionary', 'omni', 'member', 'syntax', 'include', 'buffer', 'file/include']
let g:neocomplete#sources = {
  \ '_' : ['vim', 'omni', 'include', 'buffer', 'file/include']
  \ }

" 特定のタイミングでのみ使う補完は、直接呼び出すようにする
inoremap <expr><C-X><C-F>  neocomplete#start_manual_complete('file')
inoremap <expr><C-X><C-K>  neocomplete#start_manual_complete('dictionary')
inoremap <expr><C-X>s      neocomplete#start_manual_complete('neosnippet')

まとめ

浮気して、彼女の良さに気付くパターンです。

YCMを使って気付きました。なんだかんだNeoCompleteが最高ですね!!

インラインTODO管理のWatsonを使う

最近、Githubのトレンドにも入っていたWatsonを紹介します。

watsonのデモ

インラインTODO管理とは何か

もしあなたがエンジニアなら、次のようなコメントを見たことがあると思います。

class ApplicationController < ActionController::Base
  def logged_in?
    # TODO 管理ユーザーと処理を分ける
    ...
  end
end

このように、コード内には至る所にコメントが書かれています。 単なるコードの説明に限らず、修正が必要な内容を記述したものも多くあります。

しかしながら、しばしばこういったコメントは放置され、コードの中に埋もれたままになってしまうこともあります。

Watsonは、コード内に書かれたコメントを走査し、近代的な管理ツールに流し込むことでIssueを管理するツールです。

どうやって使うのか

watsonを使って、コード内に記述されたコメントを洗い出して、GithubのIssueに登録してみましょう。

ステップ1: watsonのインストール

$ gem install watson

ステップ2: watsonの初期化

$ cd path/to/project_dir
$ watson
# 一旦<Ctrl-C>で終了してください。

.watsonrcが自動的に作成されるので、プロジェクトに合わせて走査するディレクトリなどを設定します。

例として、Railsプロジェクト用の.watsonrcを貼付けておきます。

ステップ3: watsonの実行!!

watsonを使うときは、独自のタグを使ってコメントを書いておきます。

  • [todo] - タスクの内容を記入する
  • [review] - 他の人に意見を求めるような内容を記入する
  • [fix] - バグの内容を記入する

試しに、適当なファイルを開いて、上記のようなフォーマットでコメントを記入してみてください。

後は、再度watsonと打って実行!

めでたしめでたし。 プロジェクト内のTODOなどが、一覧で出力されます。

ステップ4: githubへIssue登録する

先ほどの出力した内容を、Githubへ一括同期しましょう。

まず、Githubのリポジトリをwatsonに認識させます

$ watson --remote github

英語のコメントに沿って、情報を入力していきましょう。

続いて、Issueを登録します。

$ watson --update

処理が終わると、Githubのissueへの登録が完了です。

githubのissueプレビュー

まとめ

watsonは先月ぐらいに注目され始めた新しいプロジェクトです。

今後は、コメントを活用して様々な処理を行えるように拡張されると思うので、動向が楽しみですね。

watsonの現状

  • Ruby初心者の人が作ったため、コードがよろしくない(PR中)
  • 今のところ対応している管理ツールは、githubとbitbucket。
  • 安定版に必要な機能が未実装。なので、新機能のPRがなかなか取り入れられない状況。数ヶ月待たないといけなさそう。
  • 対応しているファイルタイプがまだ少ない

Guard-shellが便利だった話

Guardって便利ですよねー。

あの、ファイルをwatchして、変更を検知したらアクションをグルグル回すやつです。

最近Vimの開発をしていて、あー変更と同時にコンパイルしてくれたらいいのになぁ。

Guardを使って実現してみました。

guard + guard-shell

おなじみのGuardにshellコマンドを実行できるようにします。

GuardでC言語を自動コンパイル!!!

# Gemfile
source 'https://rubygems.org'

gem 'guard'
gem 'guard-shell'
# Guardfile
group :vim3 do
  guard :shell do
    target_dir = 'vim-3\.0/src'
    watch(%r!^#{target_dir}/(.+)\.(c|h)!) do
      `cd #{target_dir} && make`
      `cd #{target_dir} && make debug`
    end
  end

  ...
end

ポイントは、groupguard :shell …ですね。

guardのDSL group

groupのDSLを使うと、guardの設定を切り替えることができます。

例えば、バージョン毎にgroupで設定をわけておけば、不必要な部分でguardが動作することを防ぐことができます。 僕の場合は、vimのバージョン毎に設定を切り替えることで不必要なコンパイルを防いでいます。

また、分けてあるgroupを切り替えるときは、guardのコンソールでscope vim3と打てば切り替わります。

(起動時にscopeを指定する場合は、guard --group vim3)

guard-shellを使う

guard-shellは、ファイルの変更をフックにしてshellコマンドを実行するgemです。

と、あたかもshellに特化したネーミングですが、実際はただ単にwatchに渡したブロックを評価するだけのシンプルなやつです。

下記のようにすれば、ファイルが保存されたと同時にhogepiyooooooooooooooと教えてくれます。 わーい。

# Guardfile
guard :shell do
  watch(/.*/) { |m| `say hogepiyoooooooooooooo` }
end

まとめ

guard-shell便利。

(ホゲピヨーーーーーって言うのかと思ったら、「ホージピュゥ」って何か冷めた感じに返された。。。)

Vimを勉強し始めました #1

Vim読書会 #1

先日から続けているVim読書会(一人)ですが、 今回からモチベーションのために記事にあげて行おうと思います。

本日読むソースコード

Vim-0.3

  • cmdline.c
  • cmdtab.h
  • cmdcmds.c

cmdline.c L3723行

cmdline.c: functions for reading in the command line and executing it

// L650:
static char_u * DoOneCmd(buff) char_u *buff; {

この関数で、コマンドラインからの入力を処理してます。 関数の前半部分で入力をパースして、後半部分でコマンドを分岐しています。

分岐部分はこんな感じですね。

L1111:
cmdswitch:
  switch (cmdidx)
  {
    /*
     * quit current window, quit Vim if closed the last window
     */
    case CMD_quit:
      ...

    case CMD_qall:
      ...

:quitの処理を変更したかったら、case CMD_quit以下を変更すればいいです。

cmdtab.h L337行

また、CMD_...といった定数はcmdtab.hで初期化されており、全てのコマンドが定義されています。 コマンドは、ユニークなID,コマンド名,受け付ける引数がここで定義されます。

そのコマンドの実際の動作は、cmdline.cにべた書きされているという感じでしょうか。

Vim-3.0の書き方だと、コマンドがひとつ増える度にcmdline.cの分岐がひとつ増えるというヘビーな書き方なので、新しいバージョンではリファクタリングされてそう。

cmdcmds.c L541行

cmdcmds.c: functions for command line commands

cmdcmds.cは、cmdline.cでのコマンドの分岐で重なる部分の関数をまとめたもの、といった印象です。 Wordpressでいうfunctionsのような感じかな。一応、他の場所でも使える感じに仕上がっています。

この中には、do_aligndoshellといった、想像につく名前の関数がありますね。 CMD_moveで分岐した場合は、こちらに飛ばされます。

まとめ

コマンド関連の細かい実装を見るのは大変ですが、全体的に見ると読みやすかったです。 Vimのオプションやコマンド名が、そのまま変数に使われているので読みやすかったです。

:echoなどのコマンドを追加する場合は、ここら辺を弄るだけでなんとかなりそうですね! 次回トライしてみます。