42931: completion for several utilities especially for checksums across a variety of systems

This commit is contained in:
dana 2018-06-04 10:04:27 -05:00 committed by Oliver Kiddle
parent 594f2ff06e
commit 64ef1eddfd
10 changed files with 485 additions and 81 deletions

View File

@ -1,5 +1,12 @@
2018-06-07 Oliver Kiddle <okiddle@yahoo.co.uk>
* 42931: dana: Completion/Unix/Command/_base64,
Completion/Unix/Command/_chroot, Completion/Unix/Command/_cksum,
Completion/Unix/Command/_lz4, Completion/Unix/Command/_md5sum,
Completion/Unix/Command/_tee, Completion/Unix/Command/_shasum,
Completion/Unix/Command/_readlink: completion for several
utilities especially for checksums across a variety of systems
* users/23434: Functions/Misc/zed: initialise UNDO_LIMIT_NO so
that an initial undo doesn't clear the whole edit buffer

View File

@ -1,67 +0,0 @@
#compdef cksum sum=cksum md2 md4 md5 rmd160 sha1 sha256 sha384 sha512 sha512t256
if [[ $OSTYPE == (dragonfly|freebsd)* && service == cksum ]]; then
_arguments -s -S -A '-*' \
'-o[use specified historic algorithm]:historic algorithm:(1 2 3)' \
'*:_files'
else
local -a args
case $OSTYPE in
dragonfly*|freebsd*|netbsd*)
args+=(
'-t[run built-in time trial]'
)
;|
dragonfly*|freebsd*|openbsd*)
args+=(
'-r[reverse the output format]'
)
;|
dragonfly*)
args+=(
'-b+[begin at specified offset]:begin offset: '
'-e+[end at specified offset]:end offset: '
)
;;
freebsd*)
args+=(
'-c+[compare digest against specified string]:digest string: '
)
;;
netbsd*)
args+=(
'(*)-c+[compare checksums against specifed sumfile]:sumfile:_files'
'-n[reverse the output format]'
'-w[warn on malformed checksum files]'
)
if [[ $service == cksum ]]; then
args=(
'(-o)-a+[use the specfied algorithm(s)]:algorithm:(crc md2 md4 md5 old1 old2 rmd160 sha1 sha256 sha384 sha512)'
'(-a)-o+[use the specfied historic algorithm]:historic algorithm:(1 2)'
)
fi
;;
openbsd*)
args+=(
'-b[output in base 64]'
'-C+[compare checksums against specifed checklist]:checklist:_files'
'-c[file arguments are checklists]'
'-h+[output to specified hashfile]:hashfile:_files'
'*-t[run built-in time trial]'
)
if [[ $service == cksum ]]; then
args+=('*-a+[use the specfied algorithm(s)]:algorithm:_values -s , algotithm cksum md5 rmd160 sha1 sha224 sha256 sha384 sha512/256 sha512')
fi
;;
esac
_arguments -s -S -A '-*' \
$args \
'-p[echo stdin to stdout]' \
'-q[quiet mode]' \
'-s+[checksum specified string]:string: ' \
'-x[run built-in test]' \
'*:_files'
fi

View File

