# MIT License # # Copyright (c) 2016 Alex Goodman # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # of the Software, and to permit persons to whom the Software is furnished to do # so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import sys import difflib import argparse import StringIO import pygments from pygments.lexers import guess_lexer_for_filename from pygments.lexer import RegexLexer from pygments.formatters import HtmlFormatter from pygments.token import * class DefaultLexer(RegexLexer): """ Simply lex each line as a token. """ name = 'Default' aliases = ['default'] filenames = ['*'] tokens = { 'root': [ (r'.*\n', Text), ] } class DiffHtmlFormatter(HtmlFormatter): """ Formats a single source file with pygments and adds diff highlights based on the diff details given. """ isLeft = False diffs = None def __init__(self, isLeft, diffs, *args, **kwargs): self.isLeft = isLeft self.diffs = diffs super(DiffHtmlFormatter, self).__init__(*args, **kwargs) def wrap(self, source, outfile): return self._wrap_code(source) def getDiffLineNos(self): retlinenos = [] for idx, ((left_no, left_line),(right_no, right_line),change) in enumerate(self.diffs): no = None if self.isLeft: if change: if isinstance(left_no, int) and isinstance(right_no, int): no = '' + str(left_no) + "" elif isinstance(left_no, int) and not isinstance(right_no, int): no = '' + str(left_no) + "" elif not isinstance(left_no, int) and isinstance(right_no, int): no = ' ' else: no = '' + str(left_no) + "" else: if change: if isinstance(left_no, int) and isinstance(right_no, int): no = '' + str(right_no) + "" elif isinstance(left_no, int) and not isinstance(right_no, int): no = ' ' elif not isinstance(left_no, int) and isinstance(right_no, int): no = '' + str(right_no) + "" else: no = '' + str(right_no) + "" retlinenos.append(no) return retlinenos def _wrap_code(self, source): source = list(source) yield 0, '
' for idx, ((left_no, left_line),(right_no, right_line),change) in enumerate(self.diffs): #print idx, ((left_no, left_line),(right_no, right_line),change) try: if self.isLeft: if change: if isinstance(left_no, int) and isinstance(right_no, int) and left_no <= len(source): i,t = source[left_no-1] t = '' + t + "" elif isinstance(left_no, int) and not isinstance(right_no, int) and left_no <= len(source): i,t = source[left_no-1] t = '' + t + "" elif not isinstance(left_no, int) and isinstance(right_no, int): i,t = 1, left_line t = '' + t + "" else: raise else: if left_no <= len(source): i,t = source[left_no-1] else: i = 1 t = left_line else: if change: if isinstance(left_no, int) and isinstance(right_no, int) and right_no <= len(source): i,t = source[right_no-1] t = '' + t + "" elif isinstance(left_no, int) and not isinstance(right_no, int): i,t = 1, right_line t = '' + t + "" elif not isinstance(left_no, int) and isinstance(right_no, int) and right_no <= len(source): i,t = source[right_no-1] t = '' + t + "" else: raise else: if right_no <= len(source): i,t = source[right_no-1] else: i = 1 t = right_line yield i, t except: #print "WARNING! failed to enumerate diffs fully!" pass # this is expected sometimes yield 0, '\n' def _wrap_tablelinenos(self, inner): dummyoutfile = StringIO.StringIO() lncount = 0 for t, line in inner: if t: lncount += 1 dummyoutfile.write(line) fl = self.linenostart mw = len(str(lncount + fl - 1)) sp = self.linenospecial st = self.linenostep la = self.lineanchors aln = self.anchorlinenos nocls = self.noclasses lines = [] for i in self.getDiffLineNos(): lines.append('%s' % (i,)) ls = ''.join(lines) # in case you wonder about the seemingly redundant
'
' ' + ls + ' | ')
else:
yield 0, ('
|