Last active
June 3, 2022 02:56
-
-
Save thomasfaingnaert/2b21a0a9d0768063fa932be350f3eb49 to your computer and use it in GitHub Desktop.
Fancy git-diff output with syntax highlighting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Inspired by: https://gist.github.com/oprypin/9668969 | |
import argparse | |
import pygments | |
import pygments.formatters | |
import pygments.lexers | |
import re | |
import sys | |
parser = argparse.ArgumentParser(description = 'Make git-diff output fancier by including syntax highlighting using Pygments.') | |
parser.add_argument('input', nargs='?', type=argparse.FileType('r'), default=sys.stdin, help='File containing the git-diff output') | |
parser.add_argument('--output', '-o', nargs='?', type=argparse.FileType('w'), default=sys.stdout, help='Output HTML file') | |
args = parser.parse_args() | |
# Regular expressions to ignore in the output. | |
ignore_patterns = [r'^diff --git', r'^index [0-9a-fA-F]+..[0-9a-fA-F]+ [0-9a-fA-F]+'] | |
ignore_regexes = [re.compile(pat) for pat in ignore_patterns] | |
# Pygments setup. | |
formatter = pygments.formatters.HtmlFormatter(nowrap=True) | |
infile = args.input | |
outfile = args.output | |
outfile.write('<!DOCTYPE html>') | |
outfile.write('<html>') | |
outfile.write('<head>') | |
outfile.write('<title>Diff</title>') | |
outfile.write('<style>') | |
outfile.write(formatter.get_style_defs()) | |
outfile.write('.diff_header { font-size: 1.6em; font-weight: bold; }') | |
outfile.write('.diff_minus { background-color: rgba(255, 0, 0, 0.3) }') | |
outfile.write('.diff_plus { background-color: rgba(0, 255, 0, 0.3) }') | |
outfile.write('.diff_special { background-color: rgba(128, 128, 128, 0.3); font-size: 1.3em; }') | |
outfile.write('.err { border: none; }') | |
outfile.write('</style>') | |
outfile.write('</head>') | |
outfile.write('<body>') | |
outfile.write('<div>') | |
outfile.write('<pre>') | |
filename = '' | |
def highlight(line, filename): | |
try: | |
lexer = pygments.lexers.get_lexer_for_filename(filename) | |
return pygments.highlight(line, lexer, formatter) | |
except: | |
return line | |
for line in infile.readlines(): | |
if any(regex.match(line) for regex in ignore_regexes): | |
continue | |
if line.startswith('--- ') or line.startswith('+++ '): | |
filename = line[4:].rstrip('\n') | |
if line.startswith('@@'): | |
pos = line.find('@@', 2) | |
line_range = line[:pos+2] | |
context = line[pos+2:] | |
highlighted_line = line_range + highlight(context, filename) | |
elif line.startswith('+++') or line.startswith('---'): | |
highlighted_line = f'<div class="diff_header">{line}</div>' | |
elif line.startswith('+') or line.startswith('-'): | |
highlighted_line = line[:1] + highlight(line[1:], filename) | |
else: | |
highlighted_line = highlight(line, filename) | |
cls = {'+': 'diff_plus', '-': 'diff_minus', '@': 'diff_special'}.get(line[0:1], '') | |
if cls != '': | |
cls = f' class="{cls}"' | |
outfile.write(f'<div{cls}>{highlighted_line}</div>') | |
outfile.write('</pre>') | |
outfile.write('</div>') | |
outfile.write('</body>') | |
outfile.write('</html>') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment