Skip to content

Commit

Permalink
feat(set): more featureful completion
Browse files Browse the repository at this point in the history
Complete option flags, with plus and dash prefixes, setopt values only
after `-o`/`+o`, allow filename completions if not preceded by `-` or
`--`.

Closes #103
  • Loading branch information
scop committed May 13, 2024
1 parent 0543d1a commit 1cb3eae
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 5 deletions.
3 changes: 0 additions & 3 deletions bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ complete -j -P '"%' -S '"' fg jobs disown
# readonly and unset complete with shell variables
complete -v readonly unset

# set completes with set options
complete -A setopt set

# shopt completes with shopt options
complete -A shopt shopt

Expand Down
1 change: 1 addition & 0 deletions completions/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ bashcomp_DATA = 2to3 \
screen \
scrub \
secret-tool \
set \
sh \
sha256sum \
shellcheck \
Expand Down
50 changes: 50 additions & 0 deletions completions/set
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# bash completion for set -*- shell-script -*-

_comp_cmd_set()
{
local cur prev words cword comp_args
_comp_initialize -- "$@" || return

local noargopts='!(-*|*[o]*)'

# shellcheck disable=SC2254
case "$prev" in
[+-]${noargopts}o)
_comp_compgen -- -A setopt
return
;;
esac

local i want_options=set
for ((i = 1; i < cword; i++)); do
if [[ ${words[i]} == -?(-) ]]; then
want_options=""
break
fi
done

if [[ $want_options && $cur == [+-]* ]]; then
local has_plus=""
if [[ $cur == +?([a-zA-Z]) ]]; then
has_plus=set
cur=${cur/#+/-}
fi
_comp_compgen_usage
if [[ $has_plus ]]; then
local i
for i in "${!COMPREPLY[@]}"; do
if [[ ${COMPREPLY[i]} == -- ]]; then
unset -v 'COMPREPLY[i]'
else
COMPREPLY[i]=${COMPREPLY[i]/#-/+}
fi
done
fi
return
fi

_comp_compgen_filedir
} &&
complete -F _comp_cmd_set set

# ex: filetype=sh
23 changes: 21 additions & 2 deletions test/t/test_set.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import pytest

from conftest import assert_complete


class TestSet:
@pytest.mark.complete("set no")
def test_1(self, completion):
@pytest.mark.parametrize("dash", ["", "-", "--"])
def test_basic(self, bash, dash):
completion = assert_complete(bash, f"set {dash} ")
assert completion

@pytest.mark.parametrize("prefix", ["-", "+"])
def test_options(self, bash, prefix):
completion = assert_complete(bash, f"set {prefix}")
assert f"{prefix}o" in completion
assert "+-" not in completion

@pytest.mark.parametrize("prefix", ["-", "+"])
def test_o_args(self, bash, prefix):
completion = assert_complete(bash, f"set {prefix}o ")
assert any(x.startswith("no") for x in completion)

@pytest.mark.parametrize("dash,prefix", [["-", "--"], ["-", "+"]])
def test_options_after_dash_or_dashdash(self, bash, dash, prefix):
completion = assert_complete(bash, f"set {dash} {prefix}")
assert not completion

0 comments on commit 1cb3eae

Please sign in to comment.