git diffのようにワード単位で色の付いたdiffが欲しい

ワード単位のdiffが欲しかったのでメモ。

ワード単位のdiff?

以下のようなファイルがあるときに

$ ls src
src/000person.json
src/001person.json

000person.json と 001person.json の差分をdiffで見る1。色付きでみたいときには /tmp/a.diff などに出力してエディタでみたりなどしていた2

$ diff -u src/000person.json src/001person.json
--- src/000person.json  2020-01-08 06:16:00.000000000 +0900
+++ src/001person.json  2020-01-08 06:16:00.000000000 +0900
@@ -1,5 +1,5 @@
 {
-  "name": "foo",
-  "age": 20,
+  "name": "bar",
+  "age": 21,
   "type": "person"
 }

ところで、git diffはいい感じにワード単位で色付きで表示してくれる。

$ cp -r src/001person.json src/000person.json
$ git diff

git-diff

(追記: どうやらデフォルトの表示ではなく、diff-highlightを設定していたようだった。詳細は追記部分参照)

このようなワード単位の表示を他の場所でも使いたい。その方法のメモ。

行単位の色付け + 単語単位のハイライト

検索していたところ以下の様なスタックオーバーフローが見つかった。

まさにこれが探していたものだった。

#!/bin/sh -eu

# Use diff-highlight to show word-level differences

diff -U3 --minimal "$@" |
  sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
  diff-highlight

そんなわけで .bashrc に以下のような記述が増えた。

# diff -u <> <> | cdiffhighlight
cdiffhighlight() {
  SED=$(which gsed || which sed)
  $SED 's/^- /\x1b[1;31m-/;s/^+ /\x1b[1;32m+/;s/^@/\x1b[1;36m@/;s/$/\x1b[0m/' | diff-highlight
}

こんな感じで使う。最初はcdiffという関数を作っていたが補完などが効かなくなるので不便だったので辞めた。

$ diff -u xxx yyy | cdiffhighlight

これが

01

行単位で色が付き

02

ワード単位でハイライトされる。

03

sedとか使わずとも何らかのパッケージをインストールすれば便利だよという話はあるのかもしれないが、そもそもパッケージを新たに導入したくないのでこれくらいが無難なところだと思う3

ここからは追記

追記: diff-highlight

diff-highlightはgitをインストールしているとついてくる。

$ port contents git | grep "diff-highlight$"
  /opt/local/bin/diff-highlight
  /opt/local/share/git/contrib/diff-highlight/diff-highlight

追記: git diffのデフォルトのワード単位のdiff

git diffのデフォルトのワード単位のdiffというとこちらの表示になる模様。

$ git diff --word-diff=color

xx

~/.gitconfig に以下のような設定が含まれていた。以下の記事を参考にしていた模様

[pager]
    log = diff-highlight | less
    show = diff-highlight | less
    diff = diff-highlight | less

追記: 微妙にsedの内容を変えた

先頭の+++,---は色がついていなかった(スクリーンショットの時点では気づいていなかった)。変えた。 あと色が微妙に違った。

gist

https://gist.github.com/podhmo/fdc261640fd044648e73e01c5d62b9cb

参考


  1. 例はもう少し良いものが良かったが思いつかなかった

  2. 個人的にはEmacsを使っているが、他のエディタでもunified形式のdiffを色付きで表示する機能くらい存在しているはず

  3. pipでもnpmでも嫌だし、brew,portでも嫌