Skip to content

Commit

Permalink
feat(env): complete commands and variable assignments
Browse files Browse the repository at this point in the history
Refs #1111

Co-authored-by: Koichi Murase <[email protected]>
  • Loading branch information
scop and akinomyoga committed Apr 4, 2024
1 parent a3e8a5e commit 5c75fa3
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 1 deletion.
2 changes: 1 addition & 1 deletion bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -2991,7 +2991,7 @@ _comp_complete_longopt()
# makeinfo and texi2dvi are defined elsewhere.
complete -F _comp_complete_longopt \
a2ps awk base64 bash bc bison cat chroot colordiff cp \
csplit cut date df diff dir du enscript env expand fmt fold gperf \
csplit cut date df diff dir du enscript expand fmt fold gperf \
grep grub head irb ld ldd less ln ls m4 mkdir mkfifo mknod \
mv netstat nl nm objcopy objdump od paste pr ptx readelf rm rmdir \
sed seq shar sort split strip sum tac tail tee \
Expand Down
1 change: 1 addition & 0 deletions completions/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ bashcomp_DATA = 2to3 \
ebtables \
ecryptfs-migrate-home \
_eject \
env \
eog \
ether-wake \
evince \
Expand Down
49 changes: 49 additions & 0 deletions completions/env
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# bash completion for env(1) -*- shell-script -*-

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

local i noargopts='!(-*|*[uCS]*)'
for ((i = 1; i <= cword; i++)); do
if [[ ${words[i]} != -* && ${words[i]} != *=* ]]; then
_comp_command_offset $i
return
fi
# shellcheck disable=SC2254
[[ ${words[i]} == @(--@(unset|chdir|split-string)|-${noargopts}[uCS]) ]] &&
((i++))
done

# shellcheck disable=SC2254
case "$prev" in
--unset | -${noargopts}u)
_comp_compgen -- -A variable
return
;;
--chdir | -${noargopts}C)
_comp_compgen_filedir -d
return
;;
--split-string | -${noargopts}S)
return
;;
--block-signal | --default-signal | --ignore-signal)
# TODO signals, but only if completing with a =SIG
;;
esac

[[ $was_split ]] && return

_comp_variable_assignments "$cur" && return

if [[ $cur == -* ]]; then
_comp_compgen_help || _comp_compgen_usage
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
return
fi
} &&
complete -F _comp_cmd_env env

# ex: filetype=sh
24 changes: 24 additions & 0 deletions test/t/test_env.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import pytest

from conftest import assert_complete


class TestEnv:
@pytest.mark.complete("env --", require_longopt=True)
def test_1(self, completion):
assert completion

@pytest.mark.complete("env __unknown_variable__=")
def test_unknown_variable_falls_back_to_filedir(self, completion):
assert "shared/" in completion

@pytest.mark.complete("env LANG=", xfail="! locale -a &>/dev/null")
def test_lang_envvar(self, completion):
assert any(x == "C" or x.startswith("C.") for x in completion)

@pytest.mark.parametrize(
"opts",
[
"",
"foo=bar",
"--debug",
"foo=bar --debug",
"--debug foo=bar",
],
)
def test_command(self, bash, opts):
completion = assert_complete(bash, "env %s s" % opts)
assert completion == "h" or "sh" in completion

0 comments on commit 5c75fa3

Please sign in to comment.