Completed
Pull Request — master (#2448)
by Lasse
01:56
created

ChoicesCompleter   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 4
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
wmc 1
1
import argparse
2
import sys
3
4
from coalib.misc import Constants
5
from coalib.collecting.Collectors import get_all_bears_names
6
7
8
class CustomFormatter(argparse.RawDescriptionHelpFormatter):
9
    """
10
    A Custom Formatter that will keep the metavars in the usage but remove them
11
    in the more detailed arguments section.
12
    """
13
14
    def _format_action_invocation(self, action):
15
        if not action.option_strings:
16
            # For arguemnts that don't have options strings
17
            metavar, = self._metavar_formatter(action, action.dest)(1)
18
            return metavar
19
        else:
20
            # Option string arguments (like "-f, --files")
21
            parts = action.option_strings
22
            return ', '.join(parts)
23
24
25
def default_arg_parser(formatter_class=None):
26
    """
27
    This function creates an ArgParser to parse command line arguments.
28
29
    :param formatter_class: Formatting the arg_parser output into a specific
30
                            form. For example: In the manpage format.
31
    """
32
    formatter_class = formatter_class or CustomFormatter
33
34
    entry_point = sys.argv[0]
35
    for entry in ['coala-ci', 'coala-dbus', 'coala-format', 'coala-json',
36
                  'coala-delete-orig']:
37
        if entry_point.endswith(entry):
38
            parser_type = entry
39
            break
40
    else:
41
        parser_type = 'coala'
42
43
    description = """
44
coala provides a common command-line interface for linting and fixing all your
45
code, regardless of the programming languages you use.
46
47
To find out what kind of analysis coala offers for the languages you use, visit
48
<https://github.com/coala-analyzer/bear-docs/blob/master/README.rst#supported-languages>
49
or run:
50
51
    $ coala --show-bears --filter-by-language C Python
52
53
To perform code analysis, simply specify the analysis routines (bears) and the
54
files you want it to run on, for example:
55
56
    $ coala --bears SpaceConsistencyBear --files **.py
57
58
coala can also automatically fix your code:
59
60
    $ coala --bears SpaceConsistencyBear --files **.py --apply-patches
61
"""
62
63
    arg_parser = argparse.ArgumentParser(
64
        formatter_class=formatter_class,
65
        prog="coala",
66
        description=description,
67
        # Use our own help so that we can put it in the group we want
68
        add_help=False)
69
70
    arg_parser.add_argument('TARGETS',
71
                            nargs='*',
72
                            help="sections to be executed exclusively")
73
74
    info_group = arg_parser.add_argument_group('Info')
75
76
    info_group.add_argument('-h',
77
                            '--help',
78
                            action='help',
79
                            help='show this help message and exit')
80
81
    info_group.add_argument('-v',
82
                            '--version',
83
                            action='version',
84
                            version=Constants.VERSION)
85
86
    config_group = arg_parser.add_argument_group('Configuration')
87
88
    config_group.add_argument(
89
        '-c', '--config', nargs=1, metavar='FILE',
90
        help="configuration file to be used, defaults to {}".format(
91
            Constants.default_coafile))
92
93
    config_group.add_argument(
94
        '-F', '--find-config', action='store_const', const=True,
95
        help="find {} in ancestors of the working directory".format(
96
            Constants.default_coafile))
97
98
    config_group.add_argument(
99
        '-I', '--no-config', const=True, action='store_const',
100
        help="run without using any config file")
101
102
    config_group.add_argument(
103
        '-s', '--save', nargs='?', const=True, metavar='FILE',
104
        help="save used arguments to a config file to a {}, the given path, "
105
             "or at the value of -c".format(Constants.default_coafile))
106
107
    config_group.add_argument(
108
        '-C', '--changed-files', const=True, action='store_const',
109
        help='check only files that have changed since last run')
110
    config_group.add_argument(
111
        '--flush-cache', const=True, action='store_const',
112
        help='rebuild the file cache')
113
114
    inputs_group = arg_parser.add_argument_group('Inputs')
115
116
    inputs_group.add_argument(
117
        '-b', '--bears', nargs='+', metavar='NAME',
118
        help='names of bears to use').completer = (
119
            lambda *args, **kwargs: get_all_bears_names())  # pragma: no cover
120
121
    inputs_group.add_argument(
122
        '-f', '--files', nargs='+', metavar='FILE',
123
        help='files that should be checked')
124
125
    inputs_group.add_argument(
126
        '-i', '--ignore', nargs='+', metavar='FILE',
127
        help='files that should be ignored')
128
129
    inputs_group.add_argument(
130
        '--limit-files', nargs='+', metavar='FILE',
131
        help="filter the `--files` argument's matches further")
132
133
    inputs_group.add_argument(
134
        '-d', '--bear-dirs', nargs='+', metavar='DIR',
135
        help='additional directories which may contain bears')
136
137
    outputs_group = arg_parser.add_argument_group('Outputs')
138
139
    outputs_group.add_argument(
140
        '-V', '--verbose', action='store_const',
141
        dest='log_level', const='DEBUG',
142
        help="alias for `-L DEBUG`")
143
144
    outputs_group.add_argument(
145
        '-L', '--log-level', nargs=1,
146
        choices=['ERROR', 'INFO', 'WARNING', 'DEBUG'], metavar='ENUM',
147
        help="set log output level to ERROR/INFO/WARNING/DEBUG")
148
149
    outputs_group.add_argument(
150
        '-m', '--min-severity', nargs=1,
151
        choices=('INFO', 'NORMAL', 'MAJOR'), metavar='ENUM',
152
        help="set minimal result severity to INFO/NORMAL/MAJOR")
153
154
    # The following are "coala" specific arguments
155
    if parser_type == 'coala':
156
        outputs_group.add_argument(
157
            '-B', '--show-bears', const=True, action='store_const',
158
            help='list all bears')
159
160
        outputs_group.add_argument(
161
            '-l', '--filter-by-language', nargs='+', metavar='LANG',
162
            help="filters `--show-bears` by the given languages")
163
164
        outputs_group.add_argument(
165
            '-D', '--show-description', const=True, action='store_const',
166
            help="show bear descriptions for `--show-bears`")
167
168
        outputs_group.add_argument(
169
            '--show-details', const=True, action='store_const',
170
            help='show bear details for `--show-bears`')
171
172
    # The following are "coala-json" specific arguments
173
    if parser_type == 'coala-json':
174
        outputs_group.add_argument(
175
            '-B', '--show-bears', const=True, action='store_const',
176
            help='list all bears')
177
178
        outputs_group.add_argument(
179
            '-l', '--filter-by-language', nargs='+', metavar='LANG',
180
            help="filters `--show-bears` by the given languages")
181
182
        outputs_group.add_argument(
183
            '-o', '--output', nargs=1, metavar='FILE',
184
            help='write JSON logs to the given file')
185
186
        outputs_group.add_argument(
187
            '--text-logs', nargs='?', const=True, metavar='BOOL',
188
            help="use regular log messages instead of JSON")
189
190
        outputs_group.add_argument(
191
            '-r', '--relpath', nargs='?', const=True,
192
            help="return relative paths for files")
193
194
    misc_group = arg_parser.add_argument_group('Miscellaneous')
195
196
    misc_group.add_argument(
197
        '-S', '--settings', nargs='+', metavar='SETTING',
198
        help="arbitrary settings in the form of section.key=value")
199
200
    misc_group.add_argument(
201
        '-a', '--apply-patches', action='store_const',
202
        dest='default_actions', const='*: ApplyPatchAction',
203
        help='apply all patches automatically if possible')
204
205
    misc_group.add_argument(
206
        "-j", "--jobs", type=int,
207
        help="number of jobs to use in parallel")
208
209
    misc_group.add_argument(
210
        '-n', '--no-orig', const=True, action='store_const',
211
        help="don't create .orig backup files before patching")
212
213
    try:  # pragma: no cover
214
        # Auto completion should be optional, because of somewhat complicated
215
        # setup.
216
        import argcomplete
217
        argcomplete.autocomplete(arg_parser)
218
    except ImportError:
219
        pass
220
    return arg_parser
221