Add completion for rmlint
This commit is contained in:
		
							parent
							
								
									a736cfe8e5
								
							
						
					
					
						commit
						f996cf93ed
					
				| 
						 | 
				
			
			@ -0,0 +1,407 @@
 | 
			
		|||
#compdef rmlint
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021 Github zsh-users - http://github.com/zsh-users
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, without written agreement and without
 | 
			
		||||
# licence or royalty fees, to use, copy, modify, and distribute this
 | 
			
		||||
# software and to distribute modified versions of this software for any
 | 
			
		||||
# purpose, provided that the above copyright notice and the following
 | 
			
		||||
# two paragraphs appear in all copies of this software.
 | 
			
		||||
#
 | 
			
		||||
# In no event shall the Zsh Development Group be liable to any party for
 | 
			
		||||
# direct, indirect, special, incidental, or consequential damages arising out
 | 
			
		||||
# of the use of this software and its documentation, even if the Zsh
 | 
			
		||||
# Development Group have been advised of the possibility of such damage.
 | 
			
		||||
#
 | 
			
		||||
# The Zsh Development Group specifically disclaim any warranties, including,
 | 
			
		||||
# but not limited to, the implied warranties of merchantability and fitness
 | 
			
		||||
# for a particular purpose.  The software provided hereunder is on an "as is"
 | 
			
		||||
# basis, and the Zsh Development Group have no obligation to provide
 | 
			
		||||
# maintenance, support, updates, enhancements, or modifications.
 | 
			
		||||
#
 | 
			
		||||
# Description
 | 
			
		||||
# -----------
 | 
			
		||||
#
 | 
			
		||||
# Zsh completion for rmlint 2.10.1 (https://github.com/sahib/rmlint)
 | 
			
		||||
#
 | 
			
		||||
# Authors
 | 
			
		||||
# -------
 | 
			
		||||
#
 | 
			
		||||
# * oxiedi (https://github.com/oxiedi)
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_types] )) ||
 | 
			
		||||
_rmlint_types() {
 | 
			
		||||
  compset -P '*[+-]'
 | 
			
		||||
  # FIXME: all values before `-` are swallowed by `*`, which breaks deduplication of the swallowed values
 | 
			
		||||
  # TODO: respect `prefix-needed`
 | 
			
		||||
  _values -s ',' 'list [defaults]' \
 | 
			
		||||
    'all[enables all lint types]' \
 | 
			
		||||
    'defaults[enables all lint types, but nonstripped]' \
 | 
			
		||||
    'minimal[defaults minus emptyfiles and emptydirs]' \
 | 
			
		||||
    'minimaldirs[defaults minus emptyfiles, emptydirs and duplicates, but with duplicatedirs]' \
 | 
			
		||||
    'none[disable all lint types]' \
 | 
			
		||||
    '(badids bi)'{badids,bi}'[find files with bad UID, GID or both]' \
 | 
			
		||||
    '(badlinks bl)'{badlinks,bl}'[find bad symlinks pointing nowhere valid]' \
 | 
			
		||||
    '(emptydirs ed)'{emptydirs,ed}'[find empty directories]' \
 | 
			
		||||
    '(emptyfiles ef)'{emptyfiles,ef}'[find empty files]' \
 | 
			
		||||
    '(nonstripped ns)'{nonstripped,ns}'[find nonstripped binaries]' \
 | 
			
		||||
    '(duplicates df)'{duplicates,df}'[find duplicate files]' \
 | 
			
		||||
    '(duplicatedirs dd)'{duplicatedirs,dd}'[find duplicate directories (This is the same -D!)]'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[__rmlint_setup_formatter_descriptions] )) ||
 | 
			
		||||
