File: bash_positionals_completion.py

package info (click to toggle)
crazy-complete 0.3.7-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,528 kB
  • sloc: python: 13,342; sh: 995; makefile: 68
file content (92 lines) | stat: -rw-r--r-- 2,563 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
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2025-2026 Benjamin Abendroth <braph93@gmx.de>

'''Module for positionals completion in Bash.'''

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


def _make_block(code):
    if not code:
        return '{\n  return 0;\n}'

    return '{\n%s\n  return 0;\n}' % indent(code, 2)


def _is_not_command_arg(positional):
    return (
        not positional.complete or
        positional.complete[0] != 'command_arg'
    )


def _generate_subcommand_positional(generator):
    cmds = generator.subcommands.get_choices().keys()
    complete = generator.completer.choices(generator.ctxt, [], cmds).get_code()
    return '(( ${#POSITIONALS[@]} == %d )) && %s' % (
        generator.subcommands.get_positional_num(),
        _make_block(complete))


def _get_positional_condition(positional):
    op = '=='
    if positional.repeatable:
        op = '>='
    return '${#POSITIONALS[@]} %s %s' % (op, positional.get_positional_num())


def _generate_positionals_with_when(generator):
    code = []

    positionals = filter(_is_not_command_arg, generator.positionals)

    for positional in positionals:
        condition = _get_positional_condition(positional)
        r = '(( %s )) && ' % condition
        if positional.when:
            r += '%s && ' % bash_when.generate_when_conditions(
                generator.commandline,
                generator.variable_manager,
                positional.when)
        r += '%s' % _make_block(generator.complete_option(positional))

        code.append(r)

    return '\n\n'.join(code)


def _generate_positionals_without_when(generator):
    code = []

    positionals = filter(_is_not_command_arg, generator.positionals)

    grouped_by_complete = algo.group_by(
        positionals, generator.complete_option)

    for complete, positionals in grouped_by_complete.items():
        conditions = [_get_positional_condition(p) for p in positionals]
        r = '(( %s )) && ' % ' || '.join(conditions)
        r += '%s' % _make_block(complete)
        code.append(r)

    return '\n\n'.join(code)


def generate(generator):
    '''Generate code for completing positionals.'''

    code = []

    has_when = any(p.when for p in generator.positionals)

    if has_when:
        code += [_generate_positionals_with_when(generator)]
    else:
        code += [_generate_positionals_without_when(generator)]

    if generator.subcommands:
        code += [_generate_subcommand_positional(generator)]

    return '\n\n'.join(c for c in code if c)