Skip to content

Commit 83a7ab1

Browse files
committed
Improved bash completion.
* Now parses help instead of embedding fixed strings.x * Provides relevant specific option completion for --type, color* & file completion * Prevents opts after '--' * No longer completes non-existent commands with have
1 parent 862687f commit 83a7ab1

File tree

1 file changed

+93
-51
lines changed

1 file changed

+93
-51
lines changed

dev/generate-completion-scripts.pl

Lines changed: 93 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -99,65 +99,107 @@
9999
my %IS_AN_ALIAS = map { $_ => 1 } map { @$_ } values %OPTION_ALIASES;
100100

101101
my $BASH_TEMPLATE = <<'END_TEMPLATE';
102-
declare -g -a _ack_options
103-
declare -g -a _ack_types=()
102+
_ack() {
103+
local cur prev prog split=false
104+
cur=$(_get_cword "=")
105+
prev="${COMP_WORDS[COMP_CWORD-1]}"
106+
prog="${COMP_WORDS[0]}"
107+
COMPREPLY=()
104108
105-
_ack_options=(
106-
[% FOREACH option IN options -%]
107-
"[% option -%]" \
108-
[% END -%]
109-
)
110-
111-
function __setup_ack() {
112-
local type
113-
114-
while read LINE; do
115-
case $LINE in
116-
--*)
117-
type="${LINE%% *}"
118-
type=${type/--\[no\]/}
119-
_ack_options[ ${#_ack_options[@]} ]="--$type"
120-
_ack_options[ ${#_ack_options[@]} ]="--no$type"
121-
_ack_types[ ${#_ack_types[@]} ]="$type"
122-
;;
123-
esac
124-
done < <(ack --help-types)
125-
}
126-
__setup_ack
127-
unset -f __setup_ack
109+
# Once user writes '--', just file completion after PATTERN
110+
[ "$prev" = "--" ] && return 0
111+
for word in ${COMP_WORDS[@]}; do
112+
[ "$word" = "$prev" ] && break
113+
[ "$word" = "--" ] && _filedir && return 0
114+
done
128115
129-
function _ack_complete() {
130-
local current_word
131-
local pattern
132-
133-
current_word=${COMP_WORDS[$COMP_CWORD]}
134-
135-
if [[ "$current_word" == -* ]]; then
136-
pattern="${current_word}*"
137-
for option in ${_ack_options[@]}; do
138-
if [[ "$option" == $pattern ]]; then
139-
COMPREPLY[ ${#COMPREPLY[@]} ]=$option
116+
local opts types
117+
if [ "${__COMP_CACHE_ACK}x" = "x" ]; then
118+
for i in $("$prog" --help); do
119+
i=${i%%=*}
120+
if [ "${i:0:6}" = '--[no]' ]; then
121+
i="${i#--\[no\]}"
122+
opts="$opts --no$i --$i"
123+
elif [[ "$i" =~ ^-[a-zA-Z0-9?-]+,? ]]; then
124+
opts="$opts ${i//[\[.,\'\"]}"
125+
fi
126+
done
127+
for t in $("$prog" --help-types); do
128+
if [ "${t:0:6}" = '--[no]' ]; then
129+
t="${t#--\[no\]}"
130+
opts="$opts --no$t --$t"
131+
types="$types no$t $t"
140132
fi
141133
done
134+
__COMP_CACHE_ACK=( "$opts" "$types" )
135+
export __COMP_CACHE_ACK
142136
else
143-
local previous_word
144-
previous_word=${COMP_WORDS[$(( $COMP_CWORD - 1 ))]}
145-
if [[ "$previous_word" == "=" ]]; then
146-
previous_word=${COMP_WORDS[$(( $COMP_CWORD - 2 ))]}
147-
fi
148-
149-
if [ "$previous_word" == '--type' -o "$previous_word" == '--notype' ]; then
150-
pattern="${current_word}*"
151-
for type in ${_ack_types[@]}; do
152-
if [[ "$type" == $pattern ]]; then
153-
COMPREPLY[ ${#COMPREPLY[@]} ]=$type
154-
fi
155-
done
156-
fi
137+
opts="${__COMP_CACHE_ACK[0]}"
138+
types="${__COMP_CACHE_ACK[1]}"
157139
fi
140+
141+
_split_longopt && split=true
142+
143+
case "${prev}" in
144+
# directory completion
145+
--ignore-dir*)
146+
_filedir -d
147+
return 0
148+
;;
149+
# file completion
150+
--ackrc|--files-from)
151+
_filedir
152+
return 0
153+
;;
154+
# command completion
155+
--pager)
156+
COMPREPLY=( $(compgen -c -- "${cur}") )
157+
return 0
158+
;;
159+
# search type completion
160+
--type)
161+
COMPREPLY=( $(compgen -W "${types}" -- "${cur}") )
162+
return 0
163+
;;
164+
# color completion
165+
--color-*)
166+
local colors="
167+
black on_black
168+
blue on_blue
169+
cyan on_cyan
170+
green on_green
171+
magenta on_magenta
172+
red on_red
173+
white on_white
174+
yellow on_yellow
175+
"
176+
COMPREPLY=( $(compgen -W "${colors}" -- "${cur}") )
177+
return 0
178+
;;
179+
# require args, no completion
180+
-[ABCGgm]|--*context|--color|--colour|--ignore-file|\
181+
--lines|--match|--max-count|--output|--type-*)
182+
return 0
183+
;;
184+
esac
185+
186+
$split && return 0
187+
188+
case "${cur}" in
189+
-*)
190+
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
191+
return 0
192+
;;
193+
*)
194+
_filedir
195+
return 0
196+
;;
197+
esac
158198
}
159199
160-
complete -o default -F _ack_complete ack ack2 ack-grep
200+
for i in "ack" "ack2" "ack-grep" "ack-standalone"; do
201+
have "$i" && complete -F _ack ${nospace} "$i"
202+
done
161203
END_TEMPLATE
162204

163205
my $ZSH_TEMPLATE = <<'END_TEMPLATE';

0 commit comments

Comments
 (0)