__rmlint_setup_formatter_descriptions() {
 | 
			
		||||
  typeset -gA formatter_descriptions=(
 | 
			
		||||
    csv         'output all found lint as comma-separated-value list'
 | 
			
		||||
    sh          'output all found lint as shell script'
 | 
			
		||||
    json        'print a JSON-formatted dump of all found reports'
 | 
			
		||||
    py          'outputs a python script and a JSON document, just like the json formatter'
 | 
			
		||||
    uniques     'outputs all unique paths found during the run, one path per line'
 | 
			
		||||
    stamp       'outputs a timestamp of the time rmlint was run'
 | 
			
		||||
    progressbar 'shows a progressbar'
 | 
			
		||||
    pretty      'shows all found items in realtime nicely colored'
 | 
			
		||||
    summary     'shows counts of files and their respective size after the run. Also list all written output files'
 | 
			
		||||
    fdupes      'prints an output similar to the popular duplicate finder fdupes(1)'
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_output] )) ||
 | 
			
		||||
_rmlint_output() {
 | 
			
		||||
  local -A formatter_descriptions
 | 
			
		||||
  __rmlint_setup_formatter_descriptions
 | 
			
		||||
  if compset -P "(${(kj:|:)formatter_descriptions}):"; then
 | 
			
		||||
    _alternative \
 | 
			
		||||
      'files:file:_files' \
 | 
			
		||||
      'outputs:output:(stdout stderr)'
 | 
			
		||||
  else
 | 
			
		||||
    local -a outputs
 | 
			
		||||
    local f d
 | 
			
		||||
    for f d in ${(kv)formatter_descriptions}; do
 | 
			
		||||
      outputs+=( "$f:$d" )
 | 
			
		||||
    done
 | 
			
		||||
    _describe -t outputs 'output' outputs -S ':' -q
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_config] )) ||
 | 
			
		||||
_rmlint_config() {
 | 
			
		||||
  local -A formatter_descriptions
 | 
			
		||||
  __rmlint_setup_formatter_descriptions
 | 
			
		||||
  unset 'formatter_descriptions['{py,pretty,summary}']'
 | 
			
		||||
  local -a match mbegin mend
 | 
			
		||||
  if compset -P "(#b)(${(kj:|:)formatter_descriptions}):"; then
 | 
			
		||||
    case $match[1] in
 | 
			
		||||
    (csv)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'no_header[do not write a first line describing the column headers]' \
 | 
			
		||||
        'unique[include unique files in the output]'
 | 
			
		||||
      ;;
 | 
			
		||||
    (sh)
 | 
			
		||||
      local context state state_descr line
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'cmd[specify a user defined command to run on duplicates]: :_cmdstring' \
 | 
			
		||||
        'handler[define a comma separated list of handlers to try on duplicate files in that given order until one handler succeeds]:handler:->handler' \
 | 
			
		||||
        'link[shortcut for -c sh:handler=clone,reflink,hardlink,symlink]' \
 | 
			
		||||
        'hardlink[shortcut for -c sh:handler=hardlink,symlink]' \
 | 
			
		||||
        'symlink[shortcut for -c sh:handler=symlink]'
 | 
			
		||||
      case $state in
 | 
			
		||||
      (handler)
 | 
			
		||||
        _values -s ',' $state_descr \
 | 
			
		||||
          'clone[try to clone both files with the FIDEDUPERANGE ioctl(3p) (or BTRFS_IOC_FILE_EXTENT_SAME on older kernels)]' \
 | 
			
		||||
          'reflink[try to reflink the duplicate file to the original]' \
 | 
			
		||||
          'hardlink[replace the duplicate file with a hardlink to the original file]' \
 | 
			
		||||
          'symlink[tries to replace the duplicate file with a symbolic link to the original]' \
 | 
			
		||||
          'remove[remove the file using rm -rf]' \
 | 
			
		||||
          'usercmd[use the provided user defined command (-c sh:cmd=something)]'
 | 
			
		||||
        ;;
 | 
			
		||||
      esac
 | 
			
		||||
      ;;
 | 
			
		||||
    (json)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'unique[include unique files in the output]' \
 | 
			
		||||
        'no_header[print the header with metadata]:boolean [true]:(false true)' \
 | 
			
		||||
        'no_footer[print the footer with statistics]:boolean [true]:(false true)' \
 | 
			
		||||
        'oneline[print one json document per line]:boolean [false]:(true false)'
 | 
			
		||||
      ;;
 | 
			
		||||
    (uniques)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'print0[do not put newlines between paths but zero bytes]'
 | 
			
		||||
      ;;
 | 
			
		||||
    (stamp)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'iso8601[write an ISO8601 formatted timestamps or seconds since epoch]:boolean:(true false)'
 | 
			
		||||
      ;;
 | 
			
		||||
    (progressbar)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'update_interval[number of milliseconds to wait between updates (default: 50)]: :_guard "[0-9]#" "update interval (milliseconds) [50]"' \
 | 
			
		||||
        'ascii[do not attempt to use unicode characters, which might not be supported by some terminals]' \
 | 
			
		||||
        'fancy[use a more fancy style for the progressbar]'
 | 
			
		||||
      ;;
 | 
			
		||||
    (fdupes)
 | 
			
		||||
      _values 'option' \
 | 
			
		||||
        'omitfirst[omits the first line of each set of duplicates]' \
 | 
			
		||||
        'sameline[does not print newlines between files, only a space]'
 | 
			
		||||
      ;;
 | 
			
		||||
    esac
 | 
			
		||||
  else
 | 
			
		||||
    local -a formatters
 | 
			
		||||
    local f d
 | 
			
		||||
    for f d in ${(kv)formatter_descriptions}; do
 | 
			
		||||
      formatters+=( "$f:$d" )
 | 
			
		||||
    done
 | 
			
		||||
    _describe -t formatters 'formatter' formatters -S ':'
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_algorithm] )) ||
 | 
			
		||||
