mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-05-28 10:56:08 +02:00
44274: allow finer control of completion match soring with compadd's -o option
This commit is contained in:
parent
5200637bda
commit
cd6fd2b0a3
16
ChangeLog
16
ChangeLog
|
@ -1,5 +1,21 @@
|
|||
2019-05-07 Oliver Kiddle <okiddle@yahoo.co.uk>
|
||||
|
||||
* 44274: Completion/Base/Core/_description,
|
||||
Completion/Base/Utility/_describe, Completion/Base/Utility/_guard,
|
||||
Completion/Base/Utility/_multi_parts,
|
||||
Completion/Base/Utility/_sep_parts,
|
||||
Completion/Base/Utility/_sequence, Completion/Zsh/Command/_compadd,
|
||||
Completion/Darwin/Type/_mac_files_for_application,
|
||||
Completion/Redhat/Command/_yum, Completion/Unix/Command/_git,
|
||||
Completion/Unix/Type/_canonical_paths,
|
||||
Completion/Unix/Type/_baudrates, Completion/Unix/Type/_files,
|
||||
Completion/Unix/Type/_list_files, Completion/Unix/Type/_path_files,
|
||||
Completion/Zsh/Type/_file_descriptors,
|
||||
Doc/Zsh/compsys.yo, Doc/Zsh/compwid.yo, NEWS,
|
||||
Src/Zle/comp.h, Src/Zle/compcore.c, Src/Zle/complete.c:
|
||||
allow finer control of completion match soring with
|
||||
arguments to compadd's -o option
|
||||
|
||||
* Gautam Iyer: gitlab !6: Completion/Unix/Command/_rclone:
|
||||
Rudimentary rclone completion
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#autoload
|
||||
|
||||
local name gropt nopt xopt format gname hidden hide match opts tag sort
|
||||
local name nopt xopt format gname hidden hide match opts tag
|
||||
local -a gropt sort
|
||||
|
||||
opts=()
|
||||
|
||||
gropt=(-J)
|
||||
xopt=(-X)
|
||||
nopt=()
|
||||
zparseopts -K -D -a nopt 1 2 V=gropt J=gropt x=xopt
|
||||
zparseopts -K -D -a nopt 1 2 V=gropt J x=xopt
|
||||
|
||||
3="${${3##[[:blank:]]#}%%[[:blank:]]#}"
|
||||
[[ -n "$3" ]] && _lastdescr=( "$_lastdescr[@]" "$3" )
|
||||
|
@ -33,15 +33,19 @@ zstyle -s ":completion:${curcontext}:$1" matcher match &&
|
|||
|
||||
# Use sort style, but ignore `menu' value to help _expand.
|
||||
# Also don't override explicit use of -V.
|
||||
if { zstyle -s ":completion:${curcontext}:$1" sort sort ||
|
||||
zstyle -s ":completion:${curcontext}:" sort sort; } &&
|
||||
[[ "$gropt" = -J && $sort != menu ]]; then
|
||||
if [[ "$sort" = (yes|true|1|on) ]]; then
|
||||
gropt=(-J)
|
||||
else
|
||||
gropt=(-V)
|
||||
if [[ -z "$gropt" ]]; then
|
||||
if zstyle -a ":completion:${curcontext}:$1" sort sort ||
|
||||
zstyle -a ":completion:${curcontext}:" sort sort
|
||||
then
|
||||
if [[ -z "${(@)sort:#(match|numeric|reverse)}" ]]; then
|
||||
gropt=( -o ${(j.,.)sort} )
|
||||
elif [[ "$sort" != (yes|true|1|on|menu) ]]; then
|
||||
gropt=( -o nosort )
|
||||
fi
|
||||
fi
|
||||
else
|
||||
gropt=( -o nosort )
|
||||
fi
|
||||
|
||||
if [[ -z "$_comp_no_ignore" ]]; then
|
||||
zstyle -a ":completion:${curcontext}:$1" ignored-patterns _comp_ignore ||
|
||||
|
@ -79,15 +83,15 @@ fi
|
|||
|
||||
if [[ -n "$gname" ]]; then
|
||||
if [[ -n "$format" ]]; then
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt" "$gname" "$xopt" "$format"
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt[@]" -J "$gname" "$xopt" "$format"
|
||||
else
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt" "$gname"
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt[@]" -J "$gname"
|
||||
fi
|
||||
else
|
||||
if [[ -n "$format" ]]; then
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt" -default- "$xopt" "$format"
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt[@]" -J -default- "$xopt" "$format"
|
||||
else
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt" -default-
|
||||
set -A "$name" "$opts[@]" "$nopt[@]" "$gropt[@]" -J -default-
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -108,10 +108,10 @@ while _tags; do
|
|||
fi
|
||||
|
||||
if [[ -n $_mats ]]; then
|
||||
compadd "$_opts[@]" "${(@)_expl:/-J/-2V}" -D $_strs -O $_mats - \
|
||||
compadd "$_opts[@]" -2 -o nosort "${_expl[@]}" -D $_strs -O $_mats - \
|
||||
"${(@)${(@M)${(@P)_mats}##([^:\\]|\\?)##}//\\(#b)(?)/$match[1]}"
|
||||
else
|
||||
compadd "$_opts[@]" "${(@)_expl:/-J/-2V}" -D $_strs - \
|
||||
compadd "$_opts[@]" -2 -o nosort "${_expl[@]}" -D $_strs - \
|
||||
"${(@)${(@M)${(@P)_strs}##([^:\\]|\\?)##}//\\(#b)(?)/$match[1]}"
|
||||
fi
|
||||
done
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
local garbage
|
||||
|
||||
zparseopts -K -D -a garbage M: J: V: 1 2 n F: X:
|
||||
zparseopts -K -D -a garbage M+: J+: V+: 1 2 o+: n F: X+:
|
||||
|
||||
[[ "$PREFIX$SUFFIX" != $~1 ]] && return 1
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ typeset -U tmp1 matches
|
|||
# Get the options.
|
||||
|
||||
zparseopts -D -a sopts \
|
||||
'J+:=group' 'V+:=group' 'X+:=expl' 'P:=opts' 'F:=opts' \
|
||||
S: r: R: q 1 2 n f 'M+:=matcher' 'i=imm'
|
||||
'J+:=group' 'V+:=group' 'x+:=expl' 'X+:=expl' 'P:=opts' 'F:=opts' \
|
||||
S: r: R: q 1 2 o+: n f 'M+:=matcher' 'i=imm'
|
||||
|
||||
sopts=( "$sopts[@]" "$opts[@]" )
|
||||
if (( $#matcher )); then
|
||||
|
|
|
@ -22,8 +22,8 @@ local matchflags opt group expl nm=$compstate[nmatches] opre osuf opts matcher
|
|||
|
||||
# Get the options.
|
||||
|
||||
zparseopts -D -a opts \
|
||||
'J+:=group' 'V+:=group' P: F: S: r: R: q 1 2 n 'X+:=expl' 'M+:=matcher'
|
||||
zparseopts -D -a opts 'J+:=group' 'V+:=group' P: F: S: r: R: q 1 2 o+: n \
|
||||
'x+:=expl' 'X+:=expl' 'M+:=matcher'
|
||||
|
||||
# Get the string from the line.
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
local curcontext="$curcontext" nm="$compstate[nmatches]" pre qsep nosep minus
|
||||
local -a sep num pref suf end uniq dedup
|
||||
|
||||
zparseopts -D -a opts s:=sep n:=num p:=pref i:=pref P:=pref I:=suf S:=suf q=suf r:=suf R:=suf C:=cont d=uniq M: J: X: x:
|
||||
zparseopts -D -a opts s:=sep n:=num p:=pref i:=pref P:=pref I:=suf S:=suf \
|
||||
q=suf r:=suf R:=suf C:=cont d=uniq M+: J+: V+: 1 2 o+: X+: x+:
|
||||
(( $#cont )) && curcontext="${curcontext%:*}:$cont[2]"
|
||||
(( $#sep )) || sep[2]=,
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ _mac_parse_info_plist() {
|
|||
# Try to complete files for the specified application.
|
||||
_mac_files_for_application() {
|
||||
local -a opts
|
||||
zparseopts -D -a opts q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
|
||||
zparseopts -D -a opts q n 1 2 o+: P: S: r: R: W: x+: X+: M+: F: J+: V+:
|
||||
|
||||
local app_path
|
||||
_retrieve_mac_apps
|
||||
|
|
|
@ -212,7 +212,7 @@ _yum_ids() {
|
|||
# `${(@)@[...]}' selects a subrange from $@
|
||||
# `${(@)@[1,-2]}' are all except the last argument
|
||||
# `$@[$#]' is the last argument, e.g. the first suggestable ID
|
||||
compadd "${(@)@[1,-2]:/-J/-V}" -M "B:0=" {$@[$#]..$maxid}
|
||||
compadd "${(@)@[1,-2]}" -o numeric -M "B:0=" {$@[$#]..$maxid}
|
||||
}
|
||||
|
||||
_yum_ranges() {
|
||||
|
|
|
@ -5688,7 +5688,7 @@ __git_ignore_line () {
|
|||
__git_ignore_line_inside_arguments () {
|
||||
declare -a compadd_opts
|
||||
|
||||
zparseopts -D -E -a compadd_opts V: J: 1 2 n f X: M: P: S: r: R: q F:
|
||||
zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F:
|
||||
|
||||
__git_ignore_line $* $compadd_opts
|
||||
}
|
||||
|
@ -6160,7 +6160,7 @@ __git_ref_fields () {
|
|||
local match mbegin mend
|
||||
local -a cfields fields append opts all
|
||||
|
||||
zparseopts -D -E -a opts x: X: J: V: a=all
|
||||
zparseopts -D -E -a opts M+: x+: X+: J+: V+: o+: 1 2 a=all
|
||||
|
||||
if compset -P 1 '(#b)(*):'; then
|
||||
case $match[1] in
|
||||
|
@ -6731,7 +6731,7 @@ __git_tags_of_type () {
|
|||
tags=(${${(M)${(f)"$(_call_program ${(q)type}-tag-refs "git for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#$type(tag|) *}#$type(tag|) refs/tags/})
|
||||
__git_command_successful $pipestatus || return 1
|
||||
|
||||
_wanted $type-tags expl "$type tag" compadd -M 'r:|/=* r:|=*' "$@" -a - tags
|
||||
_wanted $type-tags expl "$type tag" compadd -M 'r:|/=* r:|=*' "$@" -o numeric -a - tags
|
||||
}
|
||||
|
||||
# Reference Argument Types
|
||||
|
@ -6826,7 +6826,7 @@ __git_files_relative () {
|
|||
__git_files () {
|
||||
local compadd_opts opts tag description gitcdup gitprefix files expl
|
||||
|
||||
zparseopts -D -E -a compadd_opts V: J: 1 2 n f X: M: P: S: r: R: q F:
|
||||
zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F:
|
||||
zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed x+: --exclude+:
|
||||
tag=$1 description=$2; shift 2
|
||||
|
||||
|
@ -6957,7 +6957,7 @@ __git_tree_files () {
|
|||
shift
|
||||
fi
|
||||
|
||||
zparseopts -D -E -a compadd_opts V: J: 1 2 n f X: M: P: S: r: R: q F:
|
||||
zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F:
|
||||
|
||||
[[ "$1" == */ ]] && Path="$1" || Path="${1:h}/"
|
||||
shift
|
||||
|
@ -7037,7 +7037,7 @@ __git_any_repositories_or_references () {
|
|||
__git_guard () {
|
||||
declare -A opts
|
||||
|
||||
zparseopts -K -D -A opts M: J: V: 1 2 n F: X:
|
||||
zparseopts -K -D -A opts M+: J+: V+: 1 2 o+: n F: x+: X+:
|
||||
|
||||
[[ "$PREFIX$SUFFIX" != $~1 ]] && return 1
|
||||
|
||||
|
@ -7075,7 +7075,7 @@ __git_guard_diff-stat-width () {
|
|||
__git_guard_number () {
|
||||
declare -A opts
|
||||
|
||||
zparseopts -K -D -A opts M: J: V: 1 2 n F: X:
|
||||
zparseopts -K -D -A opts M+: J+: V+: 1 2 o+: n F: x+: X+:
|
||||
|
||||
_guard '[[:digit:]]#' ${1:-number}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@ if (( ${+opts[-f]} )); then
|
|||
done
|
||||
fi
|
||||
|
||||
# -1V removes dupes (which there shouldn't be) and otherwise leaves the
|
||||
# order in the $rates array intact.
|
||||
_description -1V baud-rates expl 'baud rate'
|
||||
compadd "${(@)argv/#-J/-V}" "$expl[@]" -- "${rates[@]}"
|
||||
# -1 removes dupes (which there shouldn't be)
|
||||
_description -1 -o numeric baud-rates expl 'baud rate'
|
||||
compadd "${argv[@]}" "$expl[@]" -- "${rates[@]}"
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
# (relative path when an absolute path is given, and vice versa; when ..'s are
|
||||
# present in the word to be completed, and some paths got from symlinks).
|
||||
|
||||
# Usage: _canonical_paths [-A var] [-N] [-MJV12nfX] tag desc [paths...]
|
||||
# Usage: _canonical_paths [-A var] [-N] [-MJV12onfX] tag desc [paths...]
|
||||
|
||||
# -A, if specified, takes the paths from the array variable specified. Paths
|
||||
# can also be specified on the command line as shown above. -N, if specified,
|
||||
# prevents canonicalizing the paths given before using them for completion, in
|
||||
# case they are already so. `tag' and `desc' arguments are well, obvious :) In
|
||||
# addition, the options -M, -J, -V, -1, -2, -n, -F, -X are passed to compadd.
|
||||
# addition, the options -M, -J, -V, -1, -2, -o, -n, -F, -x, -X are passed to
|
||||
# compadd.
|
||||
|
||||
_canonical_paths_add_paths () {
|
||||
# origpref = original prefix
|
||||
|
@ -59,7 +60,7 @@ _canonical_paths() {
|
|||
local __index
|
||||
typeset -a __gopts __opts
|
||||
|
||||
zparseopts -D -a __gopts M: J: V: 1 2 n F: X: A:=__opts N=__opts
|
||||
zparseopts -D -a __gopts M+: J+: V+: o+: 1 2 n F: x+: X+: A:=__opts N=__opts
|
||||
|
||||
: ${1:=canonical-paths} ${2:=path}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ local opts tmp glob pat pats expl tag i def descr end ign tried
|
|||
local type sdef ignvars ignvar prepath oprefix rfiles rfile
|
||||
|
||||
zparseopts -a opts \
|
||||
'/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+:
|
||||
'/=tmp' 'f=tmp' 'g+:-=tmp' q n 1 2 P: S: r: R: W: x+: X+: M+: F: J+: V+: o+:
|
||||
|
||||
type="${(@j::M)${(@)tmp#-}#?}"
|
||||
if (( $tmp[(I)-g*] )); then
|
||||
|
|
|
@ -64,6 +64,6 @@ for f in ${(PQ)1}; do
|
|||
${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[mtime] $f")
|
||||
done
|
||||
|
||||
(( ${#listfiles} )) && listopts=(-d listfiles -l -o)
|
||||
(( ${#listfiles} )) && listopts=(-d listfiles -l -o match)
|
||||
|
||||
return 0
|
||||
|
|
|
@ -59,7 +59,7 @@ exppaths=()
|
|||
zparseopts -a mopts \
|
||||
'P:=pfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
|
||||
'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
|
||||
J+: V+: X+: 1 2 n 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
|
||||
J+: V+: x+: X+: 1 2 o+: n 'f=tmp1' '/=tmp1' 'g+:-=tmp1'
|
||||
|
||||
sopt="-${(@j::M)${(@)tmp1#-}#?}"
|
||||
(( $tmp1[(I)-[/g]*] )) && haspats=yes
|
||||
|
@ -168,7 +168,7 @@ if zstyle -s ":completion:${curcontext}:" file-sort tmp1; then
|
|||
if [[ "$sort" = on ]]; then
|
||||
sort=
|
||||
else
|
||||
mopts=( "${(@)mopts/#-J/-V}" )
|
||||
mopts=( -o nosort "${mopts[@]}" )
|
||||
|
||||
tmp2=()
|
||||
for tmp1 in "$pats[@]"; do
|
||||
|
|
|
@ -14,9 +14,13 @@ _arguments -C -s -S -A "-*" \
|
|||
'(-a)-k[matches are keys of specified associative arrays]' \
|
||||
'-d+[specify display strings]:array:_parameters -g "*array*"' \
|
||||
'-l[list display strings one per line, not in columns]' \
|
||||
'-o[order matches by match string not by display string]' \
|
||||
'(-1 -E)-J+[specify match group which will be sorted]:group' \
|
||||
'-V+[specify pre-ordered match group]:group' \
|
||||
'-o[specify order for matches by match string not by display string]:: : _values -s , order
|
||||
"match[order by match not by display string]"
|
||||
"nosort[matches are pre-ordered]"
|
||||
"numeric[order numerically]"
|
||||
"reverse[order backwards]"' \
|
||||
'(-1 -E)-J+[specify match group]:group' \
|
||||
'!-V+:group' \
|
||||
'(-J -E)-1[remove only consecutive duplicates from group]' \
|
||||
'-2[preserve all duplicates]' \
|
||||
'(-x)-X[specify explanation]:explanation' \
|
||||
|
@ -45,7 +49,7 @@ if [[ -n $state ]]; then
|
|||
elif (( $+opt_args[-k] )); then
|
||||
_parameters -g "*assoc*" && ret=0
|
||||
else
|
||||
_message -e candidate candidates
|
||||
_message -e candidates candidate
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -56,4 +56,4 @@ fi
|
|||
fds=( 0 1 2 $fds )
|
||||
|
||||
_description -V file-descriptors expl 'file descriptor'
|
||||
compadd $disp "${@/-J/-V}" "$expl[@]" -a fds
|
||||
compadd $disp -o nosort "$@" "$expl[@]" -a fds
|
||||
|
|
|
@ -2534,20 +2534,20 @@ is started, making it easy to select either of them.
|
|||
)
|
||||
kindex(sort, completion style)
|
||||
item(tt(sort))(
|
||||
Many completion widgets call tt(_description) at some point which
|
||||
decides whether the matches are added sorted or unsorted (often
|
||||
indirectly via tt(_wanted) or tt(_requested)). This style can be set
|
||||
explicitly to one of the usual `true' or `false' values as an override.
|
||||
If it is not set for the context, the standard behaviour of the
|
||||
calling widget is used.
|
||||
This allows the standard ordering of matches to be overridden.
|
||||
|
||||
If its value is `tt(true)' or `tt(false)', sorting is enabled or disabled.
|
||||
Additionally the values associated with the `tt(-o)' option to tt(compadd) can
|
||||
also be listed: tt(match), tt(nosort), tt(numeric), tt(reverse). If it is not
|
||||
set for the context, the standard behaviour of the calling widget is used.
|
||||
|
||||
The style is tested first against the full context including the tag, and
|
||||
if that fails to produce a value against the context without the tag.
|
||||
|
||||
If the calling widget explicitly requests unsorted matches, this is usually
|
||||
honoured. However, the default (unsorted) behaviour of completion
|
||||
for the command history may be overridden by setting the style to
|
||||
`true'.
|
||||
In many cases where a calling widget explicitly selects a particular ordering
|
||||
in lieu of the default, a value of `tt(true)' is not honoured. An example of
|
||||
where this is not the case is for command history where the default of sorting
|
||||
matches chronologically may be overridden by setting the style to `true'.
|
||||
|
||||
In the tt(_expand) completer, if it is set to
|
||||
`true', the expansions generated will always be sorted. If it is set
|
||||
|
@ -4404,11 +4404,11 @@ convention is not enforced). The description for the corresponding set
|
|||
of matches is passed to the function in var(descr).
|
||||
|
||||
The styles tested are: tt(format), tt(hidden), tt(matcher),
|
||||
tt(ignored-patterns) and tt(group-name). The tt(format) style is first
|
||||
tested for the given var(tag) and then for the tt(descriptions) tag if
|
||||
no value was found, while the remainder are only tested for the tag
|
||||
given as the first argument. The function also calls tt(_setup)
|
||||
which tests some more styles.
|
||||
tt(ignore-line), tt(ignored-patterns), tt(group-name) and tt(sort).
|
||||
The tt(format) style is first tested for the given var(tag) and then for
|
||||
the tt(descriptions) tag if no value was found, while the remainder are
|
||||
only tested for the tag given as the first argument. The function also
|
||||
calls tt(_setup) which tests some more styles.
|
||||
|
||||
The string returned by the tt(format) style (if any) will be modified so
|
||||
that the sequence `tt(%d)' is replaced by the var(descr) given as the third
|
||||
|
|
|
@ -446,12 +446,13 @@ startitem()
|
|||
findex(compadd)
|
||||
cindex(completion widgets, adding specified matches)
|
||||
redef(SPACES)(0)(tt(ifztexi(NOTRANS(@ @ @ @ @ @ @ @ ))ifnztexi( )))
|
||||
xitem(tt(compadd )[ tt(-akqQfenUlo12C) ] [ tt(-F) var(array) ])
|
||||
xitem(tt(compadd )[ tt(-akqQfenUl12C) ] [ tt(-F) var(array) ])
|
||||
xitem(SPACES()[tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
|
||||
xitem(SPACES()[tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
|
||||
xitem(SPACES()[tt(-i) var(ignored-prefix) ] [ tt(-I) var(ignored-suffix) ])
|
||||
xitem(SPACES()[tt(-W) var(file-prefix) ] [ tt(-d) var(array) ])
|
||||
xitem(SPACES()[tt(-J) var(name) ] [ tt(-V) var(name) ] [ tt(-X) var(explanation) ] [ tt(-x) var(message) ])
|
||||
xitem(SPACES()[tt(-J) var(group-name) ] [ tt(-X) var(explanation) ] [ tt(-x) var(message) ])
|
||||
xitem(SPACES()[tt(-V) var(group-name) ] [ tt(-o) [ var(order) ] ])
|
||||
xitem(SPACES()[tt(-r) var(remove-chars) ] [ tt(-R) var(remove-func) ])
|
||||
xitem(SPACES()[tt(-D) var(array) ] [ tt(-O) var(array) ] [ tt(-A) var(array) ])
|
||||
xitem(SPACES()[tt(-E) var(number) ])
|
||||
|
@ -540,18 +541,40 @@ This option only has an effect if used together with the tt(-d)
|
|||
option. If it is given, the display strings are listed one per line,
|
||||
not arrayed in columns.
|
||||
)
|
||||
item(tt(-o))(
|
||||
This option only has an effect if used together with the tt(-d)
|
||||
option. If it is given, the order of the output is determined by the
|
||||
match strings; otherwise it is determined by the display strings
|
||||
(i.e. the strings given by the tt(-d) option).
|
||||
item(tt(-o) [ var(order) ])(
|
||||
This controls the order in which matches are sorted. var(order) is a
|
||||
comma-separated list comprising the following possible values. These values
|
||||
can be abbreviated to their initial two or three characters. Note that the
|
||||
order forms part of the group name space so matches with different orderings
|
||||
will not be in the same group.
|
||||
|
||||
startitem()
|
||||
item(tt(match))(
|
||||
If given, the order of the output is determined by the match strings;
|
||||
otherwise it is determined by the display strings (i.e. the strings given
|
||||
by the tt(-d) option). This is the default if `tt(-o)' is specified but
|
||||
the var(order) argument is omitted.
|
||||
)
|
||||
item(tt(-J) var(name))(
|
||||
item(tt(nosort))(
|
||||
This specifies that the matches are pre-sorted and their order should be
|
||||
preserved. This value only makes sense alone and cannot be combined with any
|
||||
others.
|
||||
)
|
||||
item(tt(numeric))(
|
||||
If the matches include numbers, sort them numerically rather than
|
||||
lexicographically.
|
||||
)
|
||||
item(tt(reverse))(
|
||||
Arrange the matches backwards by reversing the sort ordering.
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
item(tt(-J) var(group-name))(
|
||||
Gives the name of the group of matches the words should be stored in.
|
||||
)
|
||||
item(tt(-V) var(name))(
|
||||
Like tt(-J) but naming an unsorted group. These are in a different name
|
||||
space than groups created with the tt(-J) flag.
|
||||
item(tt(-V) var(group-name))(
|
||||
Like tt(-J) but naming an unsorted group. This option is identical to
|
||||
the combination of tt(-J) and tt(-o nosort).
|
||||
)
|
||||
item(tt(-1))(
|
||||
If given together with the tt(-V) option, makes
|
||||
|
|
5
NEWS
5
NEWS
|
@ -21,6 +21,11 @@ functions may wish to familiarise themselves with `_normal -p` and
|
|||
The option CD_SILENT was added to suppress all output from cd (whether
|
||||
explicit or implicit with AUTO_CD). It is disabled by default.
|
||||
|
||||
The compadd builtin's -o option now takes an optional argument to
|
||||
specify the order of completion matches. This affects the display
|
||||
of candidate matches and the order in which they are selected when
|
||||
cycling between them using menu completion.
|
||||
|
||||
Changes from 5.6.2 to 5.7.1
|
||||
---------------------------
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ struct cmgroup {
|
|||
#define CGF_PACKED 32 /* LIST_PACKED for this group */
|
||||
#define CGF_ROWS 64 /* LIST_ROWS_FIRST for this group */
|
||||
#define CGF_FILES 128 /* contains file names */
|
||||
#define CGF_MATSORT 256 /* sort by match rather than by display string */
|
||||
#define CGF_NUMSORT 512 /* sort numerically */
|
||||
#define CGF_REVSORT 1024 /* sort in reverse */
|
||||
|
||||
/* This is the struct used to hold matches. */
|
||||
|
||||
|
@ -300,6 +303,9 @@ struct menuinfo {
|
|||
#define CAF_ARRAYS 32 /* compadd -a or -k: array/assoc parameter names */
|
||||
#define CAF_KEYS 64 /* compadd -k: assoc parameter names */
|
||||
#define CAF_ALL 128 /* compadd -C: _all_matches */
|
||||
#define CAF_MATSORT 256 /* compadd -o match: sort by match rather than by display string */
|
||||
#define CAF_NUMSORT 512 /* compadd -o numeric: sort numerically */
|
||||
#define CAF_REVSORT 1024 /* compadd -o numeric: sort in reverse */
|
||||
|
||||
/* Data for compadd and addmatches() */
|
||||
|
||||
|
|
|
@ -2080,6 +2080,9 @@ addmatches(Cadata dat, char **argv)
|
|||
|
||||
/* Select the group in which to store the matches. */
|
||||
gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT : 0) |
|
||||
((dat->aflags & CAF_MATSORT) ? CGF_MATSORT : 0) |
|
||||
((dat->aflags & CAF_NUMSORT) ? CGF_NUMSORT : 0) |
|
||||
((dat->aflags & CAF_REVSORT) ? CGF_REVSORT : 0) |
|
||||
((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
|
||||
((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0));
|
||||
if (dat->group) {
|
||||
|
@ -3034,8 +3037,9 @@ begcmgroup(char *n, int flags)
|
|||
HEAP_ERROR(p->heap_id);
|
||||
}
|
||||
#endif
|
||||
if (p->name &&
|
||||
flags == (p->flags & (CGF_NOSORT|CGF_UNIQALL|CGF_UNIQCON)) &&
|
||||
if (p->name && flags ==
|
||||
(p->flags & (CGF_NOSORT|CGF_UNIQALL|CGF_UNIQCON|
|
||||
CGF_MATSORT|CGF_NUMSORT|CGF_REVSORT)) &&
|
||||
!strcmp(n, p->name)) {
|
||||
mgroup = p;
|
||||
|
||||
|
@ -3118,32 +3122,35 @@ addexpl(int always)
|
|||
|
||||
/* The comparison function for matches (used for sorting). */
|
||||
|
||||
static int matchorder;
|
||||
|
||||
/**/
|
||||
static int
|
||||
matchcmp(Cmatch *a, Cmatch *b)
|
||||
{
|
||||
if ((*a)->disp && !((*a)->flags & CMF_MORDER)) {
|
||||
if ((*b)->disp) {
|
||||
if ((*a)->flags & CMF_DISPLINE) {
|
||||
if ((*b)->flags & CMF_DISPLINE)
|
||||
return strcmp((*a)->disp, (*b)->disp);
|
||||
else
|
||||
return -1;
|
||||
} else {
|
||||
if ((*b)->flags & CMF_DISPLINE)
|
||||
return 1;
|
||||
else
|
||||
return strcmp((*a)->disp, (*b)->disp);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if ((*b)->disp && !((*b)->flags & CMF_MORDER))
|
||||
return 1;
|
||||
const char *as, *bs;
|
||||
int cmp = !!(*b)->disp - !!(*a)->disp;
|
||||
int sortdir = (matchorder & CGF_REVSORT) ? -1 : 1;
|
||||
|
||||
return zstrcmp((*a)->str, (*b)->str, (SORTIT_IGNORING_BACKSLASHES|
|
||||
(isset(NUMERICGLOBSORT) ?
|
||||
SORTIT_NUMERICALLY : 0)));
|
||||
/* if match sorting selected or we have no display strings */
|
||||
if ((matchorder & CGF_MATSORT) || (!cmp && !(*a)->disp)) {
|
||||
as = (*a)->str;
|
||||
bs = (*b)->str;
|
||||
} else {
|
||||
if (cmp) /* matches with display strings come first */
|
||||
return cmp;
|
||||
|
||||
cmp = ((*b)->flags & CMF_DISPLINE) - ((*a)->flags & CMF_DISPLINE);
|
||||
if (cmp) /* sort one-per-line display strings first */
|
||||
return cmp;
|
||||
|
||||
as = (*a)->disp;
|
||||
bs = (*b)->disp;
|
||||
}
|
||||
|
||||
return sortdir * zstrcmp(as, bs, SORTIT_IGNORING_BACKSLASHES|
|
||||
((isset(NUMERICGLOBSORT) ||
|
||||
matchorder & CGF_NUMSORT) ? SORTIT_NUMERICALLY : 0));
|
||||
}
|
||||
|
||||
/* This tests whether two matches are equal (would produce the same
|
||||
|
@ -3205,6 +3212,7 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp)
|
|||
} else {
|
||||
if (!(flags & CGF_NOSORT)) {
|
||||
/* Now sort the array (it contains matches). */
|
||||
matchorder = flags;
|
||||
qsort((void *) rp, n, sizeof(Cmatch),
|
||||
(int (*) _((const void *, const void *)))matchcmp);
|
||||
|
||||
|
|
|
@ -558,12 +558,53 @@ parse_class(Cpattern p, char *iptr)
|
|||
return iptr;
|
||||
}
|
||||
|
||||
static struct { char *name; int abbrev; int oflag; } orderopts[] = {
|
||||
{ "nosort", 2, CAF_NOSORT },
|
||||
{ "match", 3, CAF_MATSORT },
|
||||
{ "numeric", 3, CAF_NUMSORT },
|
||||
{ "reverse", 3, CAF_REVSORT }
|
||||
};
|
||||
|
||||
/* Parse the option to compadd -o, if flags is non-NULL set it
|
||||
* returns -1 if the argument isn't a valid ordering, 0 otherwise */
|
||||
|
||||
/**/
|
||||
static int
|
||||
parse_ordering(const char *arg, int *flags)
|
||||
{
|
||||
int o, fl = 0;
|
||||
const char *next, *opt = arg;
|
||||
do {
|
||||
int found = 0;
|
||||
next = strchr(opt, ',');
|
||||
if (!next)
|
||||
next = opt + strlen(opt);
|
||||
|
||||
for (o = sizeof(orderopts)/sizeof(*orderopts) - 1; o >= 0 &&
|
||||
!found; --o)
|
||||
{
|
||||
if ((found = next - opt >= orderopts[o].abbrev &&
|
||||
!strncmp(orderopts[o].name, opt, next - opt)))
|
||||
fl |= orderopts[o].oflag;
|
||||
}
|
||||
if (!found) {
|
||||
if (flags) /* default to "match" */
|
||||
*flags = CAF_MATSORT;
|
||||
return -1;
|
||||
}
|
||||
} while (*next && ((opt = next + 1)));
|
||||
if (flags)
|
||||
*flags |= fl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
|
||||
{
|
||||
struct cadata dat;
|
||||
char *mstr = NULL; /* argument of -M options, accumulated */
|
||||
char *oarg = NULL; /* argument of -o option */
|
||||
int added; /* return value */
|
||||
Cmatcher match = NULL;
|
||||
|
||||
|
@ -587,6 +628,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
|
|||
}
|
||||
for (p = *argv + 1; *p; p++) {
|
||||
char *m = NULL; /* argument of -M option (this one only) */
|
||||
int order = 0; /* if -o found (argument to which is optional) */
|
||||
char **sp = NULL; /* the argument to an option should be copied
|
||||
to *sp. */
|
||||
const char *e; /* error message */
|
||||
|
@ -710,7 +752,11 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
|
|||
dat.flags |= CMF_DISPLINE;
|
||||
break;
|
||||
case 'o':
|
||||
dat.flags |= CMF_MORDER;
|
||||
/* we honour just the first -o option but need to skip
|
||||
* over a valid argument to subsequent -o options */
|
||||
order = oarg ? -1 : 1;
|
||||
sp = &oarg;
|
||||
/* no error string because argument is optional */
|
||||
break;
|
||||
case 'E':
|
||||
if (p[1]) {
|
||||
|
@ -741,15 +787,18 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
|
|||
if (sp) {
|
||||
if (p[1]) {
|
||||
/* Pasted argument: -Xfoo. */
|
||||
if (!*sp)
|
||||
if (!*sp) /* take first option only */
|
||||
*sp = p + 1;
|
||||
if (!order || !parse_ordering(oarg, order == 1 ? &dat.aflags : NULL))
|
||||
p += strlen(p+1);
|
||||
} else if (argv[1]) {
|
||||
/* Argument in a separate word: -X foo. */
|
||||
argv++;
|
||||
if (!*sp)
|
||||
*sp = *argv;
|
||||
} else {
|
||||
if (order && parse_ordering(oarg, order == 1 ? &dat.aflags : NULL))
|
||||
--argv;
|
||||
} else if (!order) {
|
||||
/* Missing argument: argv[N] == "-X", argv[N+1] == NULL. */
|
||||
zwarnnam(name, e, *p);
|
||||
zsfree(mstr);
|
||||
|
|
|
@ -138,6 +138,46 @@ F:regression test workers/31611
|
|||
>FI:{\|foo}
|
||||
>FI:{\~foo}
|
||||
|
||||
comptesteval "_tst() { compadd -onum,rev -J versions r1.10 r1.1 r1.2 r2.3 r2.34 }"
|
||||
comptest $'tst r\t'
|
||||
0:reverse numeric sorting of matches
|
||||
>line: {tst r}{}
|
||||
>NO:{r2.34}
|
||||
>NO:{r2.3}
|
||||
>NO:{r1.10}
|
||||
>NO:{r1.2}
|
||||
>NO:{r1.1}
|
||||
|
||||
comptesteval "_tst() { local expl; _wanted times expl time compadd -o match r1.10 r1.2 r2.3 r2.34 }"
|
||||
comptesteval "zstyle ':completion:*:tst:*' sort reverse numeric"
|
||||
comptest $'tst r\t'
|
||||
0:reverse numeric sorting of matches via a style
|
||||
>line: {tst r}{}
|
||||
>DESCRIPTION:{time}
|
||||
>NO:{r2.34}
|
||||
>NO:{r2.3}
|
||||
>NO:{r1.10}
|
||||
>NO:{r1.2}
|
||||
|
||||
comptesteval "_tst() { local disp=(a b c); compadd -o -J letters -d disp 3 2 1 }"
|
||||
comptest $'tst \t'
|
||||
0:sort in match rather than display name order
|
||||
>line: {tst }{}
|
||||
>NO:{c}
|
||||
>NO:{b}
|
||||
>NO:{a}
|
||||
|
||||
comptesteval "_tst() { local expl; _wanted times expl time compadd 3am 12pm 3pm 10pm }"
|
||||
comptesteval "zstyle ':completion:*:tst:*' sort false"
|
||||
comptest $'tst \t'
|
||||
0:sorting disabled via the sort style
|
||||
>line: {tst }{}
|
||||
>DESCRIPTION:{time}
|
||||
>NO:{3am}
|
||||
>NO:{12pm}
|
||||
>NO:{3pm}
|
||||
>NO:{10pm}
|
||||
|
||||
%clean
|
||||
|
||||
zmodload -ui zsh/zpty
|
||||
|
|
Loading…
Reference in New Issue