From 1f94cf6ca59e91cb9d4cee6ff2bada65ada97340 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 31 Dec 2022 14:34:44 +0100 Subject: Improve CSS, add toggleable split --- html_diff.py | 459 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 330 insertions(+), 129 deletions(-) diff --git a/html_diff.py b/html_diff.py index 350cc9d..aef2a2e 100644 --- a/html_diff.py +++ b/html_diff.py @@ -37,6 +37,7 @@ from itertools import groupby, chain import pygments from pygments.formatters import HtmlFormatter from pygments.lexer import RegexLexer +from pygments.lexers import get_lexer_by_name, guess_lexer_for_filename, get_all_lexers, LEXERS from pygments import token @@ -49,172 +50,279 @@ HTML_TEMPLATE = r''' - @@ -223,7 +331,74 @@ $pygments_css +
+
+ Split view + +
+
+
+
+
+
+
+ +
$body +
''' @@ -347,6 +522,8 @@ from functools import lru_cache @lru_cache(maxsize=256) def get_token_class(ttype): while not (name := STANDARD_TYPES.get(ttype)): + if ttype is token.Token: + return 'n' ttype = ttype.parent return name @@ -426,21 +603,21 @@ class RecordFormatter(Formatter): self.lines.append(f'') assert change and lineno_theirs -def html_diff_content(old, new): +def html_diff_content(old, new, lexer): diff = list(difflib._mdiff(old.splitlines(), new.splitlines())) fmt_l = RecordFormatter('left', diff) - pygments.highlight(old, SexprLexer(), fmt_l) + pygments.highlight(old, lexer, fmt_l) fmt_r = RecordFormatter('right', diff) - pygments.highlight(new, SexprLexer(), fmt_r) + pygments.highlight(new, lexer, fmt_r) return '\n'.join(chain.from_iterable(zip(fmt_l.lines, fmt_r.lines))) -def html_diff_block(old, new, filename): - code = html_diff_content(old, new) +def html_diff_block(old, new, filename, lexer): + code = html_diff_content(old, new, lexer) return textwrap.dedent(f'''
-
{filename}
+
{filename}
{code}
@@ -454,30 +631,42 @@ creates an html page which highlights the differences between the two. """ parser = argparse.ArgumentParser(description=description) parser.add_argument('-b', '--open', action='store_true', help='Open output file in a browser') parser.add_argument('-s', '--syntax-css', help='Path to custom Pygments CSS file for code syntax highlighting') + parser.add_argument('-l', '--lexer', help='Manually select pygments lexer (default: guess from filename, use -L to list available lexers.)') + parser.add_argument('-L', '--list-lexers', action='store_true', help='List available lexers for -l/--lexer') parser.add_argument('-t', '--pagetitle', help='Override page title of output HTML file') parser.add_argument('-o', '--output', default=sys.stdout, type=argparse.FileType('w'), help='Name of output file (default: stdout)') parser.add_argument('--header', action='store_true', help='Only output HTML header with stylesheets and stuff, and no diff') parser.add_argument('--content', action='store_true', help='Only output HTML content, without header') - parser.add_argument('old', help='source file or directory to compare ("before" file)') - parser.add_argument('new', help='source file or directory to compare ("after" file)') + parser.add_argument('old', nargs='?', help='source file or directory to compare ("before" file)') + parser.add_argument('new', nargs='?', help='source file or directory to compare ("after" file)') args = parser.parse_args() + if args.list_lexers: + for longname, aliases, filename_patterns, _mimetypes in get_all_lexers(): + print(f'{longname:<20} alias {"/".join(aliases)} for {", ".join(filename_patterns)}') + sys.exit(0) + + if not (args.old and args.new): + print('Error: The command line arguments "old" and "new" are required.', file=sys.stderr) + parser.print_usage() + sys.exit(2) + if args.open and args.output == sys.stdout: - print('Error: --open requires --output to be given.') + print('Error: --open requires --output to be given.', file=sys.stderr) parser.print_usage() sys.exit(2) old, new = Path(args.old), Path(args.new) if not old.exists(): - print(f'Error: Path "{old}" does not exist.') + print(f'Error: Path "{old}" does not exist.', file=sys.stderr) sys.exit(1) if not new.exists(): - print(f'Error: Path "{new}" does not exist.') + print(f'Error: Path "{new}" does not exist.', file=sys.stderr) sys.exit(1) if old.is_file() != new.is_file(): - print(f'Error: You must give either two files, or two paths to compare, not a mix of both.') + print(f'Error: You must give either two files, or two paths to compare, not a mix of both.', file=sys.stderr) sys.exit(1) if old.is_file(): @@ -497,10 +686,22 @@ creates an html page which highlights the differences between the two. """ diff_blocks = [] for suffix, (old, new) in sorted(found_files.items()): - old = '' if old is None else old.read_text() - new = '' if new is None else new.read_text() + old_text = '' if old is None else old.read_text() + new_text = '' if new is None else new.read_text() + + if args.lexer: + lexer = get_lexer_by_name(lexer) + else: + if new.suffix.lower() in ('.kicad_mod', '.kicad_mod', '.kicad_pcb', '.kicad_sch')\ + or new.name == 'sym_lib_table': + lexer = SexprLexer() + else: + try: + lexer = guess_lexer_for_filename(new, new_text) + except: + lexer = get_lexer_by_name('text') - diff_blocks.append(html_diff_block(old, new, suffix)) + diff_blocks.append(html_diff_block(old_text, new_text, suffix, lexer)) print(string.Template(HTML_TEMPLATE).substitute( title=pagetitle, -- cgit