From 5443c819622495fcdc759d5dd4e5c31633eab389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Thu, 2 May 2019 16:57:25 +0300 Subject: [PATCH] _pnames: adapt for busybox ps, rewrite in pure bash Closes https://github.com/scop/bash-completion/issues/318 --- bash_completion | 51 ++++++++++++++++++++++++++++++------------ test/t/test_killall.py | 4 ++++ 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/bash_completion b/bash_completion index 58987a7fc1..bf7d02c753 100644 --- a/bash_completion +++ b/bash_completion @@ -1069,23 +1069,46 @@ _pnames() } || _pnames() { + local -a procs if [[ "$1" == -s ]]; then - COMPREPLY=( $(compgen -X '' \ - -W '$(command ps axo comm | command sed -e 1d)' -- "$cur") ) + procs=( $(command ps axo comm | command sed -e 1d) ) else - # FIXME: completes "[kblockd/0]" to "0". Previously it was completed - # to "kblockd" which isn't correct either. "kblockd/0" would be - # arguably most correct, but killall from psmisc 22 treats arguments - # containing "/" specially unless -r is given so that wouldn't quite - # work either. Perhaps it'd be best to not complete these to anything - # for now. - COMPREPLY=( $(compgen -X '' -W '$(command ps axo command= | command sed -e \ - "s/ .*//" -e \ - "s:.*/::" -e \ - "s/:$//" -e \ - "s/^[[(-]//" -e \ - "s/[])]$//" | sort -u)' -- "$cur") ) + local line i=-1 OIFS=$IFS + IFS=$'\n' + local -a psout=( $(command ps axo command=) ) + IFS=$OIFS + for line in "${psout[@]}"; do + if [[ $i -eq -1 ]]; then + # First line, see if it has COMMAND column header. For example + # the busybox ps does that, i.e. doesn't respect axo command= + if [[ $line =~ ^(.*[[:space:]])COMMAND([[:space:]]|$) ]]; then + # It does; store its index. + i=${#BASH_REMATCH[1]} + else + # Nope, fall through to "regular axo command=" parsing. + break + fi + else + # + line=${line:$i} # take command starting from found index + line=${line%% *} # trim arguments + procs+=( $line ) + fi + done + if [[ $i -eq -1 ]]; then + # Regular axo command= parsing + for line in "${psout[@]}"; do + if [[ $line =~ ^[[(](.+)[])]$ ]]; then + procs+=( ${BASH_REMATCH[1]} ) + else + line=${line%% *} # trim arguments + line=${line##@(*/|-)} # trim leading path and - + procs+=( $line ) + fi + done + fi fi + COMPREPLY=( $(compgen -X "" -W '${procs[@]}' -- "$cur" ) ) } # This function completes on user IDs diff --git a/test/t/test_killall.py b/test/t/test_killall.py index 725a16e4d6..136eee7373 100644 --- a/test/t/test_killall.py +++ b/test/t/test_killall.py @@ -11,3 +11,7 @@ def test_1(self, completion): @pytest.mark.complete("killall --signal ") def test_2(self, completion): assert all(x in completion for x in "INT KILL TERM".split()) + + @pytest.mark.complete("killall ") + def test_3(self, completion): + assert "command=" not in completion