_rmlint_algorithm() {
 | 
			
		||||
  local -a tmp=( sha{1,256,512} sha3-{256,384,512} blake{2s,2b,2sp,2bp} highway{64,128,256} )
 | 
			
		||||
  _alternative \
 | 
			
		||||
    '512bit-algorithms:512-bit:(blake2b blake2bp sha3-512 sha512)' \
 | 
			
		||||
    '384bit-algorithms:384-bit:(sha3-384)' \
 | 
			
		||||
    '256bit-algorithms:256-bit:(blake2s blake2sp sha3-256 sha256 highway256 metro256 metrocrc256)' \
 | 
			
		||||
    '160bit-algorithms:160-bit:(sha1)' \
 | 
			
		||||
    '128bit-algorithms:128-bit:(md5 murmur metro metrocrc)' \
 | 
			
		||||
    '64bit-algorithms:64-bit:(highway64 xxhash)' \
 | 
			
		||||
    "cryptographic-algorithms:cryptographic:($tmp)" \
 | 
			
		||||
    'non-cryptographic-algorithms:non-cryptographic:(metro metro256 xxhash murmur)' \
 | 
			
		||||
    'not-useful-algorithms:not-useful:(cumulative paranoid ext)'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_sort] )) ||
 | 
			
		||||
_rmlint_sort() {
 | 
			
		||||
  local -A letter_descriptions=(
 | 
			
		||||
    s 'sort by size of group'
 | 
			
		||||
    a 'sort alphabetically by the basename of the original'
 | 
			
		||||
    m 'sort by mtime of the original'
 | 
			
		||||
    p 'sort by path-index of the original'
 | 
			
		||||
    o 'sort by natural found order (might be different on each run)'
 | 
			
		||||
    n 'sort by number of files in the group'
 | 
			
		||||
  )
 | 
			
		||||
  local -a letters
 | 
			
		||||
  local l d
 | 
			
		||||
  for l d in ${(kv)letter_descriptions}; do
 | 
			
		||||
    letters+=( "${l}[$d]" "${(U)l}[$d (in reverse order)]" )
 | 
			
		||||
  done
 | 
			
		||||
  _values -s '' 'order' $letters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[__rmlint_describe_multipliers] )) ||
 | 
			
		||||