@ -0,0 +1,59 @@
#compdef base64 gbase64 base32 gbase32
# Note: This does NOT cover `uuencode`/`uudecode`, which on some BSD systems
# have the aliases `b64encode`/`b64decode` — those are sufficiently different
# that they belong in another function. It DOES cover GNU's `base32`, since it
# is essentially the same program as their `base64`.
local variant type=base${service//[^2346]/}
_pick_variant -r variant \
gnu='Free Soft' fourmilab=fourmi darwin=-D unix --version
case $variant in
gnu)
_arguments -s -S : \
'(: -)--help[display help information]' \
'(: -)--version[display version information]' \
+ dec \
'(enc -d --decode)'{-d,--decode}"[decode input from $type]" \
'(enc -i --ignore-garbage)'{-i,--ignore-garbage}'[ignore irrelevant characters when decoding]' \
+ '(enc)' \
'(dec)'{-w+,--wrap=}'[wrap encoded lines at specified number of columns]:number of columns' \
+ in \
'1:input file:_files'
return
;;
darwin)
_arguments -s -S : \
'(: -)'{-h,--help}'[display help information]' \
+ '(dec)' \
'(enc)'{-D,--decode}"[decode input from $type]" \
+ '(enc)' \
'(dec)'{-b+,--break=}'[wrap encoded lines at specified number of columns]:number of columns' \
+ '(out)' \
{-o+,--output=}'[specify output file]:output file:_files' \
+ '(in)' \
{-i+,--input=}'[specify input file]:input file:_files' \
'1:input file:_files'
return
;;
fourmilab)
_arguments -s -S : \
'(: -)--copyright[display copyright information]' \
'(: -)'{-u,--help}'[display help information]' \
'(: -)--version[display version information]' \
+ dec \
'(enc -d --decode)'{-d,--decode}"[decode input from $type]" \
'(enc -n --noerrcheck)'{-n,--noerrcheck}'[ignore errors when decoding]' \
+ '(enc)' \
'(dec)'{-e,--encode}"[encode input to $type]" \
+ io \
'1:input file:_files' \
'2:output file:_files'
return
;;
esac
# A few other implementations exist, though they are rarely encountered
_default

View File

@ -0,0 +1,53 @@
#compdef chroot gchroot
local variant ret=1
local -a context line state state_descr args
local -A opt_args
_pick_variant -r variant gnu='Free Soft' unix --version
variant+=-$OSTYPE
case $variant in
gnu-*)
args=(
'(: -)--help[display help information]'
'(: -)--version[display version information]'
'--groups=[specify supplemental group memberships]: :_sequence -s , _groups'
'--userspec=[specify user and group to run process as]: :->userspecs'
'--skip-chdir[do not change working directory to /]'
)
;;
*-openbsd*)
args=(
'-u+[specify user to run process as]: :_users'
'-g+[specify group to run process as, and supplemental group memberships]: :_sequence -s , _groups'
)
;;
*-(darwin|dragonfly|freebsd|netbsd)*)
args=(
'-u+[specify user to run process as]: :_users'
'-g+[specify group to run process as]: :_groups'
'-G+[specify supplemental group memberships]: :_sequence -s , _groups'
)
;;
esac
args+=( '1:new root directory:_directories' '*:::command:_normal' )
_arguments -s -S : $args && ret=0
# @todo user:group specs are probably used often enough to justify making a type
# function for this (see also `chown`, `cpio`, `rsync`, ...)
[[ $state == userspecs ]] &&
if compset -P '*:*:'; then
ret=1
elif compset -P '*:'; then
_groups && ret=0
elif compset -S ':*'; then
_users && ret=0
else
_users -qS : && ret=0
fi
return ret

View File

