From f047b70f140d2ca1186539f5e2bf86a0d797aa19 Mon Sep 17 00:00:00 2001 From: archetype Date: Sun, 26 Jun 2022 21:18:30 +0300 Subject: [PATCH 1/3] feat(doas): add new completion --- completions-core/Makefile.am | 1 + completions-core/doas.bash | 45 ++++++++++++++++++++++++++++++++++++ test/t/Makefile.am | 1 + test/t/test_doas.py | 17 ++++++++++++++ test/test-cmd-list.txt | 1 + 5 files changed, 65 insertions(+) create mode 100644 completions-core/doas.bash create mode 100644 test/t/test_doas.py diff --git a/completions-core/Makefile.am b/completions-core/Makefile.am index abcd93aea21..39d407e21ff 100644 --- a/completions-core/Makefile.am +++ b/completions-core/Makefile.am @@ -82,6 +82,7 @@ cross_platform = 2to3.bash \ dmypy.bash \ dnssec-keygen.bash \ dnsspoof.bash \ + doas.bash \ dot.bash \ dpkg.bash \ dpkg-source.bash \ diff --git a/completions-core/doas.bash b/completions-core/doas.bash new file mode 100644 index 00000000000..1b5abc64b19 --- /dev/null +++ b/completions-core/doas.bash @@ -0,0 +1,45 @@ +# doas(1) completion -*- shell-script -*- + +_comp_cmd_doas() +{ + local cur prev words cword split + _init_completion -s || return + + local i + + for ((i = 1; i <= cword; i++)); do + if [[ ${words[i]} != -* ]]; then + local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin + local root_command=${words[i]} + _command_offset $i + return + fi + [[ ${words[i]} == -@(!(-*)[uCLs]) ]] && + ((i++)) + done + + case "$prev" in + -!(-*)u) + COMPREPLY=($(compgen -u -- "$cur")) + return + ;; + -!(-*)C) + _filedir + return + ;; + -!(-*)[Ls]) + return + ;; + esac + + $split && return + + if [[ $cur == -* ]]; then + COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace + return + fi +} && + complete -F _comp_cmd_doas doas + +# ex: filetype=sh diff --git a/test/t/Makefile.am b/test/t/Makefile.am index 115f5736f10..b0736686f87 100644 --- a/test/t/Makefile.am +++ b/test/t/Makefile.am @@ -140,6 +140,7 @@ EXTRA_DIST = \ test_dmypy.py \ test_dnssec_keygen.py \ test_dnsspoof.py \ + test_doas.py \ test_dot.py \ test_dpkg.py \ test_dpkg_deb.py \ diff --git a/test/t/test_doas.py b/test/t/test_doas.py new file mode 100644 index 00000000000..a8039c58608 --- /dev/null +++ b/test/t/test_doas.py @@ -0,0 +1,17 @@ +import pytest + + +class TestDoas: + @pytest.mark.complete("doas -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("doas cd foo", cwd="shared/default") + def test_2(self, completion): + assert completion == ".d/" + assert not completion.endswith(" ") + + @pytest.mark.complete("doas sh share") + def test_3(self, completion): + assert completion == "d/" + assert not completion.endswith(" ") diff --git a/test/test-cmd-list.txt b/test/test-cmd-list.txt index bec7631b8d2..004c0153633 100644 --- a/test/test-cmd-list.txt +++ b/test/test-cmd-list.txt @@ -79,6 +79,7 @@ display dmesg dmypy dnsspoof +doas dpkg dpkg-deb dpkg-query From 22ebba4cc3df288559bbeb1ee379db9db9ed9647 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Sun, 28 Jun 2026 08:50:36 +0900 Subject: [PATCH 2/3] refactor(doas): use the latest internal API --- completions-core/doas.bash | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/completions-core/doas.bash b/completions-core/doas.bash index 1b5abc64b19..8b50f8ebdbd 100644 --- a/completions-core/doas.bash +++ b/completions-core/doas.bash @@ -1,45 +1,45 @@ -# doas(1) completion -*- shell-script -*- +# doas(1) completion _comp_cmd_doas() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local i + local noargopts='!(-*|*[uCLs]*)' + local i for ((i = 1; i <= cword; i++)); do if [[ ${words[i]} != -* ]]; then local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin local root_command=${words[i]} - _command_offset $i + _comp_command_offset "$i" return fi - [[ ${words[i]} == -@(!(-*)[uCLs]) ]] && + [[ ${words[i]} == -@(${noargopts}[uCLs]) ]] && ((i++)) done - case "$prev" in - -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + # shellcheck disable=SC2254 # glob $noargopts should not be quoted + case $prev in + -${noargopts}u) + _comp_compgen -- -u return ;; - -!(-*)C) - _filedir + -${noargopts}C) + _comp_compgen_filedir return ;; - -!(-*)[Ls]) + -${noargopts}[Ls]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && complete -F _comp_cmd_doas doas - -# ex: filetype=sh From a705713f8a5785d8e0a373224138d24977bc5865 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Sun, 28 Jun 2026 08:53:38 +0900 Subject: [PATCH 3/3] feat(doas): generate completions as if we're root --- completions-core/doas.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/completions-core/doas.bash b/completions-core/doas.bash index 8b50f8ebdbd..43a3d2a999d 100644 --- a/completions-core/doas.bash +++ b/completions-core/doas.bash @@ -12,6 +12,7 @@ _comp_cmd_doas() if [[ ${words[i]} != -* ]]; then local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin local root_command=${words[i]} + local _comp_root_command=$1 _comp_command_offset "$i" return fi