summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--Completion/BSD/Command/_ipfw4
-rw-r--r--Completion/Base/Core/_description8
-rw-r--r--Completion/Base/Utility/_numbers87
-rw-r--r--Completion/Linux/Command/_btrfs8
-rw-r--r--Completion/Unix/Command/_dd14
-rw-r--r--Completion/Unix/Command/_git6
-rw-r--r--Completion/Unix/Command/_head22
-rw-r--r--Completion/Unix/Command/_killall12
-rw-r--r--Completion/Unix/Command/_pv18
-rw-r--r--Completion/Unix/Command/_rclone10
-rw-r--r--Completion/Unix/Command/_rsync10
-rw-r--r--Completion/Unix/Command/_stdbuf6
-rw-r--r--Completion/Unix/Command/_tail22
-rw-r--r--Completion/Unix/Command/_timeout2
-rw-r--r--Completion/Unix/Command/_zfs20
-rw-r--r--Completion/X/Command/_xset4
-rw-r--r--Doc/Zsh/compsys.yo81
18 files changed, 258 insertions, 90 deletions
diff --git a/ChangeLog b/ChangeLog
index bb8b73085..d7b225d42 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2021-11-24 Oliver Kiddle <opk@zsh.org>
+
+ * 49597: Completion/Base/Core/_description, Doc/Zsh/compsys.yo,
+ Completion/Base/Utility/_numbers, Completion/BSD/Command/_ipfw,
+ Completion/Linux/Command/_btrfs, Completion/Unix/Command/_dd,
+ Completion/Unix/Command/_git, Completion/Unix/Command/_head,
+ Completion/Unix/Command/_killall, Completion/Unix/Command/_pv,
+ Completion/Unix/Command/_rclone, Completion/Unix/Command/_rsync,
+ Completion/Unix/Command/_stdbuf, Completion/Unix/Command/_tail,
+ Completion/Unix/Command/_timeout, Completion/Unix/Command/_zfs,
+ Completion/X/Command/_xset: add a helper for completing numbers
+ with unit suffixes and separate out defaults, ranges and units
+ in completion descriptions
+
2021-11-22 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
* 49586: Src/hist.c: fix :a and :A modifiers (with PWD="/") on
diff --git a/Completion/BSD/Command/_ipfw b/Completion/BSD/Command/_ipfw
index 2354a70fe..49d0ef1e8 100644
--- a/Completion/BSD/Command/_ipfw
+++ b/Completion/BSD/Command/_ipfw
@@ -249,8 +249,8 @@ actions=(
$'/(pipe|queue|sched)[ \t\0]/' -'pqs=${match%?}' ':dummynet-commands:dummynet configuration:$ca pipe queue sched'
$word ': _message -e numbers number'
$word ':options:config:$ca config'
- \( $'/bw[ \t\0]/' \( $'/<->/' ': _guard "[0-9]#" bandwidth'
- $word ':units:unit:compadd -M "m:{a-z}={A-Z}" {K,M,G}{bit,Byte}/s'
+ \( $'/bw[ \t\0]/'
+ \( $word ':bandwidths: :_numbers -M "m:{a-z}={A-Z}" bandwidth {K,M,G}{bit,Byte}/s'
\| $word ':devices:device:_net_interfaces -qS " "' \)
\| $'/delay[ \t\0]/' $word ': _message -e numbers "propagation delay (ms)"'
\| $'/burst[ \t\0]/' $word ': _message -e numbers "size (bytes)"'
diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description
index 5b54484c7..368b41ee2 100644
--- a/Completion/Base/Core/_description
+++ b/Completion/Base/Core/_description
@@ -2,6 +2,7 @@
local name nopt xopt format gname hidden hide match opts tag
local -a ign gropt sort
+local -a match mbegin mend
opts=()
@@ -78,6 +79,13 @@ shift 2
if [[ -z "$1" && $# -eq 1 ]]; then
format=
elif [[ -n "$format" ]]; then
+ if [[ -z $2 ]]; then
+ argv+=( h:${1%%( ##\((#b)([^\)]#[^0-9-][^\)]#)(#B)\)|)( ##\((#b)([0-9-]##)(#B)\)|)( ##\[(#b)([^\]]##)(#B)\]|)} )
+ [[ -n $match[1] ]] && argv+=( m:$match[1] )
+ [[ -n $match[2] ]] && argv+=( r:$match[2] )
+ [[ -n $match[3] ]] && argv+=( o:$match[3] )
+ fi
+
zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}"
fi
diff --git a/Completion/Base/Utility/_numbers b/Completion/Base/Utility/_numbers
new file mode 100644
index 000000000..97bb8b4c8
--- /dev/null
+++ b/Completion/Base/Utility/_numbers
@@ -0,0 +1,87 @@
+#autoload
+
+# Usage: _numbers [compadd options] [-t tag] [-f|-N] [-u units] [-l min] [-m max] \
+# [-d default] ["description"] [unit-suffix...]
+
+# -t : specify a tag (defaults to 'numbers')
+# -u : indicate the units, e.g. seconds
+# -l : lowest possible value
+# -m : maximum possible value
+# -d : default value
+# -N : allow negative numbers (implied by range including a negative)
+# -f : allow decimals (float)
+
+# For a unit-suffix, an initial colon indicates a unit that asserts the default
+# otherwise, colons allow for descriptions, e.g:
+
+# :s:seconds m:minutes h:hours
+
+# unit-suffixes are not sorted by the completion system when listed
+# Specify them in order of magnitude, this tends to be ascending unless
+# the default is of a higher magnitude, in which case, descending.
+# So for, example
+# bytes kB MB GB
+# s ms us ns
+# Where the compadd options include matching control or suffixes, these
+# are applied to the units
+
+# For each unit-suffix, the format style is looked up with the
+# unit-suffixes tag and the results concatenated. Specs used are:
+# x : the suffix
+# X : suffix description
+# d : indicate suffix is for the default unit
+# i : list index
+# r : reverse list index
+# The latter three of these are useful with ternary expressions.
+
+# _description is called with the x token set to make the completed
+# list of suffixes available to the normal format style
+
+local desc tag range suffixes suffix suffixfmt pat='<->' partial=''
+local -a expl formats
+local -a default max min keep tags units
+local -i i
+local -A opts
+
+zparseopts -K -D -A opts M+:=keep q:=keep s+:=keep S+:=keep J+: V+: 1 2 o+: n F: x+: X+: \
+ t:=tags u:=units l:=min m:=max d:=default f=type e=type N=type
+
+desc="${1:-number}" tag="${tags[2]:-numbers}"
+(( $# )) && shift
+
+[[ -n ${(M)type:#-f} ]] && pat='(<->.[0-9]#|[0-9]#.<->|<->)' partial='(|.)'
+[[ -n ${(M)type:#-N} || $min[2] = -* || $max[2] = -* ]] && \
+ pat="(|-)$pat" partial="(|-)$partial"
+
+if (( $#argv )) && compset -P "$pat"; then
+ zstyle -s ":completion:${curcontext}:units" list-separator sep || sep=--
+ _description -V units expl unit
+ disp=( ${${argv#:}/:/ $sep } )
+ compadd -M 'r:|/=* r:|=*' -d disp "$keep[@]" "$expl[@]" - ${${argv#:}%%:*}
+ return
+elif [[ -prefix $~pat || $PREFIX = $~partial ]]; then
+ formats=( "h:$desc" )
+ (( $#units )) && formats+=( m:${units[2]} ) desc+=" ($units[2])"
+ (( $#min )) && range="$min[2]-"
+ (( $#max )) && range="${range:--}$max[2]"
+ [[ -n $range ]] && formats+=( r:$range ) desc+=" ($range)"
+ (( $#default )) && formats+=( o:${default[2]} ) desc+=" [$default[2]]"
+
+ zstyle -s ":completion:${curcontext}:unit-suffixes" format suffixfmt || \
+ suffixfmt='%(d.%U.)%x%(d.%u.)%(r..|)'
+ for ((i=0;i<$#;i++)); do
+ zformat -f suffix "$suffixfmt" "x:${${argv[i+1]#:}%%:*}" \
+ "X:${${argv[i+1]#:}#*:}" "d:${#${argv[i+1]}[1]#:}" \
+ i:i r:$(( $# - i - 1))
+ suffixes+="$suffix"
+ done
+ [[ -n $suffixes ]] && formats+=( x:$suffixes )
+
+ _comp_mesg=yes
+ _description -x $tag expl "$desc" $formats
+ [[ $compstate[insert] = *unambiguous* ]] && compstate[insert]=
+ compadd "$expl[@]"
+ return 0
+fi
+
+return 1
diff --git a/Completion/Linux/Command/_btrfs b/Completion/Linux/Command/_btrfs
index bb0f724e6..65cf067aa 100644
--- a/Completion/Linux/Command/_btrfs
+++ b/Completion/Linux/Command/_btrfs
@@ -147,16 +147,16 @@ while (( $#state )); do
'--tbytes[show sizes in TiB, or TB with --si]'
)
;|
- filesystem:resize) args+=( '1:size:_guard "(|+|-)[0-9]#[GKM]"' '2:path:->mounts' );;
+ filesystem:resize) args+=( '1: :_numbers -u bytes -N size K M G T P E' '2:path:->mounts' );;
filesystem:defragment)
args+=( '!-v'
'-r[defragment files recursively]'
'-c+[compress files while defragmenting]::compression algorithm:(zlib lzo zstd)'
'-r[defragment files recursively]'
'-f[flush after defragmenting]'
- '-s[start position]:byte position'
- '-l[defragment limited number of bytes]:length (bytes)'
- '-t[defragment only files over a certain size]:minimum size (bytes) [32M]'
+ '-s[start position]: :_numbers -u bytes -d "beginning of file" offset K M G T P E'
+ '-l[defragment limited number of bytes]: :_numbers -u bytes length K M G T P E'
+ '-t[defragment only extents up to a certain size]: :_numbers -u bytes -d 32M "maximum extent size" K M G T P E'
'*:file:_files'
)
;;
diff --git a/Completion/Unix/Command/_dd b/Completion/Unix/Command/_dd
index e5c5e63ce..10682bc8e 100644
--- a/Completion/Unix/Command/_dd
+++ b/Completion/Unix/Command/_dd
@@ -1,18 +1,19 @@
#compdef dd gdd
-local -a vals conv flags
+local -a vals conv flags units
local variant
+units=( w:word b:block k:1024 m g t )
_pick_variant -r variant gnu=GNU $OSTYPE --version
vals=(
- '(ibs obs)bs[block size]:block size (bytes)'
- 'cbs[conversion buffer size]:buffer size (bytes)'
+ '(ibs obs)bs[block size]: :_numbers -u bytes "block size" $units'
+ 'cbs[conversion buffer size]: :_numbers -u bytes "buffer size" $units'
'conv[specify conversions to apply]: :_values -s , conversion $conv'
'count[number of input blocks to copy]:blocks'
- '(bs)ibs[input block size]:block size (bytes)'
+ '(bs)ibs[input block size]: :_numbers -u bytes -d 512 "block size" $units'
'if[specify input file]:input file:_tilde_files'
- '(bs)obs[output block size]:block size (bytes)'
+ '(bs)obs[output block size]: :_numbers -u bytes -d 512 "block size" $units'
'of[specify output file]:output file:_tilde_files'
'seek[output blocks initially skipped]:blocks'
'skip[input blocks initially skipped]:blocks'
@@ -63,7 +64,7 @@ case $variant in
freebsd*)
vals+=(
'fillchar[specify padding character]:character'
- 'speed[limit copying speed]:speed (bytes/second)'
+ 'speed[limit copying speed]: :_numbers -u bytes/second speed $units'
)
conv+=(
'(pareven parnone parodd parset)'{pareven,parnone,parodd,parset}
@@ -75,6 +76,7 @@ case $variant in
)
flags+=( fullblock noatime nocache count_bytes skip_bytes seek_bytes )
conv+=( excl nocreat fdatasync fsync )
+ units=( c:1 w:2 b:512 kB:1000 K:1024 MB:1000^2 M:1024\^2 GB G TB T PB P EB E ZB Z YB Y )
;;
netbsd*)
vals+=(
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 7c7fb22bc..c757376b0 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -3720,8 +3720,8 @@ _git-fast-import () {
now\:"use current time and timezone"' \
'--done[terminate with error if there is no "done" command at the end of the stream]' \
'--force[force updating modified existing branches]' \
- '--max-pack-size=-[maximum size of each packfile]: : __git_guard_bytes' \
- '--big-file-threshold=-[maximum size of blob to create deltas for]: : __git_guard_bytes' \
+ '--max-pack-size=-[maximum size of each packfile]: : __git_guard_bytes -d unlimited size' \
+ '--big-file-threshold=-[maximum size of blob to create deltas for]: : __git_guard_bytes -d 512m size' \
'--depth=-[maximum delta depth for blob and tree deltification]: :__git_guard_number "maximum delta depth"' \
'--active-branches=-[maximum number of branches to maintain active at once]: :__git_guard_number "maximum number of branches"' \
'--export-marks=-[dump internal marks table when complete]: :_files' \
@@ -7506,7 +7506,7 @@ __git_guard_number () {
(( $+functions[__git_guard_bytes] )) ||
__git_guard_bytes () {
- _guard '[[:digit:]]#([kKmMgG]|)' ${*:-size}
+ _numbers -u bytes ${*:-size} k m g
}
(( $+functions[__git_datetimes] )) ||
diff --git a/Completion/Unix/Command/_head b/Completion/Unix/Command/_head
index f25c97c83..0771b1e4d 100644
--- a/Completion/Unix/Command/_head
+++ b/Completion/Unix/Command/_head
@@ -32,20 +32,14 @@ _arguments -C -s -S $opts : $args '*:file:_files' && return 0
case $state in
(number)
- local mlt sign digit
- mlt='multiplier:multiplier:((b\:512 K\:1024 KB\:1000 M\:1024\^2'
- mlt+=' MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4))'
- sign='sign:sign:((-\:"print all but the last specified bytes/lines"'
- sign+=' +\:"print the first specified bytes/lines (default)"))'
- digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)'
- if compset -P '(-|+|)[0-9]##'; then
- _alternative $mlt $digit && ret=0
- elif [[ -z $PREFIX ]]; then
- _alternative $sign $digit && ret=0
- elif compset -P '(+|-)'; then
- _alternative $digit && ret=0
- fi
- ;;
+ local alts
+ [[ -z $PREFIX ]] && alts=(
+ 'sign:sign:((-\:"print all but the last specified bytes/lines" +\:"print the first specified bytes/lines (default)"))'
+ )
+ compset -P '+'
+ alts+=( 'numbers: :_numbers -N $state_descr b\:512 K\:1024 KB\:1000 M\:1024\^2 MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4' )
+ _alternative $alts && ret=0
+ ;;
esac
return ret
diff --git a/Completion/Unix/Command/_killall b/Completion/Unix/Command/_killall
index 36accb2e0..3ddd36341 100644
--- a/Completion/Unix/Command/_killall
+++ b/Completion/Unix/Command/_killall
@@ -38,15 +38,9 @@ if _pick_variant psmisc=PSmisc unix --version; then
case $state in
(time)
- local -a units=( 's:seconds' 'm:minutes' 'h:hours' 'd:days'
- 'w:weeks' 'M:months' 'y:years' )
- if compset -P '[0-9]##(|.[0-9]#)'; then
- _alternative 'float-numbers:: _message "float number"' \
- 'units:: _describe unit units' && ret=0
- else
- _message 'float number and unit' && ret=0
- fi
- ;;
+ _numbers -fN age 's:seconds' 'm:minutes' 'h:hours' 'd:days' \
+ 'w:weeks' 'M:months' 'y:years'
+ ;;
esac
return ret
diff --git a/Completion/Unix/Command/_pv b/Completion/Unix/Command/_pv
index 68f8e8586..d02d3a35d 100644
--- a/Completion/Unix/Command/_pv
+++ b/Completion/Unix/Command/_pv
@@ -25,7 +25,7 @@ _arguments -s -S $args \
'(-q --quiet)'{-q,--quiet}"[don't output any transfer information at all, useful with -L]" \
'(-W --wait)'{-W,--wait}'[display nothing until first byte transferred]' \
'(-D --delay-start -R --remote)'{-D+,--delay-start=}'[display nothing until delay has passed]:delay (seconds)' \
- '(-s --size)'{-s+,--size=}'[set estimated data size]:size (bytes):->size-unit' \
+ '(-s --size)'{-s+,--size=}'[set estimated data size]: :_numbers -u bytes size K M G T' \
'(-l --line-mode -R --remote)'{-l,--line-mode}'[count lines instead of bytes]' \
'(-0 --null -l --line-mode)'{-0,--null}'[lines are null-terminated]' \
'(-i --interval)'{-i+,--interval=}'[update every after specified interval]:interval (seconds) [1]' \
@@ -34,8 +34,8 @@ _arguments -s -S $args \
'(-N --name)'{-N+,--name=}'[prefix visual information with given name]:name' \
'(-f --force -R --remote)'{-f,--force}'[output even if standard error is not a terminal]' \
'(-c --cursor -R --remote)'{-c,--cursor}'[use cursor positioning escape sequences]' \
- '(-L --rate-limit)'{-L+,--rate-limit=}'[limit transfer rate]:rate (bytes per second):->size-unit' \
- '(-B --buffer-size)'{-B+,--buffer-size=}'[use a buffer size of given size]:size (bytes):->size-unit' \
+ '(-L --rate-limit)'{-L+,--rate-limit=}'[limit transfer rate]: :_numbers -u "bytes per second" rate K M G T' \
+ '(-B --buffer-size)'{-B+,--buffer-size=}'[use a buffer size of given size]: :_numbers -u bytes size K M G T' \
'(-C --no-splice)'{-C,--no-splice}'[never use splice(), always use read/write]' \
'(-R --remote)*'{-E,--skip-errors}"[skip read errors in input${Edesc}]" \
'(-S --stop-at-size -R --remote)'{-S,--stop-at-size}'[stop after --size bytes have been transferred]' \
@@ -70,18 +70,6 @@ case $state in
_pids $suf && ret=0
fi
;;
- size-unit)
- if compset -P '<->'; then
- _tags values units
- else
- _tags values
- fi
- while _tags; do
- _requested values && _message -e values "$state_descr" && ret=0
- _requested units expl unit compadd -o nosort - K M G T && ret=0
- (( ret )) || break
- done
- ;;
esac
return ret
diff --git a/Completion/Unix/Command/_rclone b/Completion/Unix/Command/_rclone
index 27b4dd926..a2e3429f5 100644
--- a/Completion/Unix/Command/_rclone
+++ b/Completion/Unix/Command/_rclone
@@ -62,7 +62,7 @@ _arguments -C \
'--backup-dir[make backups into hierarchy based at specified directory]:directory:_directories' \
'--bind[specify socal address to bind to for outgoing connections]:IPv4, IPv6 or name' \
'--buffer-size[specify in memory buffer size when reading files for each --transfer]:size [16M]' \
- '--bwlimit[specify bandwidth limit]:BwTimetable (kBytes/s or b|k|M|G suffix)' \
+ '--bwlimit[specify bandwidth limit]: :_numbers -u kBytes/s limit b k M G' \
'--cache-dir[specify directory rclone will use for caching]:directory [~/.cache/rclone]:_directories' \
'--checkers[specify number of checkers to run in parallel]:number [8]': \
'(-c --checksum)'{-c,--checksum}'[skip based on checksum & size, not mod-time & size]' \
@@ -99,15 +99,15 @@ _arguments -C \
'--log-format[specify comma separated list of log format options]:string ["date,time"]' \
'--log-level[specify log level]:string [NOTICE]:(DEBUG INFO NOTICE ERROR)' \
'--low-level-retries[number of low level retries to do]:int [10]' \
- '--max-age[only transfer files younger than this in s or suffix ms|s|m|h|d|w|M|y]:duration [default off]' \
+ '--max-age[only transfer files younger than specified age]: :_numbers -u seconds age ms\:milliseconds \:s\:seconds m\:minutes h\:hours d\:days w\:weeks M\:months y\:years' \
'--max-backlog[maximum number of objects in sync or check backlog]:int [10000]' \
'--max-delete[when synchronizing, limit the number of deletes]:delete limit [-1]' \
'--max-depth[limit the recursion depth]:depth [-1]' \
- '--max-size[only transfer files smaller than this in k or suffix b|k|M|G]:int [default off]' \
+ '--max-size[only transfer files smaller than specified size]: :_numbers -u kBytes size \:k M G' \
'--max-transfer[maximum size of data to transfer]:int [default off]' \
'--memprofile[write memory profile to file]:file:_files' \
- '--min-age[only transfer files older than this in s or suffix ms|s|m|h|d|w|M|y]:duration [default off]' \
- '--min-size[only transfer files bigger than this in k or suffix b|k|M|G]:int [default off]' \
+ '--min-age[only transfer files older than specified age]: :_numbers -u seconds age ms\:milliseconds \:s\:seconds m\:minutes h\:hours d\:days w\:weeks M\:months y\:years' \
+ '--min-size[only transfer files bigger than specified size]: :_numbers -u kBytes size \:k M G' \
'--modify-window[specify max time delta to be considered the same]:duration [1ns]' \
'--multi-thread-cutoff[use multi-threaded downloads for files above specified size]:size (250M)' \
'--multi-thread-streams[specify max number of streams to use for multi-threaded downloads]:number (4)' \
diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync
index b1a4f6046..eb906e974 100644
--- a/Completion/Unix/Command/_rsync
+++ b/Completion/Unix/Command/_rsync
@@ -99,7 +99,7 @@ _rsync() {
_arguments -s \
'*'{-v,--verbose}'[increase verbosity]' \
{--no-v,--no-verbose}'[turn off --verbose]' \
- '--bwlimit=[limit I/O bandwidth]:limit (KiB per second)' \
+ '--bwlimit=[limit I/O bandwidth]: :_numbers -f -u "KiB per second" -d 1g limit B K M G T P' \
'--outbuf=[set output buffering]:buffering:(none line block)' \
'--port=[specify alternate port number]:port:(873)' \
'--address=[bind to the specified address]:bind address:_bind_addresses' \
@@ -181,7 +181,7 @@ _rsync() {
{--no-W,--no-whole-file}'[turn off --whole-file]' \
'(--cc --checksum-choice)'{--cc,--checksum-choice}'=[choose the checksum algorithms]:algorithm:_sequence -n 2 compadd - auto md4 md5 none' \
'(-x --one-file-system)'{-x,--one-file-system}"[don't cross filesystem boundaries]" \
- '(-B --block-size)'{-B+,--block-size=}'[force a fixed checksum block-size]:block size (bytes)' \
+ '(-B --block-size)'{-B+,--block-size=}'[force a fixed checksum block-size]: :_numbers -f -u bytes -d 1g "block size" B K M G T P' \
'(-e --rsh)'{-e+,--rsh=}'[specify the remote shell to use]:remote-shell command:(rsh ssh)' \
'--rsync-path=[specify path to rsync on the remote machine]:remote command' \
'--ignore-existing[ignore files that already exist on receiving side]' \
@@ -199,10 +199,10 @@ _rsync() {
'--force-change[affect user-/system-immutable files/dirs]' \
'--force-uchange[affect user-immutable files/dirs]' \
'--force-schange[affect system-immutable files/dirs]' \
- '--max-delete=[do not delete more than NUM files]:number' \
- '--max-size=[do not transfer any file larger than specified size]:number' \
+ "--max-delete=[don't delete more than NUM files]: :_numbers -f -u bytes size B K M G T P" \
+ "--max-size=[don't transfer any file larger than specified size]: :_numbers -f -u bytes size B K M G T P" \
'--min-size=[do not transfer any file smaller than specified size]:number' \
- '--max-alloc=[set limit to individual memory allocation]:size (bytes) [1g]' \
+ '--max-alloc=[set limit to individual memory allocation]: :_numbers -f -u bytes -d 1g size B K M G T P' \
'(-P)--partial[keep partially transferred files]' \
'--no-partial[turn off --partial]' \
'--partial-dir=[put a partially transferred file into specified directory]:directory:_directories' \
diff --git a/Completion/Unix/Command/_stdbuf b/Completion/Unix/Command/_stdbuf
index a18938ee1..4b7d98ba0 100644
--- a/Completion/Unix/Command/_stdbuf
+++ b/Completion/Unix/Command/_stdbuf
@@ -7,7 +7,9 @@ short=( -e -i -o )
long=( --error --input --output )
buf=( err in out )
-opt='[set initial buffering for std${buf[i]}]:mode or size:((0\:unbuffered L\:line\ buffered'
+opt='[set initial buffering for std${buf[i]}]: : _alternative
+ "sizes\: \: _numbers -u bytes size k M G"
+ "modes\:mode\:((0\:unbuffered L\:line\ buffered'
if _pick_variant gnu=GNU freebsd --version; then
gnu=1
args=(
@@ -17,7 +19,7 @@ if _pick_variant gnu=GNU freebsd --version; then
else
opt+=' B\:fully\ buffered'
fi
-opt+='))'
+opt+='))"'
for ((i=1;i<=3;i++)); do
args+=( "(${long[i]})${short[i]}+${(e)opt}" )
diff --git a/Completion/Unix/Command/_tail b/Completion/Unix/Command/_tail
index 6d6e9b2d5..e54a0b06e 100644
--- a/Completion/Unix/Command/_tail
+++ b/Completion/Unix/Command/_tail
@@ -53,20 +53,14 @@ _arguments -C -s -S $opts : $args '*:file:_files' && return
case $state in
(number)
- local mlt sign digit
- mlt='multipliers:multiplier:((b\:512 K\:1024 KB\:1000 M\:1024\^2'
- mlt+=' MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4))'
- sign='signs:sign:((+\:"start at the specified byte/line"'
- sign+=' -\:"output the last specified bytes/lines (default)"))'
- digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)'
- if compset -P '(-|+|)[0-9]##'; then
- _alternative $mlt $digit && ret=0
- elif [[ -z $PREFIX ]]; then
- _alternative $sign $digit && ret=0
- elif compset -P '(+|-)'; then
- _alternative $digit && ret=0
- fi
- ;;
+ local alts
+ [[ -z $PREFIX ]] && alts=(
+ 'sign:sign:((-\:"print all but the last specified bytes/lines" +\:"print the first specified bytes/lines (default)"))'
+ )
+ compset -P '+'
+ alts+=( 'numbers: :_numbers -N $state_descr b\:512 K\:1024 KB\:1000 M\:1024\^2 MB\:1000\^2 G\:1024\^3 GB\:1000\^3 T\:1024\^4 TB\:1000\^4' )
+ _alternative $alts && ret=0
+ ;;
esac
return ret
diff --git a/Completion/Unix/Command/_timeout b/Completion/Unix/Command/_timeout
index 2235fa5ec..c041283ac 100644
--- a/Completion/Unix/Command/_timeout
+++ b/Completion/Unix/Command/_timeout
@@ -16,5 +16,5 @@ _arguments -S -A "-" $args \
"--foreground[don't propagate timeout to the command children]" \
'(-s --signal)'{-s,--signal}'[specify the signal to send on timeout]:signal:_signals' \
'(-k --kill-after)'{-k,--kill-after}'[followup first signal with SIGKILL if command persists after specified time]:time' \
- '1: :_guard "[0-9.]#([smhd]|)" duration' \
+ '1: :_numbers -f -u seconds duration :s:seconds m:minutes h:hours d:days' \
'*:::command:_normal'
diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs
index 452e1160d..51da9170b 100644
--- a/Completion/Unix/Command/_zfs
+++ b/Completion/Unix/Command/_zfs
@@ -162,12 +162,20 @@ _zfs() {
"multilevel:value:(on off)"
"nbmand:value:(on off)"
"primarycache:value:(all none metadata)"
- "quota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == quota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'quota' compadd none; fi}"
+ "quota: : _alternative \
+ 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(none)'"
"readonly:value:(on off)"
"recordsize:value:(512 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M)"
- "refquota:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refquota= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refquota' compadd none; fi}"
- "refreservation:number or 'none':{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == refreservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'refreservation' compadd none; fi}"
- "reservation:value:{if [[ -prefix [0-9]## ]]; then _message -e 'number'; elif [[ $PREFIX == reservation= ]]; then _wanted none expl 'number or none' compadd none; else _wanted none expl 'reservation' compadd none; fi}"
+ "refquota: : _alternative \
+ 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(none)'"
+ "refreservation: : _alternative \
+ 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(auto none)'"
+ "reservation: : _alternative \
+ 'sizes: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
+ 'properties:property:(none)'"
"rstchown:value:(on off)"
"secondarycache:value:(all none metadata)"
"setuid:value:(on off)"
@@ -238,8 +246,8 @@ _zfs() {
':filesystem:_zfs_dataset -t fs -e "parent dataset"' \
- set2 \
'-s[Create sparse volume]' \
- '-b[Set volblocksize]:blocksize:' \
- '-V[Set size]:size:' \
+ '-b+[set volblocksize]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes blocksize :B {k,M,G,T,P,E,Z}{,B}' \
+ '-V+[set size]: :_numbers -M "m\:{a-zA-Z}={A-Za-z}" -u bytes size :B {k,M,G,T,P,E,Z}{,B}' \
':volume:_zfs_dataset -t fs -e "parent dataset"'
;;
diff --git a/Completion/X/Command/_xset b/Completion/X/Command/_xset
index b35a6466b..adda47f01 100644
--- a/Completion/X/Command/_xset
+++ b/Completion/X/Command/_xset
@@ -91,8 +91,8 @@ _regex_arguments _xset_parse \
\( "/(blank|noblank|expose|noexpose|default|on|activate|reset)$nul/" \
':option-s:screen saver:(blank noblank expose noexpose default on activate reset off)' \
\| "/off$nul/" \( "/off$nul/" ':option-s-off-period:period off:(off)' \| \) \
- \| "/[0-9]##$nul/" ':option-s-timeout:length:' \
- \( "/[0-9]##$nul/" ':option-s-period:period:' \
+ \| "/[0-9]##$nul/" ':option-s-timeout: :_numbers -u seconds length' \
+ \( "/[0-9]##$nul/" ':option-s-period: :_numbers -u seconds period' \
\| \) \
\| \) \
\| "/-r$nul/" "$guard" \
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 8c6bf9c40..40238c4b9 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -4496,8 +4496,22 @@ not contain an explanation string to be displayed above the matches.
If tt(_description) is called with more than three arguments,
the additional var(spec)s should be of the form `var(char)tt(:)var(str)'.
These supply escape sequence replacements for the tt(format) style:
-every appearance of `tt(%)var(char)' will be
-replaced by var(string).
+every appearance of `tt(%)var(char)' will be replaced by var(string).
+If no additional var(spec)s are given but the description in var(descr)
+conforms to a common form then further escape sequences are set for
+elements of that description. These elements correspond to a default
+value (`tt(%o)'), the units (`tt(%m)') range of acceptable values
+(`tt(%r)') and the remaining initial part of the description (`tt(%h)').
+The form the description takes consists of specifying the units and
+range in parentheses and the default value in square brackets, for
+example:
+
+example(_description times expl 'timeout (seconds) (0-60) [20]')
+
+It is possible to use tt(zformat) conditional expressions when styling
+these elements. So, for example, to add `tt(default:)' as a tag but only
+when there is a default value to show, the tt(format) style might
+include `tt(%(o.default: %o.))'.
If the tt(-x) option is given, the description will be passed to
tt(compadd) using the tt(-x) option instead of the default tt(-X). This
@@ -4773,6 +4787,69 @@ checked. If it is set completion is terminated at that point even if
no matches have been found. This is the same effect as in the
tt(-first-) context.
)
+findex(_numbers)
+item(tt(_numbers) [ var(option) ... ] [ var(description) ] [ var(suffix) ... ])(
+This can be used where a number is followed by a suffix to indicate the units.
+The unit suffixes are completed and can also be included in the description
+used when completion is invoked for the preceding number.
+
+In addition to common tt(compadd) options, tt(_numbers) accepts the following
+options:
+
+startitem()
+item(tt(-t) var(tag))(
+Specify a tag to use instead of the default of tt(numbers).
+)
+item(tt(-u) var(units))(
+Indicate the default units for the number, e.g. tt(bytes).
+)
+item(tt(-l) var(min))(
+Specify the lowest possible value for the number.
+)
+item(tt(-m) var(max))(
+Specify the highest possible value for the number.
+)
+item(tt(-d) var(default))(
+Specify the default value.
+)
+item(tt(-N))(
+Allow negative numbers. This is implied if the range includes a negative.
+)
+item(tt(-f))(
+Allow decimal numbers.
+)
+enditem()
+
+Where a particular suffix represents the default units for a number, it
+should be prefixed with a colon. Additionally, suffixes can be followed
+by a colon and a description. So for example, the following allows the
+age of something to be specified, either in seconds or with an optional
+suffix with a longer unit of time:
+
+example(_numbers -u seconds age :s:seconds m:minutes h:hours d:days)
+
+It is typically helpful for units to be presented in order of magnitude
+when completed. To facilitate this, the order in which they are given
+is preserved.
+
+When the tt(format) style is looked up with the tt(descriptions) tag or
+the tag specified with tt(-t), the list of suffixes is available as a
+`tt(%x)' escape sequence. This is in addition to the usual sequences
+documented under the tt(format) style. The form this list takes can also
+be configured. To this end, the tt(format) style is first looked up with
+the tag tt(unit-suffixes). The retrieved format is applied to each
+suffix in turn and the results are then concatenated to form the
+completed list. For the tt(unit-suffixes) format, `tt(%x)' expands to
+the individual suffix and `tt(%X)' to its description. tt(%d)' indicates
+a default suffix and can be used in a condition. The index and reverse
+index are set in `tt(%i)' and `tt(%r)' respectively and are useful for
+text included only with the first and last suffixes in the list. So for
+example, the following joins the suffixes together as a comma-separated
+list:
+
+example(zstyle ':completion:*:unit-suffixes' format '%x%(r::,)')
+)
+
findex(_options)
item(tt(_options))(
This can be used to complete the names of shell options. It provides a