__rmlint_describe_multipliers() {
 | 
			
		||||
  local -a multipliers=(
 | 
			
		||||
    'C:1^1'
 | 
			
		||||
    'W:2^1'
 | 
			
		||||
    'B:512^1'
 | 
			
		||||
    'K:1000^1'
 | 
			
		||||
    'KB:1024^1'
 | 
			
		||||
    'M:1000^2'
 | 
			
		||||
    'MB:1024^2'
 | 
			
		||||
    'G:1000^3'
 | 
			
		||||
    'GB:1024^3'
 | 
			
		||||
    'T:1000^4'
 | 
			
		||||
    'TB:1024^4'
 | 
			
		||||
    'P:1000^5'
 | 
			
		||||
    'PB:1024^5'
 | 
			
		||||
    'E:1000^6'
 | 
			
		||||
    'EB:1024^6'
 | 
			
		||||
  )
 | 
			
		||||
  _describe -t multiplier 'multiplier' multipliers "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[__rmlint_multipliers] )) ||
 | 
			
		||||
__rmlint_multipliers() {
 | 
			
		||||
  compset -P '[0-9]##' || return
 | 
			
		||||
  __rmlint_describe_multipliers "$@"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_size] )) ||
 | 
			
		||||
_rmlint_size() {
 | 
			
		||||
  ! __rmlint_multipliers && [[ -z $PREFIX ]] && _message -e "${1:-size}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_size_range] )) ||
 | 
			
		||||
_rmlint_size_range() {
 | 
			
		||||
  if compset -P '[0-9]##'; then
 | 
			
		||||
    if compset -P '(C|W|B|K|KB|M|MB|G|GB|T|TB|P|PB|E|EB)-'; then
 | 
			
		||||
      _rmlint_size 'max'
 | 
			
		||||
    else
 | 
			
		||||
      __rmlint_describe_multipliers -S '-' -q
 | 
			
		||||
    fi
 | 
			
		||||
  elif [[ -z $PREFIX ]]; then
 | 
			
		||||
    _message -e 'min'
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_iso8601_or_unix_timestamp] )) ||
 | 
			
		||||
_rmlint_iso8601_or_unix_timestamp() {
 | 
			
		||||
  _alternative \
 | 
			
		||||
    'dates:iso8601_timestamp: _dates -f "%FT%T"' \
 | 
			
		||||
    'seconds:unix_timestamp:_guard "[0-9]#" "seconds since epoch"'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_rank] )) ||
 | 
			
		||||
_rmlint_rank() {
 | 
			
		||||
  # TODO: {r,R,x,X}<regex>
 | 
			
		||||
  _values -s '' 'criteria [pOma]' \
 | 
			
		||||
    'm[keep lowest mtime (oldest)]'             'M[keep highest mtime (newest)]' \
 | 
			
		||||
    'a[keep first alphabetically]'              'A[keep last alphabetically]' \
 | 
			
		||||
    'p[keep first named path]'                  'P[keep last named path]' \
 | 
			
		||||
    'd[keep path with lowest depth]'            'D[keep path with highest depth]' \
 | 
			
		||||
    'l[keep path with shortest basename]'       'L[keep path with longest basename]' \
 | 
			
		||||
    'r[keep paths matching regex]'              'R[keep path not matching regex]' \
 | 
			
		||||
    'x[keep basenames matching regex]'          'X[keep basenames not matching regex]' \
 | 
			
		||||
    'h[keep file with lowest hardlink count]'   'H[keep file with highest hardlink count]' \
 | 
			
		||||
    'o[keep file with lowest number of hardlinks outside of the paths traversed by rmlint]' \
 | 
			
		||||
    'O[keep file with highest number of hardlinks outside of the paths traversed by rmlint]'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_percent] )) ||
 | 
			
		||||
_rmlint_percent() {
 | 
			
		||||
  if compset -P '(100|[1-9][0-9]|[1-9])'; then
 | 
			
		||||
    compadd "$@" -- '%'
 | 
			
		||||
  elif [[ -z $PREFIX ]]; then
 | 
			
		||||
    _message -e 'percent%%'
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_clamp] )) ||
 | 
			
		||||