@ -0,0 +1,112 @@
#compdef cksum gcksum sum gsum md2 md4 md5 rmd160 sha1 sha256 sha384 sha512 sha512t256 skein256 skein512 skein1024
# This function covers mostly the BSD `cksum`, `sum`, and digest utilities. It
# also covers the GNU Coreutils `cksum` and `sum`. For the GNU digest utilities,
# see `_md5sum`. For the `shasum` Perl script, see `_shasum`.
#
# Notes:
# - We really don't do a very good job of handling option exclusivity here. In
# particular, OpenBSD treats -t and -x as exclusive of each other and most
# other options — but there are issues with other variants too (@todo)
# - Although only OpenBSD's documentation mentions it, -t can be supplied
# multiple times with all variants to run additional rounds of testing
# - All digest variants on a given platform share code, but not all variants are
# found on all platforms (e.g., Darwin only has `md5`). Some BSDs are actively
# purging legacy/insecure digest tools
# - The documentation for Dragonfly/FreeBSD `sum` says that it's 'identical to'
# `cksum`, but, as the synopsis confirms, it doesn't take any options
# - FreeBSD's -c is never useful, and Dragonfly's -b/-e are *almost* never
# useful, with multiple input files
# - NetBSD's -n isn't useful with `sum` and `cksum` unless a digest is specified
# with -a. Similarly, OpenBSD's -b isn't useful with `cksum` without -a
# - OpenBSD's -a option allows you to add a b/x suffix to each algorithm name;
# we don't handle that. Also, only one -a option can be used in conjunction
# with -c; we don't handle that either
local -a args
_pick_variant gnu='Free Soft' unix --version && {
args=(
'*: :_files'
'(: -)--help[display help information]'
'(: -)--version[display version information]'
)
[[ $service == *cksum* ]] || args+=(
'(-s --sysv)-r[use BSD algorithm (1 KiB blocks)]'
'(-r -s --sysv)'{-s,--sysv}'[use System V algorithm (512 B blocks)]'
)
_arguments -s -S : $args
return
}
[[ $OSTYPE == (darwin|dragonfly|freebsd|openbsd)* && $service == sum ]] && {
_default
return
}
[[ $OSTYPE == (darwin|dragonfly|freebsd)* && $service == cksum ]] && {
_arguments -s -S -A '-*' \
'-o[use specified historic algorithm]:historic algorithm:(1 2 3)' \
'*: :_files'
return
}
case $OSTYPE in
darwin*|dragonfly*|freebsd*|netbsd*)
args+=(
'(-n -p -r)-q[output checksums only]'
)
;| # MATCH AGAIN
darwin*|dragonfly*|freebsd*|openbsd*)
args+=(
'(-p -q)-r[reverse output format]'
)
;| # MATCH AGAIN
netbsd*|openbsd*)
args+=(
'-c[verify checksums from input files]'
)
;| # MATCH AGAIN
dragonfly*)
args+=(
'-b+[begin processing files at specified offset]:begin offset (bytes)'
'-e+[end processing files at specified offset]:end offset (bytes)'
)
;;
freebsd*)
args+=(
'-c+[verify input against specified digest string]:digest string'
)
;;
netbsd*)
args+=(
'(-p -q)-n[reverse output format]'
'(-p)-w[warn on malformed checksum files]'
)
[[ $service == (|ck)sum ]] && args+=(
'(-o)-a+[use specified algorithm]:algorithm:(crc md2 md4 md5 old1 old2 rmd160 sha1 sha256 sha384 sha512)'
'(-a)-o+[use specified historic algorithm]:historic algorithm:(1 2)'
)
;;
openbsd*)
args+=(
'-b[output in base64]'
'(-h)-C+[verify input files against checksums in specifed file]:checksum file:_files'
'(-C)-h+[output checksums to specified file]:checksum file:_files'
'(-n -r)-q[output checksum only, or suppress check success messages]'
)
[[ $service == cksum ]] && args+=(
'*-a+[use specified algorithm(s)]:algorithm:_values -s , algorithm cksum md5 rmd160 sha1 sha224 sha256 sha384 sha512/256 sha512'
)
;;
esac
args+=(
'-p[output stdin along with checksum]'
'*-s+[checksum specified string]:string'
'*-t[run built-in time trial(s)]'
'-x[run built-in tests]'
'*: :_files'
)
_arguments -s -S -A '-*' : $args

View File

