File: help_converter.py

package info (click to toggle)
crazy-complete 0.3.6-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,404 kB
  • sloc: python: 7,949; sh: 4,636; makefile: 74
file content (133 lines) | stat: -rw-r--r-- 3,762 bytes parent folder | download | duplicates (2)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'''This module contains functions for generating a YAML file from help texts.'''

from . import help_parser
from . import yaml_source
from .str_utils import indent


def fix_description(s):
    '''Fix description.'''

    s = s.strip()

    # Replace hyphens followed by a newline ('-\n') with a simple hyphen.
    # This prevents words like "Some-word-with-\nhyphens" from being split
    # incorrectly due to the newline. Instead, it will correctly join as
    # "Some-word-with-hyphens".
    s = s.replace('-\n', '-')

    s = s.replace('\n', ' ')
    return s


def strip_metavar(s):
    '''Strip metavar.'''

    if s and s[0] == '[' and s[-1] == ']':
        s = s[1:-1]

    if s and s[0] == '=':
        s = s[1:]

    if s and s[0] == '<' and s[-1] == '>':
        s = s[1:-1]

    return s


def complete_for_metavar(string):
    '''Return completion for metavar.'''

    string = string.strip('<>')
    lower  = string.lower()

    equals = {
        'f':            ['file'],
        'n':            ['integer'],
        'duration':     ['integer'],
        'bits':         ['integer'],
        'cols':         ['integer'],
        'column':       ['integer'],
        'digits':       ['integer'],
        'size':         ['integer'],
        'bytes':        ['integer'],
        'pid':          ['pid'],
        'user':         ['user'],
        'group':        ['group'],
        'program':      ['command'],
        'command':      ['command'],
        'cmd':          ['cmd'],
        'signal':       ['signal'],
        'sig':          ['signal'],
    }

    endswith = {
        'file':         ['file'],
        'filename':     ['file'],
        'dir':          ['directory'],
        'directory':    ['directory'],
        'seconds':      ['integer'],
        'length':       ['integer'],
        'width':        ['integer'],
        'num':          ['integer'],
        'number':       ['integer'],
    }

    if lower in equals:
        return equals[lower]

    for suffix, complete in endswith.items():
        if lower.endswith(suffix):
            return complete

    if string.startswith('{') and string.endswith('}'):
        string = string.strip('{}')
        for sep in ['|', ',']:
            if sep in string:
                return ['choices', [item.strip() for item in string.split(sep)]]

    return ['none']


def from_file_to_yaml(file):
    '''Parse help text in a file and return YAML.'''

    with open(file, 'r', encoding='utf-8') as fh:
        content = fh.read()

    prog = help_parser.get_program_name_from_help(content)
    char_stream = help_parser.CharStream(content)
    parsed = help_parser.parse(char_stream)

    output = []

    output.append(f'prog: "{prog}"\nhelp: "<Program description here>"\noptions:')

    for obj in parsed:
        if isinstance(obj, help_parser.Unparsed):
            output.append(f"# {obj.text.rstrip()}")
        elif isinstance(obj, help_parser.OptionsWithDescription):
            option_dict = {
                'option_strings': [],
                'metavar':        None,
                'optional_arg':   False,
                'help':           fix_description(obj.description or '')
            }

            for option in obj.options:
                option_dict['option_strings'].append(option.option)

                if option.optional:
                    option_dict['optional_arg'] = True

                if option.metavar:
                    option_dict['metavar'] = strip_metavar(option.metavar)
                    option_dict['complete'] = complete_for_metavar(option_dict['metavar'])

            output.append(
                indent(yaml_source.option_to_yaml(option_dict), 2)
            )

            output.append('')

    return '\n'.join(output)