Input中心のブログ

gina.vimとGitHubの連携を向上させる

September 15, 2020

久しぶりに書きます. 最近研究に忙殺されていて、あんまり技術書やら本が読めてなくて、ブログも書く時間がないです。 今日はgina.vimで便利な設定ができたのでブログにまとめていきたいと思います.

ところでGina.vimとは?

gina.vimはVim上で使うGitの便利なプラグインになります。 作者はlamdalisueaさんという方で、この他にもfern.vimsuda.vim等、様々なVimのプラグインを作ってらっしゃります。

gina.vimはその中でも、Gitの操作をVim上で行うためのプラグインで以下のようなメソッドが使えます。

  • Gina status
  • Gina commit
  • Gina blame
  • Gina browse …

詳しくはgina.vimのdocを見てください。 このブログでは多機能なgina.vimの中でもGitHubとの連携に絞ったことについて書いていきたいと思います。

Gina browseの基本機能について

Gina browseはOSのデフォルトブラウザで該当のリンクを開いてくれる機能になります。 これだけ聞くと、それならhub browseで十分じゃないかと思われるかもしれません。 しかし、ただこれだけではなく色々な応用を効かせることができます。

例えば、:Gina browse :と入力すると現在のファイルの場所を選択した状態でURLを開いてくれます。 また行単位のビジュアルモードで行を複数選択し、その状態で:Gina browse :を入力するとその行を選択した状態でリンクを開いてくれます。

alt

Gina browse —exact

Gina browse --exactはbranchではなくcommitのハッシュ値をもとにリンクを開いてくれます。 例えば、issueやPRで参照したいコードがある場合は参照したい場所を行単位のビジュアルモードで選択し、:Gina browse --exact :を入力します。 すると、先ほどと同じようなページが表示されますが、URLが絶妙に変わっていることに気が付くと思います。 これは先ほどとは違ってbranchではなく、commitのハッシュ値からページを開いてくれるためです。 そのページのURLをissueなどのコメントに貼ると以下の用に表示することが出来ます。

alt

また、わざわざブラウザを開かなくても、:Gina browse --exact --yank :と入力することで、ブラウザを開くことなくヤンクしてくれるので、clipboardの設定をしているならこのコマンドでも十分でしょう。 --exactを使用するには、現在のcommitをリモートのリポジトリにプッシュしている必要があります。

Gina browse --scheme

Gina browseには --scheme というオプションが用意されています。 用意されているオプションは_, root, blame, compareの4種類です。 僕は全てを理解しているわけではないですが、例えば:Gina browse --scheme=blame :と入力すると以下のようなblameページが表示されます。

alt

Gina blameとの連携

もちろん上の--scheme=blameオプションをつけなくても、Gina blameというコマンドがあり、各行についてどのコミットで追加されたものかというのが分かりやすくなってます。

alt

gina#command#blame#formatter#formatを変更することによって自分なりに表示するものを変えることができます。 詳しくは:help gina#command#blame#formatter#formatを入力してください。

これでこんなひどいコードを書いたのは誰だ!と糾弾するのに役立ちます。(大体こう思うときの犯人は自分ですが..) しかし、こういうひどいコードを書いてるときはcommitメッセージも適当になってしまいがちです。 自分の場合は、「fix」とか使いがちですね。。

こういう意図が分かりにくいコードやcommitメッセージでは、プルリクを見る以外に有効な手段がありません。 そこでこのblame画面から直接該当のプルリクを見に行くことができれば便利だと考て作成しました。

このコマンドは依存ツールとして、hubが必要になるので、あらかじめインストールしておいてください。

まずはcommitハッシュ値からブラウザで該当プルリクを開くAliasを作成します。 このAliasについてはCommit Hash から、該当 Pull Request を見つける方法という記事を参考にしました。 まずは準備としてコマンドラインに以下のようなコマンドを打ち込みます。

$ git config --global alias.openpr \!"f() { hub browse -- \`git log --merges --oneline --reverse --ancestry-path \$1...master | grep 'Merge pull request #' | head -n 1 | cut -f5 -d' ' | sed -e 's%#%pull/%'\`; }; f"

これで、

$ git openpr [ハッシュ値]

と打ち込むことで該当PRを開くことができます。 詳しくは元の記事を読んでください。 次に:Gina blameを開いているときに、カーソル下の行のcommitハッシュ値を取得し、上のコマンドに渡すことができればOKです。 以下のコマンドを.vimrc等に入力すると出来上がりです。

function! GinaOpenPR() abort
  redir => s:messages
    call gina#action#call('blame:echo')
  redir END
  let s:lastmsg = get(split(s:messages, "\n"), -1, "")
  let s:commit_hash = matchstr(s:lastmsg, '\[.*\]$')
  if strlen(s:commit_hash) < 2
    return
  endif

  let s:commit_hash = s:commit_hash[1:strlen(s:commit_hash)-2]
  call system(printf("git openpr %s", s:commit_hash))
endfunction

command! GinaOpenPR call GinaOpenPR()

あとは、:Gina blameを打った後に気になる行にカーソルを移動し、おもむろに:GinaOpenPRを入力すると該当のPRを開くことができます。

これで終わるのも微妙なのでコードについて、説明します。 まず最初のこの部分はgina.vimのactionであるblame:echoを読んでいます。(詳しくは:h gina-actions-blame) そして、次のget(...)ではechoされたメッセージで最新のものを取得しています 本当はカーソルの下commitハッシュ値を取得したかったのですが、gina.vimのAPIを探しても見つからないためこのような荒療治を行いました。

redir => s:messages
  call gina#action#call('blame:echo')
redir END
let s:lastmsg = get(split(s:messages, "\n"), -1, "")

続いての以下のコードでは、blame:echoの内容からcommitを抜き出してきています。 もしcommitが取得できない場合はreturnしています。

let s:commit_hash = matchstr(s:lastmsg, '\[.*\]$')
if strlen(s:commit_hash) < 2
  return
endif

let s:commit_hash = s:commit_hash[1:strlen(s:commit_hash)-2]

最後のこの部分ではgit openprで先ほど取得したcommitの紐づいたPRを開くようにしているという感じです。

call system(printf("git openpr %s", s:commit_hash))

これでblameを使い、そのあと該当のPRを開くことが出来ます! これで意味不明なコードが入っていたとしても安心ですね!

alt

まとめ

GinaとGitHub間の連携をうまく行うことが出来るメソッドを紹介したり、作成したりしていきました。

最後の:GinaOpenPRは、わざわざblame:echoをしていたり、Gina browseではなく外部コマンドであるhubを使っていたりと自分的には不満な点がいくつかありますが、普通に使いやすくなったのではないでしょうか? これで必要なコマンドをそろえてPRを出したい! と思ったりもしましたが、この方法だと

  • squashマージの場合にうまくいかない
  • GitHub以外で上手くいくかわからない
  • masterに直接マージをしていたら無意味になる

等々、どうすればいいか分からない点がいろいろあったのでブログを書くにとどまっておきました。 もし、便利だなと思ったらぜひ使ってください。

参考