@ -0,0 +1,103 @@
#compdef lz4 lz4c lz4c32 lz4cat unlz4
# Notes:
# - All lz4 CLI tools take the same options — you can do `unlz4 --compress` if
# you want — and we complete accordingly. One can make a reasonable argument
# that we shouldn't, but...?
# - The only exceptions to the above are the legacy compression options (-c0,
# -hc, and so on) — only lz4c accepts these. Each of these options is
# interpreted separately otherwise (e.g., -c0 becomes equivalent to -c -0)
# - All these tools use a non-standard option-handling method that we don't
# fully support. For example, the tool will let you do things like `-b1e3i3`
# instead of `-b1 -e3 -i3` — we won't
local ret=1
local -a context line state state_descr expl args levels=( -{1..16} )
local -A opt_args val_args
args=(
+ excl # Fully exclusive options
'(: -)'{-h,--help}'[display help information]'
'(: -)-H[display long help information]'
'(: -)'{-V,--version}'[display version information]'
+ misc # Misc. arguments
'(-q -v --quiet --verbose)*'{-q,--quiet}'[reduce output verbosity]'
'(-q -v --quiet --verbose)*'{-v,--verbose}'[increase output verbosity]'
'*::: :->files'
+ B # Benchmark/compress-mode options (not allowed with legacy format)
'(d t -l)*-B-[specify block property]: :->block-props'
'(d t -l --no-content-size)--content-size[record original uncompressed size]'
'(d t -l --no-frame-crc)--frame-crc[enable content checksum]'
'(d t -l --content-size)--no-content-size[do not record original uncompressed size]'
'(d t -l --frame-crc)--no-frame-crc[disable content checksum]'
'(d t -l --sparse)--no-sparse[disable sparse-file support]'
'(d t -l --no-sparse)--sparse[enable sparse-file support]'
+ C # Compress/decompress-mode options
'(b t -c --stdout --to-stdout)'{-c,--stdout}'[write on standard output]'
'(b t -y)'{-f,--force}'[overwrite target without prompting, or cat on standard output]'
'(b t -k --keep --rm)'{-k,--keep}'[keep source file]'
'(b t -m -r --multiple)'{-m,--multiple}'[take multiple input files]'
'!(b -t -f -y --force)--no-force'
'(b t -m --multiple)-r[operate recursively on directories]'
'(b t -k --keep)--rm[remove source file]'
'!(b t -c --stdout)--to-stdout'
+ b # Benchmark-mode options
"(C c d t)-b-[benchmark file using specified compression level]::compression level:(${(j< >)levels//-/})"
"(C c d t)-e-[specify upper compression level limit (with -b)]:compression level:(${(j< >)levels//-/})"
'(C c d t)-i-[specifiy minimum evaluation time (with -b)]:evaluation time (seconds)'
+ c # Compress-mode options
"(b d t ${(j< >)levels} -c0 -c1 -c2 -hc)"${^levels}
'(B b d t -m -r --multiple)-l[compress using legacy (Linux kernel) format]'
'(b d t -z --compress)'{-z,--compress}'[compress file]'
+ d # Decompress-mode options
'(B b c d t)'{-d,--decompress}'[decompress file]'
'!(B b c d t)--uncompress'
+ t # Test-mode options
'(B C b c d t)'{-t,--test}'[test integrity of compressed file]'
)
[[ $service == lz4c ]] && args+=(
+ l # Legacy compress-mode options (not to be confused with the legacy format)
"(b d t ${(j< >)levels} -c1 -c2 -hc)-c0[use fast compression (like -0)]"
"(b d t ${(j< >)levels} -c0 -c2 -hc)-c1[use high compression (like -9)]"
"(b d t ${(j< >)levels} -c0 -c1 -c2 -hc)"{-c2,-hc}'[use very high compression (like -12)]'
'(b t -f --force)-y[overwrite target without prompting]'
)
_arguments -s -S : $args && ret=0
case $state in
block-props)
# The usage help indicates that the use of an explicit byte value (-B32 or
# greater) is only for benchmarking, and indeed when such a value is given
# the tool prints a message prefixed with 'bench:'... but there is nothing
# that actually restricts this to the benchmark mode, so...?
_values 'predefined block property or block size in bytes (32+)' \
'4[set block size to 64 KiB]' \
'5[set block size to 256 KiB]' \
'6[set block size to 1 MiB]' \
'7[set block size to 4 MiB]' \
'D[enable block dependency]' \
'X[enable block checksum]' \
&& ret=0
;;
files)
if
(( CURRENT == 1 )) ||
[[ -n ${opt_args[(i)*-(-b|-m|-r|--multiple)]} ]]
then
if [[ -n ${opt_args[(i)*--r]} ]]; then
_description files expl 'input file or directory'
else
_description files expl 'input file'
fi
_files "${(@)expl}" && ret=0
elif (( CURRENT == 2 )); then
_description files expl 'output file'
_files "${(@)expl}" && ret=0
else
_message 'no more arguments' && ret=0
fi
;;
esac
return ret