_rmlint_clamp() {
 | 
			
		||||
  _alternative \
 | 
			
		||||
    "factor: :_guard '((|0)(|.[0-9]#)|1(|.0#))' 'fac.tor [$1]'" \
 | 
			
		||||
    'percent:percent%%:_rmlint_percent' \
 | 
			
		||||
    'multiplier:offset: _rmlint_size "offset"'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(( $+functions[_rmlint_files_or_separator] )) ||
 | 
			
		||||
_rmlint_files_or_separator() {
 | 
			
		||||
  if (( $words[(i)-] < CURRENT )); then
 | 
			
		||||
    [[ -z $words[CURRENT] ]] && compadd "$@" -S '' -- -
 | 
			
		||||
    return
 | 
			
		||||
  fi
 | 
			
		||||
  local -a alts=( 'files:file:_files' )
 | 
			
		||||
  (( $line[(I)//] || $+opt_args[--equal] )) || alts+=( 'separator:separator:(//)' )
 | 
			
		||||
  _alternative $alts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_rmlint() {
 | 
			
		||||
  local curcontext="$curcontext" state state_descr
 | 
			
		||||
  local -a line
 | 
			
		||||
  local -i ret=1
 | 
			
		||||
  typeset -A opt_args
 | 
			
		||||
 | 
			
		||||
  _arguments -s -w -C : \
 | 
			
		||||
    '(-T --types)'{-T,--types}'=[configure the types of lint rmlint will look for]: :_rmlint_types' \
 | 
			
		||||
    '*'{-o,--output}'=[configure the way rmlint outputs its results]:spec:_rmlint_output' \
 | 
			
		||||
    '*'{-O,--add-output}'=[configure the way rmlint outputs its results (preserve defaults)]:spec:_rmlint_output' \
 | 
			
		||||
    '*'{-c,--config}'=[configure a format]:spec:_rmlint_config' \
 | 
			
		||||
    '(-z --perms)'{-z,--perms}'=[only look into file if it is readable, writable or executable by the current user]: :_values -s "" perms r w x' \
 | 
			
		||||
    '(-a --algorithm)'{-a,--algorithm}'=[choose the algorithm to use for finding duplicate files]:algo:_rmlint_algorithm' \
 | 
			
		||||
    '*'{-p,--paranoid}'[increase the paranoia of rmlint'\''s duplicate algorithm]' \
 | 
			
		||||
    '*'{-P,--less-paranoid}'[decrease the paranoia of rmlint'\''s duplicate algorithm]' \
 | 
			
		||||
    '*'{-v,--loud}'[increase the verbosity]' \
 | 
			
		||||
    '*'{-V,--quiet}'[decrease the verbosity]' \
 | 
			
		||||
    '(-g --progress)'{-g,--progress}'[show a progressbar with sane defaults]' \
 | 
			
		||||
    '(-G --no-progress)'{-G,--no-progress}'[do not show a progressbar with sane defaults (default)]' \
 | 
			
		||||
    '(-D --merge-directories)'{-D,--merge-directories}'[makes rmlint use a special mode where all found duplicates are collected and checked if whole directory trees are duplicates]' \
 | 
			
		||||
    '(-j --honour-dir-layout)'{-j,--honour-dir-layout}'[only recognize directories as duplicates that have the same path layout]' \
 | 
			
		||||
    '(-y --sort-by)'{-y,--sort-by}'=[during output, sort the found duplicate groups by criteria described by order]:order:_rmlint_sort' \
 | 
			
		||||
    '(-w --with-color)'{-w,--with-color}'[use color escapes for pretty output (default)]' \
 | 
			
		||||
    '(-W --no-with-color)'{-W,--no-with-color}'[disable color escapes for pretty output]' \
 | 
			
		||||
    '(- *)'{-h,--help}'[show a shorter reference help text]' \
 | 
			
		||||
    '(- *)--help-all[show all help options]' \
 | 
			
		||||
    '(- *)'{-H,--show-man}'[show the full man page]' \
 | 
			
		||||
    '(- *)--version[print the version of rmlint]' \
 | 
			
		||||
    '(-s --size)'{-s,--size}'=[only consider files as duplicates in a certain size range]:range:_rmlint_size_range' \
 | 
			
		||||
    '(-d --max-depth)'{-d,--max-depth}'=[only recurse up to this depth]: :_guard "[0-9]#" "depth"' \
 | 
			
		||||
    '(-l --hardlinked)'{-l,--hardlinked}'[hardlinked files are treated as duplicates (default)]' \
 | 
			
		||||
    '--keep-hardlinked[rmlint will not delete any files that are hardlinked to an original in their respective group]' \
 | 
			
		||||
    '(-L --no-hardlinked)'{-L,--no-hardlinked}'[only one file (of a set of hardlinked files) is considered, all the others are ignored]' \
 | 
			
		||||
    '(-f --followlinks)'{-f,--followlinks}'[follow symbolic links]' \
 | 
			
		||||
    '(-F --no-followlinks)'{-F,--no-followlinks}'[ignore symbolic links completely]' \
 | 
			
		||||
    '(-@ --see-symlinks)'{-@,--see-symlinks}'[see symlinks and treats them like small files with the path to their target in them (default)]' \
 | 
			
		||||
    '(-x --no-crossdev)'{-x,--no-crossdev}'[stay always on the same device]' \
 | 
			
		||||
    '(-X --crossdev)'{-X,--crossdev}'[allow crossing mountpoints (default)]' \
 | 
			
		||||
    '(-r --hidden)'{-r,--hidden}'[traverse hidden directories]' \
 | 
			
		||||
    '(-R --no-hidden)'{-R,--no-hidden}'[don'\''t traverse hidden directories (default)]' \
 | 
			
		||||
    '--partial-hidden[traverse duplicate hidden directories]' \
 | 
			
		||||
    '(-b --match-basename)'{-b,--match-basename}'[only consider those files as dupes that have the same basename]' \
 | 
			
		||||
    '(-B --unmatched-basename)'{-B,--unmatched-basename}'[only consider those files as dupes that do not share the same basename]' \
 | 
			
		||||
    '(-e --match-with-extension)'{-e,--match-with-extension}'[only consider those files as dupes that have the same file extension]' \
 | 
			
		||||
    '(-E --no-match-with-extension)'{-E,--no-match-with-extension}'[don'\'t' consider those files as dupes that have the same file extension (default)]' \
 | 
			
		||||
    '(-i --match-without-extension)'{-i,--match-without-extension}'[only consider those files as dupes that have the same basename minus the file extension]' \
 | 
			
		||||
    '(-I --no-match-without-extension)'{-I,--no-match-without-extension}'[don'\'t' consider those files as dupes that have the same basename minus the file extension (default)]' \
 | 
			
		||||
    '(-n --newer-than-stamp)'{-n,--newer-than-stamp}'=[only consider files (and their size siblings for duplicates) newer than a certain modification time (mtime)]:timestamp_filename:_files' \
 | 
			
		||||
    '(-N --newer-than)'{-N,--newer-than}'=[don'\'t' consider files (and their size siblings for duplicates) newer than a certain modification time (mtime)]: :_rmlint_iso8601_or_unix_timestamp' \
 | 
			
		||||
    '(-k --keep-all-tagged)'{-k,--keep-all-tagged}'[don'\''t delete any duplicates that are in tagged paths]' \
 | 
			
		||||
    '(-K --keep-all-untagged)'{-K,--keep-all-untagged}'[don'\''t delete any duplicates that are in non-tagged paths]' \
 | 
			
		||||
    '(-m --must-match-tagged)'{-m,--must-match-tagged}'[only look for duplicates of which at least one is in one of the tagged paths]' \
 | 
			
		||||
    '(-M --must-match-untagged)'{-M,--must-match-untagged}'[only look for duplicates of which at least one is in one of the non-tagged paths]' \
 | 
			
		||||
    '(-S --rank-by)'{-S,--rank-by}'=[sort the files in a group of duplicates into originals and duplicates by one or more criteria]: :_rmlint_rank' \
 | 
			
		||||
    '--replay[read an existing json file and re-output it]' \
 | 
			
		||||
    '(-C --xattr)'{-C,--xattr}'[shortcut for --xattr-read, --xattr-write, --write-unfinished]' \
 | 
			
		||||
    '--xattr-read[read cached checksums from the extended file attributes]' \
 | 
			
		||||
    '--xattr-write[write cached checksums from the extended file attributes]' \
 | 
			
		||||
    '--xattr-clear[clear cached checksums from the extended file attributes]' \
 | 
			
		||||
    '(-U --write-unfinished)'{-U,--write-unfinished}'[include files in output that have not been hashed fully, i.e. files that do not appear to have a duplicate]' \
 | 
			
		||||
    '(-t --threads)'{-t,--threads}'=[the number of threads to use during file tree traversal and hashing (default: 16)]: :_guard "[0-9]#" "threads [16]"' \
 | 
			
		||||
    '(-u --limit-mem)'{-u,--limit-mem}'=[apply a maximum number of memory to use for hashing and --paranoid]:size: _rmlint_size' \
 | 
			
		||||
    '(-q --clamp-low)'{-q,--clamp-low}'=[only look at the content of files in the range of from low to (including) high (default: 0)]: : _rmlint_clamp 0' \
 | 
			
		||||
    '(-Q --clamp-top)'{-Q,--clamp-top}'=[only look at the content of files in the range of from low to (including) high (default: 1.0)]: : _rmlint_clamp 1.0' \
 | 
			
		||||
    '(-Z --mtime-window)'{-Z,--mtime-window}'=[only consider those files as duplicates that have the same content and the same modification time (mtime) within a certain window of T seconds (default: -1)]: :_guard "[0-9]#" "mtime window (seconds) [-1]"' \
 | 
			
		||||
    '--with-fiemap[enable reading the file extents on rotational disk in order to optimize disk access patterns (default)]' \
 | 
			
		||||
    '--without-fiemap[disable reading the file extents on rotational disk in order to optimize disk access patterns]' \
 | 
			
		||||
    '--gui[start the optional graphical frontend to rmlint called Shredder]:*: :->gui' \
 | 
			
		||||
    '--hash[make rmlint work as a multi-threaded file hash utility]:*: :->hash' \
 | 
			
		||||
    '--equal[check if the paths given on the commandline all have equal content]: :_rmlint_files_or_separator' \
 | 
			
		||||
    '(-0 --stdin0)'{-0,--stdin0}'[read null-separated file list from stdin]' \
 | 
			
		||||
    '--backup[do create backups of previous result files]' \
 | 
			
		||||
    '--no-backup[do not create backups of previous result files]' \
 | 
			
		||||
    '--dedupe[dedupe matching extents from source to dest (if filesystem supports)]:*:: := ->dedupe' \
 | 
			
		||||
    '--dedupe-xattr[check extended attributes to see if the file is already deduplicated]' \
 | 
			
		||||
    '--dedupe-readonly[(--dedupe option) even dedupe read-only snapshots (needs root)]' \
 | 
			
		||||
    '--is-reflink[test if two files are reflinks (share same data extents)]:*:: := ->reflink' \
 | 
			
		||||
    '*: :_rmlint_files_or_separator' && return
 | 
			
		||||
 | 
			
		||||
  case $state in
 | 
			
		||||
  (gui)
 | 
			
		||||
    _arguments -s -w : \
 | 
			
		||||
      '(- *)'{-h,--help}'[show help options]' \
 | 
			
		||||
      {-a,--add-location}'[add locations to locations view]' \
 | 
			
		||||
      {-s,--scan}'[add location to scan (as untagged path)]' \
 | 
			
		||||
      {-S,--scan-tagged}'[add location to scan (as tagged path)]' \
 | 
			
		||||
      {-l,--load-script}'[show `script` in editor view]' \
 | 
			
		||||
      '*'{-v,--verbose}'[be more verbose]' \
 | 
			
		||||
      '*'{-V,--less-verbose}'[be less verbose]' \
 | 
			
		||||
      {-c,--show-settings}'[show the settings view]' \
 | 
			
		||||
      '(- *)--version[show the version of Shredder]' && ret=0
 | 
			
		||||
    ;;
 | 
			
		||||
  (hash)
 | 
			
		||||
    _arguments -s -w : \
 | 
			
		||||
      '(- *)'{-h,--help}'[show help options]' \
 | 
			
		||||
      {-a,--algorithm}'[digest type \[bLAKE2B\]]:type:_rmlint_algorithm' \
 | 
			
		||||
      {-t,--num-threads}'[number of hashing threads \[8\]]: :_guard "[0-9]#" "threads [8]"' \
 | 
			
		||||
      {-b,--buffer-mbytes}'[megabytes read buffer \[256 MB\]]: :_guard "[0-9]#" "buffer (MB) [256]"' \
 | 
			
		||||
      {-i,--ignore-order}'[print hashes in order completed, not in order entered (reduces memory usage)]' \
 | 
			
		||||
      '*:file:_files' && ret=0
 | 
			
		||||
    ;;
 | 
			
		||||
  (dedupe)
 | 
			
		||||
    _arguments -s -w : \
 | 
			
		||||
      '-r[enable deduplication of read-only \[btrfs\] snapshots (requires root)]' \
 | 
			
		||||
      '(-V)*-v' \
 | 
			
		||||
      '(-v)*-V' \
 | 
			
		||||
      ':src:_files' \
 | 
			
		||||
      ':dst:_files' && ret=0
 | 
			
		||||
    ;;
 | 
			
		||||
  (reflink)
 | 
			
		||||
    _arguments -s -w : \
 | 
			
		||||
      '(-V)*-v' \
 | 
			
		||||
      '(-v)*-V' \
 | 
			
		||||
      ':file1:_files' \
 | 
			
		||||
      ':file2:_files' && ret=0
 | 
			
		||||
    ;;
 | 
			
		||||
  esac
 | 
			
		||||
 | 
			
		||||
  return ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_rmlint "$@"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
