1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#autoload
# This completer function is intended to be used as the first completer
# function and allows one to say more explicitly when and how the word
# from the line should be expanded than expand-or-complete.
# This function will allow other completer functions to be called if
# the expansions done produce no result or do not change the original
# word from the line.
#
# Configuration keys:
#
# expand_substitute
# If this is unset or set to the empty string, the code will first
# try to expand all substitutions in the string (such as $(...) and
# ${...}). If this is set to an non-empty string it should be
# an expression usable inside a $[...] arithmetical expression.
# In this case, expansion of substitutions will be done if the
# expression evaluates to `1'. For example, with
#
# compconf expand_substitute='NUMERIC != 1'
#
# substitution will be performed only if given an explicit numeric
# argument other than `1', as by typing ESC 2 TAB.
#
# expand_glob
# If this is unset or set to an empty string, globbing will be
# attempted on the word resulting from substitution or the
# original string. The values accepted for this key are the same
# as for expand_substitute.
#
# expand_menu
# If this is unset or set to the empty string, the words resulting
# from expansion (if any) will simply be inserted in the ommand line,
# replacing the original string. However, if this key is set to an
# non-empty string, the user can cycle through the expansion as in
# a menucompletion. Unless the value contains the sub-string `only',
# the user will still be offered all expansions at once as one of
# the strings to insert in the command line. Also, if the value
# contains the sub-string `last', the string with all expansion will
# be offered first, whereas normally it is offered as the last string
# to insert. Finally, if the value contains the sub-string `sort',
# the expansions will be sorted alphabetically, normally they are
# kept in the order the expansion produced them in.
#
# expand_original
# If this is set to an non-empty string, the original string from the
# line will be included in the list of strings the user can cycle
# through as in a menucompletion. If the value contains the sub-string
# `last', the original string will appear as the last string, with
# other values it is inserted as the first one (so that the command
# line does not change immediatly).
#
# expand_prompt
# This may be set to a string that should be displayed before the
# possible expansions. This is given to the -X option and thus may
# contain the control sequences `%n', `%B', etc. Also, the sequence
# `%o' in this string will be replaced by the original string.
local exp word="$PREFIX$SUFFIX" group=-V
# Do this only for the first global matcher.
[[ "$compstate[matcher]" -le 1 ]] || return 1
# In exp we will collect the expansion.
exp=("$word")
# First try substitution. That weird thing spanning multiple lines
# changes quoted spaces, tabs, and newlines into spaces.
[[ -z "$compconfig[expand_substitute]" ||
"${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] &&
exp=( "${(e)exp//\\[
]/ }" )
# If the array is empty, store the original string again.
[[ -z "$exp" ]] && exp=("$word")
# Now try globbing.
[[ -z "$compconfig[expand_glob]" ||
"${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] &&
exp=( ${~exp}(N) )
# If we don't have any expansions or only one and that is the same
# as the original string, we let other completers run.
[[ $#exp -eq 0 ||
( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1
# We have expansions, should we menucomplete them?
if [[ -z "$compconfig[expand_menu]" ]]; then
# No, so if the user only wants a list, we add the strings
# separately. Otherwise we add the whole array as one string,
# probably also adding the original string.
if [[ -z "$compstate[insert]" ]]; then
compadd -U -V _expand -Q - "$exp[@]"
else
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" != *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
compadd -UQ -V _expand - "$exp"
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" = *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
compstate[insert]=menu
fi
else
# Sorting? We just use a different group type then.
[[ "$compconfig[expand_menu]" = *sort* ]] && group=-J
# Now add the expansion string, probably also adding the original
# and/or the string containing all expanded string.
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" != *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
[[ "$compconfig[expand_menu]" = *last* &&
"$compconfig[expand_menu]" != *only* ]] &&
compadd -UnQ -V _expand_all - "$exp"
if [[ -z "$compconfig[expand_prompt]" ]]; then
compadd -UQ $group _expand - "$exp[@]"
else
compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
$group _expand - "$exp[@]"
fi
[[ "$compconfig[expand_menu]" != *last* &&
"$compconfig[expand_menu]" != *only* ]] &&
compadd -UnQ -V _expand_all - "$exp"
[[ -n "$compconfig[expand_original]" &&
"$compconfig[expand_original]" = *last* ]] &&
compadd -UnQ -V _expand_original - "$word"
compstate[insert]=menu
fi
return 0
|