Skip to content

Instantly share code, notes, and snippets.

@Antoine-Lassauzay
Last active November 6, 2015 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Antoine-Lassauzay/7e0732b6aa272d694622 to your computer and use it in GitHub Desktop.
Save Antoine-Lassauzay/7e0732b6aa272d694622 to your computer and use it in GitHub Desktop.
Colorize diff with pygments, and open it in a webpage
#!/usr/bin/env python
import sys
import os
import StringIO
import BaseHTTPServer
import cgi
import webbrowser
import pygments
import pygments.lexers
import pygments.formatters
import pygments.util
# Override HtmlFormatter's wrap function so it
# doesn't wrap our result in excess HTML containers
class LineHtmlFormatter(pygments.formatters.HtmlFormatter):
def wrap(self, source, outfile):
return source
DIFF_STYLES = """
pre { margin: 0px; }
.deletion { background-color: rgba(117, 0, 0, 0.3)}
.addition { background-color: rgba(0, 117, 0, 0.3) }
"""
EXTENSION_OVERRIDE = {'.bindings': '.cs'}
def generate_html(formatter, html_file):
html_file.write("<!DOCTYPE html>")
html_file.write("<html>")
html_file.write("<head>")
html_file.write("<meta charset=\"UTF-8\">")
html_file.write("<style>")
html_file.write(formatter.get_style_defs())
html_file.write(DIFF_STYLES)
html_file.write("</style></head>")
html_file.write("<body class=\"hll\">")
lexer = None
for line in sys.stdin:
line = line.rstrip('\n')
if not line:
continue
html_file.write("<pre class=\"highlight {}\" >".format({'+': "addition", '-':"deletion"}.get(line[0], '')))
if line.startswith("--"):
html_file.write(line)
lexer = None
elif line.startswith("+++"):
file_name, file_extension = os.path.splitext(line[4:])
file_extension = EXTENSION_OVERRIDE.get(file_extension, file_extension)
try:
lexer = pygments.lexers.get_lexer_for_filename(file_name + file_extension)
except pygments.util.ClassNotFound:
print "Warning: missing lexer for {}".format(line[4:])
html_file.write(line)
elif line.startswith("@") or line.startswith("diff"):
html_file.write(line)
elif lexer and line:
html_file.write(line[0] + pygments.highlight(line[1:], lexer, formatter).rstrip('\n'))
html_file.write("</pre>")
html_file.write('\n')
html_file.write("</body></html>")
if __name__ == "__main__":
formatter = LineHtmlFormatter(style="native")
html_file = StringIO.StringIO()
generate_html(formatter, html_file)
class MemoryFileHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
response_body = html_file.getvalue()
self.send_response(200)
self.send_header('Content-Type', 'text/html; encoding=utf8')
self.send_header('Content-Length', len(response_body))
self.send_header('Connection', 'close')
self.end_headers()
self.wfile.write(response_body)
BaseHTTPServer.BaseHTTPRequestHandler.protocol_version = 'HTTP/1.1'
BaseHTTPServer.SocketServer.TCPServer.allow_reuse_address = True
server = BaseHTTPServer.HTTPServer(('', 8081), MemoryFileHandler)
webbrowser.open("http://localhost:8081/")
# Serve one request, hopefully resulting from the browser session above
server.handle_request()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment