Exemplo n.º 1
0
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))
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
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))
Exemplo n.º 4
0
            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)
        ]
Exemplo n.º 5
0
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()