Skip to content

feat(_filedir): add -f to manually suffix / to directory names #847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions bash_completion
Original file line number Diff line number Diff line change
@@ -1166,9 +1166,15 @@ _comp_quote_compgen()

# This function performs file and directory completion. It's better than
# simply using 'compgen -f', because it honours spaces in filenames.
# @param $1 If `-d', complete only on directories. Otherwise filter/pick only
# completions with `.$1' and the uppercase version of it as file
# extension.
# @param $1 Complete filenames matching `.$1' and the uppercase version of it.
# Ignored with `-d`.
# OPTIONS
# -d Complete only on directories
# -f Perform `compopt -f filenames` modifications manually. This
# suffixes a slash to a directory name. This can be combined with
# the `-C dir` option to `_comp_compgen`, where the generated
# filenames do not exist in the current working directory and Bash
# fails to properly detect the filenames.
# @return 0 if at least one completion is generated, or 1 otherwise.
#
# @since 2.12
@@ -1177,9 +1183,22 @@ _comp_compgen_filedir()
_comp_compgen_tilde && return

local -a toks
local _dir="" _filenames=""
local OPTIND=1 OPTARG="" OPTERR=0 _opt
while getopts ":df" _opt "$@"; do
case $_opt in
d) _dir=set ;;
f) _filenames=set ;;
*)
printf "bash_completion: %s: usage error\n" "$FUNCNAME" >&2
return 2
;;
esac
done
shift "$((OPTIND - 1))"
local _arg=${1-}

if [[ $_arg == -d ]]; then
if [[ $_dir ]]; then
_comp_compgen -v toks -- -d
else
local REPLY
@@ -1223,8 +1242,17 @@ _comp_compgen_filedir()
fi

if ((${#toks[@]} != 0)); then
# 2>/dev/null for direct invocation, e.g. in the _comp_compgen_filedir
# unit test
# compopt 2>/dev/null for direct invocation, e.g. in
# _comp_compgen_filedir unit test
if [[ $_filenames ]]; then
local i
for i in "${!toks[@]}"; do
if [[ -d ${toks[i]} ]]; then
toks[i]+=/
compopt -o nospace 2>/dev/null
fi
done
fi
compopt -o filenames 2>/dev/null
fi

4 changes: 2 additions & 2 deletions completions/_mount.linux
Original file line number Diff line number Diff line change
@@ -38,11 +38,11 @@ _comp_cmd_mount()
return
;;
-L)
_comp_compgen -C "/dev/disk/by-label/" -- -f
_comp_compgen -C "/dev/disk/by-label/" filedir -f
return
;;
-U)
_comp_compgen -C "/dev/disk/by-uuid/" -- -f
_comp_compgen -C "/dev/disk/by-uuid/" filedir -f
return
;;
-O | --test-opts)
6 changes: 3 additions & 3 deletions completions/_slackpkg
Original file line number Diff line number Diff line change
@@ -65,16 +65,16 @@ _comp_cmd_slackpkg()
;;
install-template | remove-template)
if [[ -e $confdir/templates ]]; then
_comp_compgen -C "$confdir/templates" -- -f -X \
"!?*.template" && COMPREPLY=("${COMPREPLY[@]%.template}")
_comp_compgen -C "$confdir/templates" filedir -f template &&
COMPREPLY=("${COMPREPLY[@]%.template}")
fi
return
;;
remove)
_comp_compgen_filedir
_comp_compgen -a -- -W 'a ap d e f k kde kdei l n t tcl x xap xfce
y'
_comp_compgen -aC /var/log/packages -- -f
_comp_compgen -aC /var/log/packages filedir -f
return
;;
install | reinstall | upgrade | blacklist | download)
2 changes: 1 addition & 1 deletion completions/removepkg
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ _comp_cmd_removepkg()
fi

local root=${ROOT:-/}
_comp_compgen -C "$root/var/log/packages" -- -f
_comp_compgen -C "$root/var/log/packages" filedir -f
} &&
complete -F _comp_cmd_removepkg removepkg

2 changes: 1 addition & 1 deletion completions/sbopkg
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ _comp_cmd_sbopkg()

_comp_compgen_split -l -- "$(command sed -ne "s/^SLACKBUILD NAME: //p" \
"$file")"
_comp_compgen -aC "$QUEUEDIR" -- -f -X "!*.sqf"
_comp_compgen -aC "$QUEUEDIR" filedir -f sqf
} &&
complete -F _comp_cmd_sbopkg sbopkg

2 changes: 1 addition & 1 deletion completions/slapt-get
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ _comp_cmd_slapt_get()
return
;;
ins) # --remove|--filelist
_comp_compgen -C /var/log/packages -- -f
_comp_compgen -C /var/log/packages filedir -f
return
;;
set) # --install-set
20 changes: 20 additions & 0 deletions test/t/unit/test_unit_compgen_filedir.py
Original file line number Diff line number Diff line change
@@ -24,11 +24,22 @@ def functions(self, request, bash):
"_g() { local cur;_comp_get_words cur; unset -v COMPREPLY; _comp_compgen_filedir e1; }; "
"complete -F _g g",
)
assert_bash_exec(
bash,
"_fc() { local cur=$(_get_cword); unset -v COMPREPLY; _comp_compgen -C _filedir filedir; }; "
"complete -F _fc fc; "
"complete -F _fc -o filenames fc2",
)
assert_bash_exec(
bash,
"_fd() { local cur;_comp_get_words cur; unset -v COMPREPLY; _comp_compgen_filedir -d; };"
"complete -F _fd fd",
)
assert_bash_exec(
bash,
"_fcd() { local cur=$(_get_cword); unset -v COMPREPLY; _comp_compgen -C _filedir filedir -df; };"
"complete -F _fcd fcd",
)

@pytest.fixture(scope="class")
def non_windows_testdir(self, request, bash):
@@ -68,6 +79,11 @@ def test_2(self, bash, functions, funcname):
completion = assert_complete(bash, "%s ab/" % funcname, cwd="_filedir")
assert completion == "e"

@pytest.mark.parametrize("funcname", "fc fc2".split())
def test_2C(self, bash, functions, funcname):
completion = assert_complete(bash, "%s _filedir ab/" % funcname)
assert completion == "e"

@pytest.mark.parametrize("funcname", "f f2".split())
def test_3(self, bash, functions, funcname):
completion = assert_complete(
@@ -156,6 +172,10 @@ def test_14(self, bash, functions, funcname):
def test_15(self, functions, completion):
assert completion == "b/"

@pytest.mark.complete(r"fcd a\ ")
def test_15d(self, functions, completion):
assert completion == "b/"

@pytest.mark.complete("g ", cwd="_filedir/ext")
def test_16(self, functions, completion):
assert completion == sorted("ee.e1 foo/ gg.e1 ii.E1".split())