File: cli.py

package info (click to toggle)
python-mistletoe 1.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 864 kB
  • sloc: python: 5,649; sh: 66; makefile: 40
file content (92 lines) | stat: -rw-r--r-- 2,801 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import sys
import mistletoe
from argparse import ArgumentParser


version_str = 'mistletoe [version {}]'.format(mistletoe.__version__)


def main(args):
    namespace = parse(args)
    if namespace.filenames:
        convert(namespace.filenames, namespace.renderer)
    else:
        interactive(namespace.renderer)


def convert(filenames, renderer):
    for filename in filenames:
        convert_file(filename, renderer)


def convert_file(filename, renderer):
    """
    Parse a Markdown file and dump the output to stdout.
    """
    try:
        with open(filename, 'r', encoding='utf-8') as fin:
            rendered = mistletoe.markdown(fin, renderer)
            sys.stdout.buffer.write(rendered.encode())
    except OSError:
        sys.exit('Cannot open file "{}".'.format(filename))


def interactive(renderer):
    """
    Parse user input, dump to stdout, rinse and repeat.
    Python REPL style.
    """
    _import_readline()
    _print_heading(renderer)
    contents = []
    more = False
    while True:
        try:
            prompt, more = ('... ', True) if more else ('>>> ', True)
            contents.append(input(prompt) + '\n')
        except EOFError:
            print('\n' + mistletoe.markdown(contents, renderer), end='')
            more = False
            contents = []
        except KeyboardInterrupt:
            print('\nExiting.')
            break


def parse(args):
    parser = ArgumentParser()
    parser.add_argument('-r', '--renderer', type=_import,
                        default='mistletoe.HtmlRenderer',
                        help='specify an importable renderer class')
    parser.add_argument('-v', '--version', action='version', version=version_str)
    parser.add_argument('filenames', nargs='*',
                        help='specify an optional list of files to convert')
    return parser.parse_args(args)


def _import(arg):
    import importlib
    try:
        cls_name, path = map(lambda s: s[::-1], arg[::-1].split('.', 1))
        module = importlib.import_module(path)
        return getattr(module, cls_name)
    except ValueError:
        sys.exit('[error] please supply full path to your custom renderer.')
    except ImportError:
        sys.exit('[error] cannot import module "{}".'.format(path))
    except AttributeError:
        sys.exit('[error] cannot find renderer "{}" from module "{}".'.format(cls_name, path))


def _import_readline():
    try:
        import readline  # noqa: F401
    except ImportError:
        print('[warning] readline library not available.')


def _print_heading(renderer):
    print('{} (interactive)'.format(version_str))
    print('Type Ctrl-D to complete input, or Ctrl-C to exit.')
    if renderer is not mistletoe.HtmlRenderer:
        print('Using renderer: {}'.format(renderer.__name__))