Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntax Highlighted Diffs

Tags:

git

git-diff

How to make Git display diffs in the terminal with code syntax highlight, like what GitHub does? I mean not only with green for addition and red for deletion, but also with code syntax highlighting.

like image 895
Fish Monitor Avatar asked May 31 '16 05:05

Fish Monitor


People also ask

What is meant by syntax highlighting?

Syntax highlighting determines the color and style of source code displayed in the Visual Studio Code editor. It is responsible for colorizing keywords like if or for in JavaScript differently than strings and comments and variable names.

How do you use syntax highlights in discord?

If you really want to spruce up your code blocks, you can denote a specific language for syntax highlighting, by typing the name of the language you want the code block to expect right after the first three backticks beginning your code block.

How do I show a diff in markdown?

Just add ```diff on start, and ``` on end.


2 Answers

I recently wrote a tool that does this: https://github.com/dandavison/delta

like image 65
5fec Avatar answered Nov 15 '22 20:11

5fec


It's possible to write a git diff driver that passes the files through Pygments' pygmentize tool.

First, define a pygmentize wrapper with your preferred pygmentize settings (formatter / style / filters) in ~/bin/pygmentize-term:

#!/bin/sh
exec pygmentize -f terminal256 -O bg=dark,style=trac "$@"

Then, define a generic "diff with syntax highlighting" program in ~/bin/hldiff:

#!/bin/bash
set -euo pipefail

# Diff two files with syntax highlighting using pygmentize.

# pygmentize-term should be a pygmentize wrapper with your preferred
# pygmentize settings (formatter / style / filters)

function prepare() {
    local fn=$1

    # Work around https://bitbucket.org/birkenfeld/pygments-main/issues/1437
    if [[ "$fn" == /dev/null ]]
    then
        return
    fi

    local lexer
    lexer=$(pygmentize -N "$fn")
    #printf "Detected lexer of %q as %q\n" "$fn" "$lexer" 1>&2

    if [[ "$lexer" == text ]]
    then
        expand "$fn" | pygmentize-term -g
    else
        expand "$fn" | pygmentize-term -l "$lexer"
    fi
}

# Use colordiff (instead of diff --color=always) solely because it
# produces consistent formatting on a per-line basis, saving us from
# having to keep track of state across lines
diff=(colordiff --color=yes)

for arg in "$@"
do
    if [[ $arg == -* ]]
    then
        diff+=("$arg")
    else
        exec {fd}< <(prepare "$arg")
        diff+=(/dev/fd/$fd)
    fi
done

sed=(
    sed
    # replace "all attributes off" (used by Pygmentize to turn off
    # bold) with "normal intensity"
    -e 's/\x1b\[00m/\x1b[22m/g'

    # Replace colordiff's foreground colors with some dark background
    # colors. You can customize them here.
    -e 's/^\x1b\[0;36m/\x1b[0;36;48;5;23m/' # cyan
    -e 's/^\x1b\[0;31m/\x1b[0;31;48;5;52m/' # red
    -e 's/^\x1b\[0;32m/\x1b[0;32;48;5;22m/' # green

    # Extend background color across the entire terminal window width
    -e 's/\x1b\[0;0m$/\x1b\[K\x1b[0m/'
)

"${diff[@]}" | "${sed[@]}"

The above can be used instead of diff to get a diff of two files with syntax highlighting.

To get git to use it, define a git diff driver wrapper for the above in ~/bin/git-hldiff-driver:

#!/bin/bash
set -euo pipefail

# Program suitable for GIT_EXTERNAL_DIFF, which will syntax-highlight differences.

hldiff -u "$2" "$5" || true

You can now set GIT_EXTERNAL_DIFF to the above wrapper script to get git to show diffs with syntax highlighting:

$ GIT_EXTERNAL_DIFF=~/bin/git-hldiff-driver git diff

To get git show to use it, you need to specify the --ext-diff switch:

$ GIT_EXTERNAL_DIFF=~/bin/git-hldiff-driver git show --ext-diff

Note that by default git show will send its output through a pager (less), which will cause the background color to not be displayed quite properly, so also add --no-pager to prevent that.

like image 35
Vladimir Panteleev Avatar answered Nov 15 '22 18:11

Vladimir Panteleev