#compdef rmlint.sh -P rmlint.*.sh
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021 Github zsh-users - http://github.com/zsh-users
 | 
			
		||||
#
 | 
			
		||||
# Permission is hereby granted, without written agreement and without
 | 
			
		||||
# licence or royalty fees, to use, copy, modify, and distribute this
 | 
			
		||||
# software and to distribute modified versions of this software for any
 | 
			
		||||
# purpose, provided that the above copyright notice and the following
 | 
			
		||||
# two paragraphs appear in all copies of this software.
 | 
			
		||||
#
 | 
			
		||||
# In no event shall the Zsh Development Group be liable to any party for
 | 
			
		||||
# direct, indirect, special, incidental, or consequential damages arising out
 | 
			
		||||
# of the use of this software and its documentation, even if the Zsh
 | 
			
		||||
# Development Group have been advised of the possibility of such damage.
 | 
			
		||||
#
 | 
			
		||||
# The Zsh Development Group specifically disclaim any warranties, including,
 | 
			
		||||
# but not limited to, the implied warranties of merchantability and fitness
 | 
			
		||||
# for a particular purpose.  The software provided hereunder is on an "as is"
 | 
			
		||||
# basis, and the Zsh Development Group have no obligation to provide
 | 
			
		||||
# maintenance, support, updates, enhancements, or modifications.
 | 
			
		||||
