def record_subcommand(geometry, input_fileno, output_fileno, cast_filename): """Save a terminal session as an asciicast recording""" import termtosvg.term as term logger.info('Recording started, enter "exit" command or Control-D to end') if geometry is None: columns, lines = term.get_terminal_size(output_fileno) else: columns, lines = geometry with term.TerminalMode(input_fileno): records = term.record(columns, lines, input_fileno, output_fileno) with open(cast_filename, 'w') as cast_file: for record in records: print(record.to_json_line(), file=cast_file) logger.info('Recording ended, cast file is {}'.format(cast_filename))
def record_subcommand(process_args, geometry, input_fileno, output_fileno, cast_filename): """Save a terminal session as an asciicast recording""" from termtosvg.term import get_terminal_size, TerminalMode, record logger.info('Recording started, enter "exit" command or Control-D to end') if geometry is None: columns, lines = get_terminal_size(output_fileno) else: columns, lines = geometry with TerminalMode(input_fileno): # Do not write anything to stdout (print, logger...) while in this # context manager if the output of the process is set to stdout. We # do not want two processes writing to the same terminal. records = record(process_args, columns, lines, input_fileno, output_fileno) with open(cast_filename, 'w') as cast_file: for record_ in records: print(record_.to_json_line(), file=cast_file) logger.info('Recording ended, cast file is {}'.format(cast_filename))
def record_render_subcommand(template, geometry, input_fileno, output_fileno, svg_filename): """Record and render the animation on the fly""" import termtosvg.term as term logger.info('Recording started, enter "exit" command or Control-D to end') if geometry is None: columns, lines = term.get_terminal_size(output_fileno) else: columns, lines = geometry with term.TerminalMode(input_fileno): asciicast_records = term.record(columns, lines, input_fileno, output_fileno) replayed_records = term.replay( records=asciicast_records, from_pyte_char=anim.CharacterCell.from_pyte) anim.render_animation(records=replayed_records, filename=svg_filename, template=template) logger.info('Recording ended, SVG animation is {}'.format(svg_filename))
self.assertNotIn(4, events[1].line) # Event #2: Second line - cursor hidden self.assertEqual(events[2].row, 1) self.assertNotIn(4, events[2].line) # Event #3: Third line - cursor displayed after 'cccc' self.assertEqual(events[3].row, 2) self.assertEqual(events[3].line[4].color, 'background') self.assertEqual(events[3].line[4].background_color, 'foreground') def test_get_terminal_size(self): with self.subTest(case='Successful get_terminal_size call'): term_size_mock = MagicMock(return_value=(42, 84)) with patch('os.get_terminal_size', term_size_mock): cols, lines, = term.get_terminal_size(-1) self.assertEqual(cols, 42) self.assertEqual(lines, 84) def test__group_by_time(self): event_records = [ AsciiCastV2Event(0, 'o', b'1', None), AsciiCastV2Event(50, 'o', b'2', None), AsciiCastV2Event(80, 'o', b'3', None), AsciiCastV2Event(200, 'o', b'4', None), AsciiCastV2Event(210, 'o', b'5', None), AsciiCastV2Event(300, 'o', b'6', None), AsciiCastV2Event(310, 'o', b'7', None), AsciiCastV2Event(320, 'o', b'8', None), AsciiCastV2Event(330, 'o', b'9', None) ]
def main(args=None, input_fileno=None, output_fileno=None): # type: (List, Union[int, None], Union[int, None]) -> None if args is None: args = sys.argv if input_fileno is None: input_fileno = sys.stdin.fileno() if output_fileno is None: output_fileno = sys.stdout.fileno() console_handler = logging.StreamHandler(sys.stderr) console_handler.setLevel(logging.INFO) console_formatter = logging.Formatter('%(message)s') console_handler.setFormatter(console_formatter) logger.handlers = [console_handler] logger.setLevel(logging.INFO) configuration = config.init_read_conf() available_themes = config.CaseInsensitiveDict(**configuration) del available_themes['global'] command, args = parse(args[1:], available_themes) if args.verbose: _, log_filename = tempfile.mkstemp(prefix='termtosvg_', suffix='.log') file_handler = logging.FileHandler(filename=log_filename, mode='w') file_handler.setLevel(logging.DEBUG) file_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') file_handler.setFormatter(file_formatter) logger.handlers.append(file_handler) logger.info('Logging to {}'.format(log_filename)) if command == 'record': logger.info( 'Recording started, enter "exit" command or Control-D to end') if args.output_file is None: _, cast_filename = tempfile.mkstemp(prefix='termtosvg_', suffix='.cast') else: cast_filename = args.output_file columns, lines = term.get_terminal_size(output_fileno) with term.TerminalMode(input_fileno): records = term.record(columns, lines, input_fileno, output_fileno) with open(cast_filename, 'w') as cast_file: for record in records: print(record.to_json_line(), file=cast_file) logger.info('Recording ended, cast file is {}'.format(cast_filename)) elif command == 'render': logger.info('Rendering started') if args.output_file is None: _, svg_filename = tempfile.mkstemp(prefix='termtosvg_', suffix='.svg') else: svg_filename = args.output_file if args.font is None: font = configuration['GLOBAL']['font'] else: font = args.font fallback_theme_name = configuration['GLOBAL']['theme'] fallback_theme = configuration[fallback_theme_name] cli_theme = configuration.get(args.theme) records = asciicast.read_records(args.input_file) replayed_records = term.replay( records=records, from_pyte_char=anim.CharacterCell.from_pyte, override_theme=cli_theme, fallback_theme=fallback_theme) anim.render_animation(replayed_records, svg_filename, font) logger.info( 'Rendering ended, SVG animation is {}'.format(svg_filename)) else: # No command passed: record and render on the fly logger.info( 'Recording started, enter "exit" command or Control-D to end') if args.output_file is None: _, svg_filename = tempfile.mkstemp(prefix='termtosvg_', suffix='.svg') else: svg_filename = args.output_file columns, lines = term.get_terminal_size(output_fileno) if args.font is None: font = configuration['GLOBAL']['font'] else: font = args.font fallback_theme_name = configuration['GLOBAL']['theme'] fallback_theme = configuration[fallback_theme_name] cli_theme = configuration.get(args.theme) with term.TerminalMode(input_fileno): records = term.record(columns, lines, input_fileno, output_fileno) replayed_records = term.replay( records=records, from_pyte_char=anim.CharacterCell.from_pyte, override_theme=cli_theme, fallback_theme=fallback_theme) anim.render_animation(replayed_records, svg_filename, font) logger.info( 'Recording ended, SVG animation is {}'.format(svg_filename)) for handler in logger.handlers: handler.close()