オフトゥン大好き。

惰眠系プログラマの作業ログで( ˘ω˘ ) スヤァ…

Emacs: git-gutterのhunk機能を使う。そしてhydraでちょこっと便利にする。

Emacsを愛するみなさん、こんにちは。
全然ブログが更新できてなくて「うわー!はてなのパスワードわすれたー!」とか思ったけど実は1Passwordで管理していたからなんとかなったid:nukosukeです。

今回はEmacsでGitのhunkを操作(または走査)するためのちょこっと便利な設定について書きます。

EmacsでGitというと最初に思い浮かぶのは、おなじみmagitですよね。僕もこれまでGit操作のほぼ全てをmagitに頼ってきました。
いやホントに、Gitバージョン管理が当たり前になったこのご時世にもしmagitがなかったらEmacsを使い続けることに挫折していたかもしれません。膨大なGit機能にフル対応しているのはおそらくこのパッケージだけでしょう。

ところが、最近になって差分箇所の視覚化にだけ使用していたgit-gutterにもhunkを操作する機能があることを知りました。この機能についてはgit-gutterのREADMEを見ればちゃんと書いてあるのですが、手早くいい感じの差分マーカーを付けたくて二次情報しか見てなかったこの愚か者は全然知りませんでした。反省しています。

github.com

ドキュメントにあるようにgit-gutterは以下のような機能を備えています(今回使用しないものは割愛)。

コマンド 機能説明
git-gutter:previous-hunk 1つ前のhunkにカーソルを移動する
git-gutter:next-hunk 1つ次のhunkにカーソルを移動する
git-gutter:stage-hunk 現在のhunkをstageする
git-gutter:revert-hunk 現在のhunkを破棄して元に戻す(undoでrevert-hunk操作をさらに戻すこともできる)
git-gutter:popup-hunk 現在のhunkをdiff形式で見れるバッファをポップアップする(別のhunkに移動すると内容を更新してくれるので超便利!!)

うわ〜これめっちゃ欲しかったやつ!既に入ってたのに気付かなかったーー!

というわけで最初は単純に M-pprevious-hunkM-nnext-hunk に割り当てて使ってたんですが、どうもしっくりこない。というかmetaキーのバインドを二つも占有するのはもったいない。そこでhydraを使っていい感じにしてみました。

;; 前提としてパッケージは全てstraight.elで入れています
(use-package hydra)

(use-package git-gutter
  :custom
  ;; stage, revertで確認を出さないようにする
  ;; (undoでもどせるからいいや、という気持ち)
  (git-gutter:ask-p nil)

  :bind
  ;; hydra-git-gutter起動のキーバインド
  ("C-c g" . hydra-git-gutter/body))

;; git-gutter:popup-hunkをそのまま割り当てるとdiffウィンドウを閉じれないので
;; トグルできる関数を定義
(defun git-gutter:toggle-popup-hunk ()
  "Toggle git-gutter hunk window."
  (interactive)
  (if (window-live-p (git-gutter:popup-buffer-window))
      (delete-window (git-gutter:popup-buffer-window))
      (git-gutter:popup-hunk)))

;; git-gutterのhydra定義
(defhydra hydra-git-gutter nil
  "git hunk"
  ("p" git-gutter:previous-hunk "previous")
  ("n" git-gutter:next-hunk "next")
  ("s" git-gutter:stage-hunk "stage")
  ("r" git-gutter:revert-hunk "revert")
  ("SPC" git-gutter:toggle-popup-hunk "toggle diffinfo"))

これで何が嬉しいかというと、 C-c g でhydra-git-gutterを起動した後、prefixキーなしで連続操作が可能になることです。 具体的には C-c g nnnnnn... とすると n を押す度に git-gutter:next-hunk が実行されhunkを次々と走査することができます( p で戻ることもできる)。

最初にスペースキーでdiffビューワーをポップアップし、hunkを見て行く途中で必要なhunkで s でstageし、いらないhunkを r で破棄する、といったことがスムーズにできるのです。 感覚としては git add -p に近いですが、途中で「あ、ここtypoしてる」とか気付いた時はそのまま編集してからstageに移すことも可能です。

言葉で説明してもいまいち分かりづらいと思うので動画にしました。

ファイル内の差分を整理するという点においてはmagitよりも使い勝手が良いんじゃないでしょうか。

というわけで、二次情報だけに頼ると損するのでちゃんと本家のREADME読みましょう(僕だけか...)