Skip to content

completion: try to complete copy or command #585

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 1 commit into
base: master
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
68 changes: 59 additions & 9 deletions bash_completion.d/clush
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
# clush bash completion
#
# to install in /usr/share/bash-completion/completions/ or ~/.local/share/bash-completion/completions/
_clush_command_or_file() {
# undo our nospace setting...
compopt +o nospace

# complete either files (copy mode) or commands (if target set)
case "$target_set,$mode" in
*,copy)
# available since bash-completion 2.12
if declare -F _comp_compgen_filedir >/dev/null; then
_comp_compgen_filedir
else
_filedir
fi
;;
1,command)
# available since bash-completion 2.12
if declare -F _comp_command_offset >/dev/null; then
_comp_command_offset "$i"
else
_command_offset "$i"
fi
;;
esac
}

_clush()
{
# shellcheck disable=SC2034 # set/used by _init_completion
local cur prev words cword split
local word options="" compopts="" skip=argv0 groupsource="" cleangroup=""
local i word options="" compopts="" skip=argv0 groupsource="" cleangroup=""
local mode=command target_set=""

_init_completion -s -n : || return

# stop parsing if there had been any non-option before (or --)
for word in "${words[@]}"; do
for i in "${!words[@]}"; do
word="${words[i]}"
case "$skip" in
"") ;;
groupsource)
Expand All @@ -23,7 +50,13 @@ _clush()
esac
case "$word" in
"") ;;
--) return;;
--)
i=$((i+1)) # command from next word!
_clush_command_or_file
return
;;
-c|--copy|--rcopy) mode=copy;;
-w|-g|--group) target_set=1; skip=any;;
# no-arg options
--version|-h|--help|-n|--nostdin|-a|--all|-q|--quiet|\
-v|--verbose|-d|--debug) ;;
Expand All @@ -34,7 +67,12 @@ _clush()
# options with = included in word
--*=*) ;;
-*) skip=any;;
*) return;; # was non-option
*)
# likely non-option, in copy mode options like -w can come
# later so just skip, otherwise likely start of command
[ "$mode" = copy ] && continue
_clush_command_or_file
return;;
esac
done

Expand All @@ -54,6 +92,7 @@ _clush()
if [ "$prev" = "-w" ]; then
compopts="@*" # include all nodes
fi
# shellcheck disable=SC2086 ## $compopts expanded on purpose
options="$(cluset ${groupsource:+-s "$groupsource"} --completion $compopts)"
if [ -n "$cleangroup" ]; then
options=${options//@"$groupsource":/@}
Expand All @@ -75,17 +114,28 @@ _clush()
;;
# no-arg options
--version|-h|--help|-n|--nostdin|-a|--all|-q|--quiet|\
-v|--verbose|-d|--debug) ;;
# any other option: just ignore.
-v|--verbose|-d|--debug|-c|--copy|--rcopy) ;;
# any other option: ignore next word (likely argument)
-*)
return;;
esac
# get all options from help text... not 100% accurate but good enough.
[ -n "$options" ] || options="$(clush --help | grep -oP -- '(?<=[ \t])(-[a-z]|--[^= \t]*)')"
# new option or no option:
if [ -z "$options" ]; then
case "$cur" in
-*)
# starts with dash - get all options from help text...
options="$(clush --help | grep -oP -- '(?<=[ \t])(-[a-z]|--[^= \t]*)')"
;;
*)
# otherwise complete command or file if appropriate and stop here
_clush_command_or_file
return
esac
fi

# append space for everything that doesn't end in `:` (likely a groupsource)
mapfile -t COMPREPLY < <(compgen -W "$options" -- "$cur" | sed -e 's/[^:]$/& /')
# remove the prefix from COMPREPLY if $cur contains colons and
# COMP_WORDBREAKS splits on colons...
__ltrim_colon_completions "$cur"
} && complete -o nospace -F _clush ${BASH_SOURCE##*/}
} && complete -o nospace -F _clush "${BASH_SOURCE##*/}"
Loading