#
 | 
			
		||||
# Description
 | 
			
		||||
# -----------
 | 
			
		||||
#
 | 
			
		||||
# Zsh completion for shell scripts produced by rmlint (https://github.com/sahib/rmlint)
 | 
			
		||||
#
 | 
			
		||||
# Authors
 | 
			
		||||
# -------
 | 
			
		||||
#
 | 
			
		||||
# * oxiedi (https://github.com/oxiedi)
 | 
			
		||||
 | 
			
		||||
_arguments -s : \
 | 
			
		||||
  '(-)-h[show help message]' \
 | 
			
		||||
  '-d[do not ask before running]' \
 | 
			
		||||
  '-x[keep rmlint.sh; do not autodelete it]' \
 | 
			
		||||
  '-p[recheck that files are still identical before removing duplicates]' \
 | 
			
		||||
  '-r[allow deduplication of files on read-only btrfs snapshots (requires sudo)]' \
 | 
			
		||||
  '(-d -x)-n[do not perform any modifications, just print what would be done (implies -d and -x)]' \
 | 
			
		||||
  '-c[clean up empty directories while deleting duplicates]' \
 | 
			
		||||
  '-q[do not show progress]' \
 | 
			
		||||
  '-k[keep the timestamp of directories when removing duplicates]' \
 | 
			
		||||
  '-i[ask before deleting each file]'
 | 
			
		||||
		Loading…
	
		Reference in New Issue