💾 Archived View for mozz.us › markdown › render_vt100.py captured on 2024-08-25 at 02:07:11.
⬅️ Previous capture (2020-09-24)
-=-=-=-=-=-=-
#!/usr/bin/env python3 """ Convert a JSON-encoded Gemini AST into VT-100 styled text. """ import textwrap A_BOLD = '\u001b[1m' A_UNDERLINE = '\u001b[4m' A_REVERSED = '\u001b[7m' BLACK = '\u001b[30m' RED = '\u001b[31m' GREEN = '\u001b[32m' YELLOW = '\u001b[33m' BLUE = '\u001b[34m' MAGENTA = '\u001b[35m' CYAN = '\u001b[36m' WHITE = '\u001b[37m' RESET = '\u001b[0m' def render_vt100(ast, width): body = [] link_count = 0 def wrap(text, initial_indent, subsequent_indent): """Shorthand method for text wrapping to the page width""" return '\n'.join(textwrap.wrap( text, width, initial_indent=initial_indent, subsequent_indent=subsequent_indent, )) for name, value in ast: if name == 'Horizontal Rule': body.append('─' * width) elif name == 'Title': body.append('') title = value.upper().center(width)[:width] body.append(A_UNDERLINE + A_BOLD + title + RESET) elif name == 'Heading': heading = value.upper()[:width] body.append(A_BOLD + heading + RESET) elif name == 'Sub-Heading': subheading = value[:width] body.append(A_BOLD + subheading + RESET) elif name == 'Paragraph': body.append(wrap(value, '', '')) elif name == 'Preformatted': lines = value.splitlines(keepends=False) text_block = [wrap(line, '> ', '') for line in lines] body.append(BLUE + '\n'.join(text_block) + RESET) elif name == 'Ordered List': items = enumerate(value, start=1) text_block = [wrap(item, f'{i}. ', ' ') for i, item in items] body.append(GREEN + '\n'.join(text_block) + RESET) elif name == 'Unordered List': text_block = [wrap(item, '• ', ' ') for item in value] body.append(YELLOW + '\n'.join(text_block) + RESET) elif name == 'Link': link = wrap(value[1], f'[{link_count}] ', ' ') body.append(CYAN + link + RESET) link_count += 1 else: raise ValueError(f'Unrecognized node name `{name}`') return '\n\n'.join(body) def main(): import argparse import sys import json parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('infile', type=argparse.FileType('r'), default=sys.stdin) parser.add_argument('--width', type=int, default=50) args = parser.parse_args() ast = json.load(args.infile) text = render_vt100(ast, args.width) sys.stdout.write(text) if __name__ == '__main__': main()