summaryrefslogtreecommitdiffstats
path: root/test/t/unit/test_unit_command_offset.py
blob: 0e32c1f8076fb401a7eaa5ab2322beb125dbc5f2 (plain)
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
134
135
136
137
138
139
140
141
142
143
144
from shlex import quote

import pytest

from conftest import assert_bash_exec, assert_complete, bash_env_saved


def join(words):
    """Return a shell-escaped string from *words*."""
    return " ".join(quote(word) for word in words)


@pytest.mark.bashcomp(
    cmd=None,
    cwd="_command_offset",
    ignore_env=r"^[+-](COMPREPLY|REPLY)=",
)
class TestUnitCommandOffset:
    wordlist = sorted(["foo", "bar"])

    @pytest.fixture(scope="class")
    def functions(self, bash):
        assert_bash_exec(
            bash,
            "_cmd1() { _comp_command_offset 1; }; complete -F _cmd1 cmd1; "
            "complete -F _comp_command meta; "
            "_compfunc() { COMPREPLY=(%s); }" % join(self.wordlist),
        )

        completions = [
            'complete -F _compfunc "${COMP_WORDS[0]}"',
            'complete -W %s "${COMP_WORDS[0]}"' % quote(join(self.wordlist)),
            'COMPREPLY=(dummy); complete -r "${COMP_WORDS[0]}"',
            "COMPREPLY+=(${#COMPREPLY[@]})",
        ]
        for idx, comp in enumerate(completions, 2):
            assert_bash_exec(
                bash,
                "_cmd%(idx)s() { %(comp)s && return 124; }; "
                "complete -F _cmd%(idx)s cmd%(idx)s"
                % {"idx": idx, "comp": comp},
            )

        assert_bash_exec(
            bash, "complete -W %s 'cmd!'" % quote(join(self.wordlist))
        )
        assert_bash_exec(bash, 'complete -W \'"$word1" "$word2"\' cmd6')

        assert_bash_exec(bash, "complete -C ./completer cmd7")

    def test_1(self, bash, functions):
        assert_complete(bash, 'cmd1 "/tmp/aaa bbb" ')
        assert_bash_exec(bash, "! complete -p aaa", want_output=None)

    @pytest.mark.parametrize(
        "cmd,expected_completion",
        [
            ("cmd2", wordlist),
            ("cmd3", wordlist),
            ("cmd4", []),
            ("cmd5", ["0"]),
        ],
    )
    def test_2(self, bash, functions, cmd, expected_completion):
        """Test meta-completion for completion functions that signal that
        completion should be retried (i.e. change compspec and return 124).

        cmd2: The case when the completion spec is overwritten by the one that
        contains "-F func"

        cmd3: The case when the completion spec is overwritten by the one
        without "-F func".

        cmd4: The case when the completion spec is removed, in which we expect
        no completions.  This mimics the behavior of Bash's progcomp for the
        exit status 124.

        cmd5: The case when the completion spec is unchanged.  The retry should
        be attempted at most once to avoid infinite loops.  COMPREPLY should be
        cleared before the retry.
        """
        assert assert_complete(bash, "meta %s " % cmd) == expected_completion

    @pytest.mark.parametrize(
        "cmd,expected_completion",
        [
            ("cmd7 ", wordlist),
            ("cmd7 l", ["line\\^Jtwo", "long"]),
            ("cmd7 lo", ["ng"]),
            ("cmd7 line", ["\\^Jtwo"]),
            ("cmd7 cont1", ["cont10", "cont11\\"]),
        ],
    )
    def test_3(self, bash, functions, cmd, expected_completion):
        got = assert_complete(bash, f"cmd1 {cmd}")
        assert got == assert_complete(bash, cmd)
        assert got == expected_completion

    def test_cmd_quoted(self, bash, functions):
        assert assert_complete(bash, "meta 'cmd2' ") == self.wordlist

    def test_cmd_specialchar(self, bash, functions):
        assert assert_complete(bash, "meta 'cmd!' ") == self.wordlist

    def test_space(self, bash, functions):
        with bash_env_saved(bash) as bash_env:
            bash_env.write_variable("word1", "a b c")
            bash_env.write_variable("word2", "d e f")
            assert assert_complete(bash, "meta cmd6 ") == ["a b c", "d e f"]

    @pytest.fixture(scope="class")
    def find_original_word_functions(self, bash):
        assert_bash_exec(
            bash,
            "_comp_test_reassemble() {"
            "    local IFS=$' \\t\\n' REPLY;"
            '    COMP_LINE=$1; _comp_split COMP_WORDS "$2"; COMP_CWORD=$((${#COMP_WORDS[@]}-1));'
            "    _comp__reassemble_words = words cword;"
            "}",
        )
        assert_bash_exec(
            bash,
            "_comp_test_1() {"
            '    local COMP_WORDS COMP_LINE COMP_CWORD words cword REPLY; _comp_test_reassemble "$1" "$2";'
            '    _comp__find_original_word "$3";'
            '    echo "$REPLY";'
            "}",
        )

    def test_find_original_word_1(self, bash, find_original_word_functions):
        result = assert_bash_exec(
            bash,
            '_comp_test_1 "sudo su do su do abc" "sudo su do su do abc" 3',
            want_output=True,
        ).strip()
        assert result == "3"

    def test_find_original_word_2(self, bash, find_original_word_functions):
        result = assert_bash_exec(
            bash,
            '_comp_test_1 "sudo --prefix=su su do abc" "sudo --prefix = su su do abc" 2',
            want_output=True,
        ).strip()
        assert result == "4"