View File

@ -1,15 +1,48 @@
#compdef md5sum gmd5sum
#compdef md5sum gmd5sum b2sum gb2sum sha1sum gsha1sum sha224sum gsha224sum sha256sum gsha256sum sha384sum gsha384sum sha512sum gsha512sum
_arguments -S \
'(-b --binary)'{-b,--binary}'[read in binary mode]' \
'(-c --check)'{-c,--check}'[read MD5 sums from the FILEs and check them]' \
'--tag[create a BSD-style checksum]' \
'(-t --text)'{-t,--text}'[read in text mode]' \
"--ignore-missing[don't fail or report status for missing files]" \
'(-q --quiet)'{-q,--quiet}"[don't print OK for each successfully verified file]" \
'--status[no output, status code shows success]' \
'--strict[exit non-zero for improperly formatted checksum lines]' \
'(-w --warn)'{-w,--warn}'[warn about improperly formatted checksum lines]' \
'(-)--help[display help and exit]' \
'(-)--version[output version information and exit]' \
'*:files:_files'
# This function covers the various digest utilities (which are all essentially
# the same program) from GNU Coreutils. It does NOT cover GNU `cksum` and `sum`,
# nor the various BSD digest utilities like `md5` and `sha1` — see `_cksum` for
# all of those. See `_shasum` for the `shasum` Perl script.
#
# @todo Support BusyBox?
local type
local -a args
case $service in
*md5*) type=MD5 ;;
*b2*) type=BLAKE2 ;;
*sha*) type=SHA${service//[^0-9]/} ;;
esac
# General options
args+=(
'(: -)--help[display help information]'
'(: -)--version[display version information]'
)
# Summing options
args+=(
+ sum
'(chk)--tag[create BSD-style checksums]'
'(chk -b -t --binary --text)'{-b,--binary}'[read in binary mode]'
'(chk -b -t --binary --text)'{-t,--text}'[read in text mode]'
)
# This is the only option that differs amongst all of these tools
[[ $service == *b2* ]] && args+=(
'(chk -l --length)'{-l+,--length=}'[specify digest length]:digest length (bits, multiples of 8)'
)
# Verification options
args+=(
+ chk
'(sum -c --check)'{-c,--check}"[verify $type checksums from input files]"
"(sum)--ignore-missing[don't fail or report status for missing files]"
"(sum)--quiet[don't print OK for each verified file]"
'(sum -w --warn)--status[suppress all output]'
'(sum)--strict[exit non-zero for improperly formatted checksum lines]'
'(sum -w --status --warn)'{-w,--warn}'[warn about each improperly formatted checksum line]'
)
# Operands
args+=( '*: :_files' )
_arguments -s -S : $args

View File

@ -0,0 +1,48 @@
#compdef readlink greadlink
local variant ret=1
local -a context line state state_descr args copts aopts=( -A '-*' )
local -A opt_args
# We can't use groups here because it would complicate the option filtering
copts=( -e -f -m --canonicalize --canonicalize-existing --canonicalize-missing )
args=(
'(: -)--help[display help information]'
'(: -)--version[display version information]'
# Delimiter options
# (Note: GNU `readlink` won't let you use -n with multiple files)
'(-n -z --no-newline --zero)'{-n,--no-newline}'[suppress trailing newline]'
'(-n -z --no-newline --zero)'{-z,--zero}'[use NUL as output delimiter]'
# Verbosity options
'(-q -s -v --quiet --silent --verbose)'{-q,-s,--quiet,--silent}'[suppress most error messages]'
'(-q -s -v --quiet --silent --verbose)'{-v,--verbose}'[show error messages]'
# Canonicalisation options
"(${(j< >)copts})"{-e,--canonicalize-existing}'[canonicalize paths (all components must exist)]'
"(${(j< >)copts})"{-f,--canonicalize}'[canonicalize paths]'
"(${(j< >)copts})"{-m,--canonicalize-missing}'[canonicalize paths (components may be missing)]'
)
# Filter out non-GNU options if applicable
if _pick_variant gnu='Free Soft' unix --version; then
aopts=( )
else
case $OSTYPE in
darwin*) args=( ${(@M)args:#(|*\))-[n]\[*} ) ;;
netbsd*) args=( ${(@M)args:#(|*\))-[fnqsv]\[*} ) ;;
dragonfly*|*bsd*) args=( ${(@M)args:#(|*\))-[fn]\[*} ) ;;
*) args=( ) ;;
esac
fi
_arguments -s -S $aopts : $args '*: :->files' && ret=0
# File arguments must be symlinks unless a canonicalisation option is given
[[ $state == files ]] &&
if [[ ${opt_args[(i)(${~${(j<|>)copts}})]} ]]; then
_files && ret=0
else
_files -g '*(@)' && ret=0
fi
return ret

View File

@ -0,0 +1,24 @@
#compdef shasum -P shasum(|5).*
# This function covers the `shasum` script included with Perl (and notably the
# primary SHA digest tool on macOS). See `_md5sum` for the GNU digest utilities
# and `_cksum` for the BSD ones.
#
# @todo It's possible that someone could symlink this script to `sha1sum` or
# whatever; we might want to detect that some day.
_arguments -s -S : \
'(: -)'{-h,--help}'[display help information]' \
'(: -)'{-v,--version}'[display version information]' \
+ '(sum)' \
'(chk)'{-0,--01}'[read in BITS mode]' \
'(chk)'{-b,--binary}'[read in binary mode]' \
'(chk)'{-p,--portable}'[read in portable mode]' \
'(chk)'{-t,--text}'[read in text mode]' \
+ 'chk' \
'(sum)'{-c,--check}'[verify checksums from input files]' \
'(sum -s -w --status --warn)'{-s,--status}'[suppress all output]' \
'(sum -s -w --status --warn)'{-w,--warn}'[warn about each improperly formatted checksum line]' \
+ misc \
'(-a --algorithm)'{-a+,--algorithm=}'[specify algorithm]:algorithm:(1 224 256 384 512 512224 512256)' \
'*: :_files'

View File

@ -0,0 +1,32 @@
#compdef tee gtee
local ret=1
local -a context line state state_descr args
local -A opt_args
args=(
'(: -)--help[display help information]'
'(: -)--version[display version information]'
'(-a --append)'{-a,--append}'[append to files instead of overwriting]'
'(-i --ignore-interrupts)'{-i,--ignore-interrupts}'[ignore interrupt signals]'
'(--output-error)-p[warn on errors writing to non-pipes]'
'(-p)--output-error=[specify write-error behavior]: :->errmodes'
)
# Filter out non-GNU options if applicable
_pick_variant gnu='Free Soft' unix --version ||
args=( ${(@M)args:#(|*\))-[ai]\[*} )
_arguments -s -S : $args '*: :_files' && ret=0
[[ $state == errmodes ]] && {
args=(
'exit[exit on errors writing to any output]'
'exit-nopipe[exit on errors writing to non-pipes]'
'warn[warn on errors writing to any output]'
'warn-nopipe[warn on errors writing to non-pipes]'
)
_values 'error mode' $args && ret=0
}
return ret