1#compdef fd 2 3## 4# zsh completion function for fd 5# 6# Based on ripgrep completion function. 7# Originally based on code from the zsh-users project — see copyright notice 8# below. 9 10autoload -U is-at-least 11 12_fd() { 13 local curcontext="$curcontext" no='!' ret=1 14 local -a context line state state_descr _arguments_options fd_types fd_args 15 local -A opt_args 16 17 if is-at-least 5.2; then 18 _arguments_options=( -s -S ) 19 else 20 _arguments_options=( -s ) 21 fi 22 23 fd_types=( 24 {f,file}'\:"regular files"' 25 {d,directory}'\:"directories"' 26 {l,symlink}'\:"symbolic links"' 27 {e,empty}'\:"empty files or directories"' 28 {x,executable}'\:"executable (files)"' 29 {s,socket}'\:"sockets"' 30 {p,pipe}'\:"named pipes (FIFOs)"' 31 ) 32 33 # Do not complete rare options unless either the current prefix 34 # matches one of those options or the user has the `complete-all` 35 # style set. Note that this prefix check has to be updated manually to account 36 # for all of the potential negation options listed below! 37 if 38 # (--[bpsu]* => match all options marked with '$no') 39 [[ $PREFIX$SUFFIX == --[bopsu]* ]] || 40 zstyle -t ":complete:$curcontext:*" complete-all 41 then 42 no= 43 fi 44 45 # We make heavy use of argument groups here to prevent the option specs from 46 # growing unwieldy. These aren't supported in zsh <5.4, though, so we'll strip 47 # them out below if necessary. This makes the exclusions inaccurate on those 48 # older versions, but oh well — it's not that big a deal 49 fd_args=( 50 + '(hidden)' # hidden files 51 {-H,--hidden}'[search hidden files/directories]' 52 53 + '(no-ignore-full)' # all ignore files 54 '(no-ignore-partial)'{-I,--no-ignore}"[don't respect .(git|fd)ignore and global ignore files]" 55 $no'(no-ignore-partial)*'{-u,--unrestricted}'[alias for --no-ignore, when repeated also alias for --hidden]' 56 57 + no-ignore-partial # some ignore files 58 "(no-ignore-full --no-ignore-vcs)--no-ignore-vcs[don't respect .gitignore files]" 59 "!(no-ignore-full --no-global-ignore-file)--no-global-ignore-file[don't respect the global ignore file]" 60 61 + '(case)' # case-sensitivity 62 {-s,--case-sensitive}'[perform a case-sensitive search]' 63 {-i,--ignore-case}'[perform a case-insensitive search]' 64 65 + '(regex-pattern)' # regex-based search pattern 66 '(no-regex-pattern)--regex[perform a regex-based search (default)]' 67 68 + '(no-regex-pattern)' # non-regex-based search pattern 69 {-g,--glob}'[perform a glob-based search]' 70 {-F,--fixed-strings}'[treat pattern as literal string instead of a regex]' 71 72 + '(match-full)' # match against full path 73 {-p,--full-path}'[match the pattern against the full path instead of the basename]' 74 75 + '(follow)' # follow symlinks 76 {-L,--follow}'[follow symbolic links to directories]' 77 78 + '(abs-path)' # show absolute paths 79 '(long-listing)'{-a,--absolute-path}'[show absolute paths instead of relative paths]' 80 81 + '(null-sep)' # use null separator for output 82 '(long-listing)'{-0,--print0}'[separate search results by the null character]' 83 84 + '(long-listing)' # long-listing output 85 '(abs-path null-sep max-results exec-cmds)'{-l,--list-details}'[use a long listing format with file metadata]' 86 87 + '(max-results)' # max number of results 88 '(long-listing exec-cmds)--max-results=[limit number of search results to given count and quit]:count' 89 '(long-listing exec-cmds)-1[limit to a single search result and quit]' 90 91 + '(fs-errors)' # file-system errors 92 $no'--show-errors[enable the display of filesystem errors]' 93 94 + '(fs-traversal)' # file-system traversal 95 $no"--one-file-system[don't descend into directories on other file systems]" 96 '!--mount' 97 '!--xdev' 98 99 + dir-depth # directory depth 100 '(--exact-depth -d --max-depth)'{-d+,--max-depth=}'[set max directory depth to descend when searching]:depth' 101 '!(--exact-depth -d --max-depth)--maxdepth:depth' 102 '(--exact-depth --min-depth)--min-depth=[set directory depth to descend before start searching]:depth' 103 '(--exact-depth -d --max-depth --maxdepth --min-depth)--exact-depth=[only search at the exact given directory depth]:depth' 104 105 + prune # pruning 106 "--prune[don't traverse into matching directories]" 107 108 + filter-misc # filter search 109 '*'{-t+,--type=}"[filter search by type]:type:(($fd_types))" 110 '*'{-e+,--extension=}'[filter search by file extension]:extension' 111 '*'{-E+,--exclude=}'[exclude files/directories that match the given glob pattern]:glob pattern' 112 '*'{-S+,--size=}'[limit search by file size]:size limit:->size' 113 '(-o --owner)'{-o+,--owner=}'[filter by owning user and/or group]:owner and/or group:->owner' 114 115 + ignore-file # extra ignore files 116 '*--ignore-file=[add a custom, low-precedence ignore-file with .gitignore format]: :_files' 117 118 + '(filter-mtime-newer)' # filter by files modified after than 119 '--changed-within=[limit search to files/directories modified within the given date/duration]:date or duration' 120 '!--change-newer-than=:date/duration' 121 '!--newer=:date/duration' 122 123 + '(filter-mtime-older)' # filter by files modified before than 124 '--changed-before=[limit search to files/directories modified before the given date/duration]:date or duration' 125 '!--change-older-than=:date/duration' 126 '!--older=:date/duration' 127 128 + '(color)' # colorize output 129 {-c+,--color=}'[declare when to colorize search results]:when to colorize:(( 130 auto\:"show colors if the output goes to an interactive console (default)" 131 never\:"do not use colorized output" 132 always\:"always use colorized output" 133 ))' 134 135 + '(threads)' 136 {-j+,--threads=}'[set the number of threads for searching and executing]:number of threads' 137 138 + '(exec-cmds)' # execute command 139 '(long-listing max-results)'{-x+,--exec=}'[execute command for each search result]:command: _command_names -e:*\;::program arguments: _normal' 140 '(long-listing max-results)'{-X+,--exec-batch=}'[execute command for all search results at once]:command: _command_names -e:*\;::program arguments: _normal' 141 '(long-listing max-results)--batch-size=[max number of args for each -X call]:size' 142 143 + other 144 '!(--max-buffer-time)--max-buffer-time=[set amount of time to buffer before showing output]:time (ms)' 145 146 + '(about)' # about flags 147 '(: * -)'{-h,--help}'[display help message]' 148 '(: * -)'{-v,--version}'[display version information]' 149 150 + path-sep # set path separator for output 151 $no'(--path-separator)--path-separator=[set the path separator to use when printing file paths]:path separator' 152 153 + search-path 154 $no'(--base-directory)--base-directory=[change the current working directory to the given path]:directory:_files -/' 155 $no'(*)*--search-path=[set search path (instead of positional <path> arguments)]:directory:_files -/' 156 157 + args # positional arguments 158 '1: :_guard "^-*" pattern' 159 '(--search-path)*:directory:_files -/' 160 ) 161 162 # Strip out argument groups where unsupported (see above) 163 is-at-least 5.4 || 164 fd_args=( ${(@)args:#(#i)(+|[a-z0-9][a-z0-9_-]#|\([a-z0-9][a-z0-9_-]#\))} ) 165 166 _arguments $_arguments_options : $fd_args && ret=0 167 168 case ${state} in 169 owner) 170 compset -P '(\\|)\!' 171 if compset -P '*:'; then 172 _groups && ret=0 173 else 174 if 175 compset -S ':*' || 176 # Do not add the colon suffix when completing "!user<TAB> 177 # (with a starting double-quote) otherwise pressing tab again 178 # after the inserted colon "!user:<TAB> will complete history modifiers 179 [[ $IPREFIX == (\\|\!)* && ($QIPREFIX == \"* && -z $QISUFFIX) ]] 180 then 181 _users && ret=0 182 else 183 local q 184 # Since quotes are needed when using the negation prefix !, 185 # automatically remove the colon suffix also when closing the quote 186 if [[ $QIPREFIX == [\'\"]* ]]; then 187 q=${QIPREFIX:0:1} 188 fi 189 _users -r ": \t\n\-$q" -S : && ret=0 190 fi 191 fi 192 ;; 193 194 size) 195 if compset -P '[-+][0-9]##'; then 196 local -a suff=( 197 'B:bytes' 198 'K:kilobytes (10^3 = 1000 bytes)' 199 'M:megabytes (10^6 = 1000^2 bytes)' 200 'G:gigabytes (10^9 = 1000^3 bytes)' 201 'T:terabytes (10^12 = 1000^4 bytes)' 202 'Ki:kibibytes ( 2^10 = 1024 bytes)' 203 'Mi:mebibytes ( 2^20 = 1024^2 bytes)' 204 'Gi:gigibytes ( 2^30 = 1024^3 bytes)' 205 'Ti:tebibytes ( 2^40 = 1024^4 bytes)' 206 ) 207 _describe -t units 'size limit units' suff -V 'units' 208 elif compset -P '[-+]'; then 209 _message -e 'size limit number (full format: <+-><number><unit>)' 210 else 211 _values 'size limit prefix (full format: <prefix><number><unit>)' \ 212 '\+[file size must be greater or equal to]'\ 213 '-[file size must be less than or equal to]' && ret=0 214 fi 215 ;; 216 esac 217 218 return ret 219} 220 221_fd "$@" 222 223# ------------------------------------------------------------------------------ 224# Copyright (c) 2011 GitHub zsh-users - http://github.com/zsh-users 225# All rights reserved. 226# 227# Redistribution and use in source and binary forms, with or without 228# modification, are permitted provided that the following conditions are met: 229# * Redistributions of source code must retain the above copyright 230# notice, this list of conditions and the following disclaimer. 231# * Redistributions in binary form must reproduce the above copyright 232# notice, this list of conditions and the following disclaimer in the 233# documentation and/or other materials provided with the distribution. 234# * Neither the name of the zsh-users nor the 235# names of its contributors may be used to endorse or promote products 236# derived from this software without specific prior written permission. 237# 238# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 239# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 240# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 241# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY 242# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 243# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 244# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 245# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 246# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 247# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248# ------------------------------------------------------------------------------ 249# Description 250# ----------- 251# 252# Completion script for fd 253# 254# ------------------------------------------------------------------------------ 255# Authors 256# ------- 257# 258# * smancill (https://github.com/smancill) 259# 260# ------------------------------------------------------------------------------ 261 262# Local Variables: 263# mode: shell-script 264# coding: utf-8-unix 265# indent-tabs-mode: nil 266# sh-indentation: 2 267# sh-basic-offset: 2 268# End: 269# vim: ft=zsh sw=2 ts=2 et 270