Skip to content

Commit 1cb3eae

Browse files
committed
feat(set): more featureful completion
Complete option flags, with plus and dash prefixes, setopt values only after `-o`/`+o`, allow filename completions if not preceded by `-` or `--`. Closes #103
1 parent 0543d1a commit 1cb3eae

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

bash_completion

-3
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,6 @@ complete -j -P '"%' -S '"' fg jobs disown
112112
# readonly and unset complete with shell variables
113113
complete -v readonly unset
114114

115-
# set completes with set options
116-
complete -A setopt set
117-
118115
# shopt completes with shopt options
119116
complete -A shopt shopt
120117

completions/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ bashcomp_DATA = 2to3 \
398398
screen \
399399
scrub \
400400
secret-tool \
401+
set \
401402
sh \
402403
sha256sum \
403404
shellcheck \

completions/set

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# bash completion for set -*- shell-script -*-
2+
3+
_comp_cmd_set()
4+
{
5+
local cur prev words cword comp_args
6+
_comp_initialize -- "$@" || return
7+
8+
local noargopts='!(-*|*[o]*)'
9+
10+
# shellcheck disable=SC2254
11+
case "$prev" in
12+
[+-]${noargopts}o)
13+
_comp_compgen -- -A setopt
14+
return
15+
;;
16+
esac
17+
18+
local i want_options=set
19+
for ((i = 1; i < cword; i++)); do
20+
if [[ ${words[i]} == -?(-) ]]; then
21+
want_options=""
22+
break
23+
fi
24+
done
25+
26+
if [[ $want_options && $cur == [+-]* ]]; then
27+
local has_plus=""
28+
if [[ $cur == +?([a-zA-Z]) ]]; then
29+
has_plus=set
30+
cur=${cur/#+/-}
31+
fi
32+
_comp_compgen_usage
33+
if [[ $has_plus ]]; then
34+
local i
35+
for i in "${!COMPREPLY[@]}"; do
36+
if [[ ${COMPREPLY[i]} == -- ]]; then
37+
unset -v 'COMPREPLY[i]'
38+
else
39+
COMPREPLY[i]=${COMPREPLY[i]/#-/+}
40+
fi
41+
done
42+
fi
43+
return
44+
fi
45+
46+
_comp_compgen_filedir
47+
} &&
48+
complete -F _comp_cmd_set set
49+
50+
# ex: filetype=sh

test/t/test_set.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
import pytest
22

3+
from conftest import assert_complete
4+
35

46
class TestSet:
5-
@pytest.mark.complete("set no")
6-
def test_1(self, completion):
7+
@pytest.mark.parametrize("dash", ["", "-", "--"])
8+
def test_basic(self, bash, dash):
9+
completion = assert_complete(bash, f"set {dash} ")
710
assert completion
11+
12+
@pytest.mark.parametrize("prefix", ["-", "+"])
13+
def test_options(self, bash, prefix):
14+
completion = assert_complete(bash, f"set {prefix}")
15+
assert f"{prefix}o" in completion
16+
assert "+-" not in completion
17+
18+
@pytest.mark.parametrize("prefix", ["-", "+"])
19+
def test_o_args(self, bash, prefix):
20+
completion = assert_complete(bash, f"set {prefix}o ")
21+
assert any(x.startswith("no") for x in completion)
22+
23+
@pytest.mark.parametrize("dash,prefix", [["-", "--"], ["-", "+"]])
24+
def test_options_after_dash_or_dashdash(self, bash, dash, prefix):
25+
completion = assert_complete(bash, f"set {dash} {prefix}")
26+
assert not completion

0 commit comments

Comments
 (0)