File: bash_option_strings_completion.py

package info (click to toggle)
crazy-complete 0.3.6-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 2,404 kB
  • sloc: python: 7,949; sh: 4,636; makefile: 74
file content (106 lines) | stat: -rw-r--r-- 3,276 bytes parent folder | download | duplicates (3)
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
'''This module contains code for completing option strings in Bash.'''

from collections import namedtuple

from . import algo
from . import shell
from . import bash_when
from .str_utils import indent


_Option = namedtuple('_Option', ('option', 'conditions', 'when'))


def _make_option_strings(options):
    r = []
    for option in options:
        for option_string in option.option_strings:
            if len(option_string) != 2 and option.complete:
                r.append(f'{option_string}=')
            else:
                r.append(option_string)
    return ' '.join(shell.escape(option_string) for option_string in r)


def _get_option_full_condition(option):
    if option.conditions and option.when:
        return '(( %s )) && %s' % (' && '.join(option.conditions), option.when)
    if option.conditions:
        return '(( %s ))' % (' && '.join(option.conditions))
    if option.when:
        return '%s' % option.when

    return ''


def _generate_option_strings_completion(options):
    r = []

    grouped_by_condition = algo.group_by(options, _get_option_full_condition)
    for condition, opts in grouped_by_condition.items():
        s = 'opts+=(%s)' % _make_option_strings([o.option for o in opts])
        if condition:
            s = '%s && %s' % (condition, s)
        r.append(s)

    return '\n'.join(r)


def _generate_final_check_with_options(final_conditions, options):
    option_strings_completion = _generate_option_strings_completion(options)

    if not final_conditions:
        return option_strings_completion

    r  = 'if (( %s )); then\n' % ' && '.join(final_conditions)
    r += '%s\n' % indent(option_strings_completion, 2)
    r += 'fi'
    return r


def generate(generator):
    '''Generate option strings completion code.'''

    commandline      = generator.commandline
    variable_manager = generator.variable_manager
    options          = []
    final_conditions = []

    for final_option in commandline.get_final_options():
        final_conditions += ["! ${#%s[@]}" % variable_manager.capture_variable(final_option)]

    for option in commandline.options:
        if option.hidden:
            continue

        conditions = []

        for exclusive_option in option.get_conflicting_options():
            conditions += ["! ${#%s[@]}" % variable_manager.capture_variable(exclusive_option)]

        if not option.repeatable:
            conditions += ["! ${#%s[@]}" % variable_manager.capture_variable(option)]

        for final_condition in final_conditions:
            try:
                conditions.remove(final_condition)
            except ValueError:
                pass

        conditions = algo.uniq(sorted(conditions))

        when = None
        if option.when is not None:
            when = bash_when.generate_when_conditions(commandline, variable_manager, option.when)

        options.append(_Option(option, conditions, when))

    r  = 'if (( ! END_OF_OPTIONS )) && [[ "$cur" = -* ]]; then\n'
    r += '  local -a opts\n'
    r += '%s\n' % indent(_generate_final_check_with_options(final_conditions, options), 2)
    r += '  COMPREPLY+=($(compgen -W "${opts[*]}" -- "$cur"))\n'
    r += '  [[ ${COMPREPLY-} == *= ]] && compopt -o nospace\n'
    r += '  return 1\n'
    r += 'fi'

    return r