_ripgrep 17.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
#compdef rg

##
# zsh completion function for ripgrep
#
# Originally based on code from the zsh-users project — see copyright notice
# below.

_rg() {
  local curcontext=$curcontext no='!' descr ret=1
  local -a context line state state_descr args tmp suf
  local -A opt_args

  # ripgrep has many options which negate the effect of a more common one — for
  # example, `--no-column` to negate `--column`, and `--messages` to negate
  # `--no-messages`. There are so many of these, and they're so infrequently
  # used, that some users will probably find it irritating if they're completed
  # indiscriminately, so let's not do that unless either the current prefix
  # matches one of those negation options or the user has the `complete-all`
  # style set. Note that this prefix check has to be updated manually to account
  # for all of the potential negation options listed below!
  if
    # We also want to list all of these options during testing
    [[ $_RG_COMPLETE_LIST_ARGS == (1|t*|y*) ]] ||
    # (--[imnp]* => --ignore*, --messages, --no-*, --pcre2-unicode)
    [[ $PREFIX$SUFFIX == --[imnp]* ]] ||
    zstyle -t ":complete:$curcontext:*" complete-all
  then
    no=
  fi

  # We make heavy use of argument groups here to prevent the option specs from
  # growing unwieldy. These aren't supported in zsh <5.4, though, so we'll strip
  # them out below if necessary. This makes the exclusions inaccurate on those
  # older versions, but oh well — it's not that big a deal
  args=(
    + '(exclusive)' # Misc. fully exclusive options
    '(: * -)'{-h,--help}'[display help information]'
    '(: * -)'{-V,--version}'[display version information]'

    + '(buffered)' # buffering options
    '--line-buffered[force line buffering]'
    $no"--no-line-buffered[don't force line buffering]"
    '--block-buffered[force block buffering]'
    $no"--no-block-buffered[don't force block buffering]"

    + '(case)' # Case-sensitivity options
    {-i,--ignore-case}'[search case-insensitively]'
    {-s,--case-sensitive}'[search case-sensitively]'
    {-S,--smart-case}'[search case-insensitively if pattern is all lowercase]'

    + '(context-a)' # Context (after) options
    '(context-c)'{-A+,--after-context=}'[specify lines to show after each match]:number of lines'

    + '(context-b)' # Context (before) options
    '(context-c)'{-B+,--before-context=}'[specify lines to show before each match]:number of lines'

    + '(context-c)' # Context (combined) options
    '(context-a context-b)'{-C+,--context=}'[specify lines to show before and after each match]:number of lines'

    + '(column)' # Column options
    '--column[show column numbers for matches]'
    $no"--no-column[don't show column numbers for matches]"

    + '(count)' # Counting options
    {-c,--count}'[only show count of matching lines for each file]'
    '--count-matches[only show count of individual matches for each file]'

    + '(encoding)' # Encoding options
    {-E+,--encoding=}'[specify text encoding of files to search]: :_rg_encodings'
    $no'--no-encoding[use default text encoding]'

    + file # File-input options
    '(1)*'{-f+,--file=}'[specify file containing patterns to search for]: :_files'

    + '(file-match)' # Files with/without match options
    '(stats)'{-l,--files-with-matches}'[only show names of files with matches]'
    '(stats)--files-without-match[only show names of files without matches]'

    + '(file-name)' # File-name options
    {-H,--with-filename}'[show file name for matches]'
    "--no-filename[don't show file name for matches]"

    + '(file-system)' # File system options
    "--one-file-system[don't descend into directories on other file systems]"
    $no'--no-one-file-system[descend into directories on other file systems]'

    + '(fixed)' # Fixed-string options
    {-F,--fixed-strings}'[treat pattern as literal string instead of regular expression]'
    $no"--no-fixed-strings[don't treat pattern as literal string]"

    + '(follow)' # Symlink-following options
    {-L,--follow}'[follow symlinks]'
    $no"--no-follow[don't follow symlinks]"

    + glob # File-glob options
    '*'{-g+,--glob=}'[include/exclude files matching specified glob]:glob'
    '*--iglob=[include/exclude files matching specified case-insensitive glob]:glob'

    + '(heading)' # Heading options
    '(pretty-vimgrep)--heading[show matches grouped by file name]'
    "(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"

    + '(hidden)' # Hidden-file options
    '--hidden[search hidden files and directories]'
    $no"--no-hidden[don't search hidden files and directories]"

    + '(ignore)' # Ignore-file options
    "(--no-ignore-global --no-ignore-parent --no-ignore-vcs)--no-ignore[don't respect ignore files]"
    $no'(--ignore-global --ignore-parent --ignore-vcs)--ignore[respect ignore files]'

    + '(ignore-global)' # Global ignore-file options
    "--no-ignore-global[don't respect global ignore files]"
    $no'--ignore-global[respect global ignore files]'

    + '(ignore-parent)' # Parent ignore-file options
    "--no-ignore-parent[don't respect ignore files in parent directories]"
    $no'--ignore-parent[respect ignore files in parent directories]'

    + '(ignore-vcs)' # VCS ignore-file options
    "--no-ignore-vcs[don't respect version control ignore files]"
    $no'--ignore-vcs[respect version control ignore files]'

    + '(json)' # JSON options
    '--json[output results in JSON Lines format]'
    $no"--no-json[don't output results in JSON Lines format]"

    + '(line-number)' # Line-number options
    {-n,--line-number}'[show line numbers for matches]'
    {-N,--no-line-number}"[don't show line numbers for matches]"

    + '(line-terminator)' # Line-terminator options
    '--crlf[use CRLF as line terminator]'
    $no"--no-crlf[don't use CRLF as line terminator]"
    '(text)--null-data[use NUL as line terminator]'

    + '(max-depth)' # Directory-depth options
    '--max-depth=[specify max number of directories to descend]:number of directories'
    '!--maxdepth=:number of directories'

    + '(messages)' # Error-message options
    '(--no-ignore-messages)--no-messages[suppress some error messages]'
    $no"--messages[don't suppress error messages affected by --no-messages]"

    + '(messages-ignore)' # Ignore-error message options
    "--no-ignore-messages[don't show ignore-file parse error messages]"
    $no'--ignore-messages[show ignore-file parse error messages]'

    + '(mmap)' # mmap options
    '--mmap[search using memory maps when possible]'
    "--no-mmap[don't search using memory maps]"

    + '(multiline)' # Multiline options
    {-U,--multiline}'[permit matching across multiple lines]'
    $no'(multiline-dotall)--no-multiline[restrict matches to at most one line each]'

    + '(multiline-dotall)' # Multiline DOTALL options
    '(--no-multiline)--multiline-dotall[allow "." to match newline (with -U)]'
    $no"(--no-multiline)--no-multiline-dotall[don't allow \".\" to match newline (with -U)]"

    + '(only)' # Only-match options
    {-o,--only-matching}'[show only matching part of each line]'

    + '(passthru)' # Pass-through options
    '(--vimgrep)--passthru[show both matching and non-matching lines]'
    '!(--vimgrep)--passthrough'

    + '(pcre2)' # PCRE2 options
    {-P,--pcre2}'[enable matching with PCRE2]'
    $no'(pcre2-unicode)--no-pcre2[disable matching with PCRE2]'

    + '(pcre2-unicode)' # PCRE2 Unicode options
    $no'(--no-pcre2 --no-pcre2-unicode)--pcre2-unicode[enable PCRE2 Unicode mode (with -P)]'
    '(--no-pcre2 --pcre2-unicode)--no-pcre2-unicode[disable PCRE2 Unicode mode (with -P)]'

    + '(pre)' # Preprocessing options
    '(-z --search-zip)--pre=[specify preprocessor utility]:preprocessor utility:_command_names -e'
    $no'--no-pre[disable preprocessor utility]'

    + pre-glob # Preprocessing glob options
    '*--pre-glob[include/exclude files for preprocessing with --pre]'

    + '(pretty-vimgrep)' # Pretty/vimgrep display options
    '(heading)'{-p,--pretty}'[alias for --color=always --heading -n]'
    '(heading passthru)--vimgrep[show results in vim-compatible format]'

    + regexp # Explicit pattern options
    '(1 file)*'{-e+,--regexp=}'[specify pattern]:pattern'

    + '(replace)' # Replacement options
    {-r+,--replace=}'[specify string used to replace matches]:replace string'

    + '(sort)' # File-sorting options
    '(threads)--sort=[sort results in ascending order (disables parallelism)]:sort method:((
      none\:"no sorting"
      path\:"sort by file path"
      modified\:"sort by last modified time"
      accessed\:"sort by last accessed time"
      created\:"sort by creation time"
    ))'
    '(threads)--sortr=[sort results in descending order (disables parallelism)]:sort method:((
      none\:"no sorting"
      path\:"sort by file path"
      modified\:"sort by last modified time"
      accessed\:"sort by last accessed time"
      created\:"sort by creation time"
    ))'
    '!(threads)--sort-files[sort results by file path (disables parallelism)]'

    + '(stats)' # Statistics options
    '(--files file-match)--stats[show search statistics]'
    $no"--no-stats[don't show search statistics]"

    + '(text)' # Binary-search options
    {-a,--text}'[search binary files as if they were text]'
    $no"(--null-data)--no-text[don't search binary files as if they were text]"

    + '(threads)' # Thread-count options
    '(sort)'{-j+,--threads=}'[specify approximate number of threads to use]:number of threads'

    + '(trim)' # Trim options
    '--trim[trim any ASCII whitespace prefix from each line]'
    $no"--no-trim[don't trim ASCII whitespace prefix from each line]"

    + type # Type options
    '*'{-t+,--type=}'[only search files matching specified type]: :_rg_types'
    '*--type-add=[add new glob for specified file type]: :->typespec'
    '*--type-clear=[clear globs previously defined for specified file type]: :_rg_types'
    # This should actually be exclusive with everything but other type options
    '(: *)--type-list[show all supported file types and their associated globs]'
    '*'{-T+,--type-not=}"[don't search files matching specified file type]: :_rg_types"

    + '(word-line)' # Whole-word/line match options
    {-w,--word-regexp}'[only show matches surrounded by word boundaries]'
    {-x,--line-regexp}'[only show matches surrounded by line boundaries]'

    + '(zip)' # Compression options
    '(--pre)'{-z,--search-zip}'[search in compressed files]'
    $no"--no-search-zip[don't search in compressed files]"

    + misc # Other options — no need to separate these at the moment
    '(-b --byte-offset)'{-b,--byte-offset}'[show 0-based byte offset for each matching line]'
    '--color=[specify when to use colors in output]:when:((
      never\:"never use colors"
      auto\:"use colors or not based on stdout, TERM, etc."
      always\:"always use colors"
      ansi\:"always use ANSI colors (even on Windows)"
    ))'
    '*--colors=[specify color and style settings]: :->colorspec'
    '--context-separator=[specify string used to separate non-continuous context lines in output]:separator'
    '--debug[show debug messages]'
    '--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size (bytes)'
    "(1 stats)--files[show each file that would be searched (but don't search)]"
    '*--ignore-file=[specify additional ignore file]:ignore file:_files'
    '(-v --invert-match)'{-v,--invert-match}'[invert matching]'
    '(-M --max-columns)'{-M+,--max-columns=}'[specify max length of lines to print]:number of bytes'
    '(-m --max-count)'{-m+,--max-count=}'[specify max number of matches per file]:number of matches'
    '--max-filesize=[specify size above which files should be ignored]:file size (bytes)'
    "--no-config[don't load configuration files]"
    '(-0 --null)'{-0,--null}'[print NUL byte after file names]'
    '--path-separator=[specify path separator to use when printing file names]:separator'
    '(-q --quiet)'{-q,--quiet}'[suppress normal output]'
    '--regex-size-limit=[specify upper size limit of compiled regex]:regex size (bytes)'
    '*'{-u,--unrestricted}'[reduce level of "smart" searching]'

    + operand # Operands
    '(--files --type-list file regexp)1: :_guard "^-*" pattern'
    '(--type-list)*: :_files'
  )

  # This is used with test_complete.sh to verify that there are no options
  # listed in the help output that aren't also defined here
  [[ $_RG_COMPLETE_LIST_ARGS == (1|t*|y*) ]] && {
    print -rl - $args
    return 0
  }

  # Strip out argument groups where unsupported (see above)
  [[ $ZSH_VERSION == (4|5.<0-3>)(.*)# ]] &&
  args=( ${(@)args:#(#i)(+|[a-z0-9][a-z0-9_-]#|\([a-z0-9][a-z0-9_-]#\))} )

  _arguments -C -s -S : $args && ret=0

  case $state in
    colorspec)
      if [[ ${IPREFIX#--*=}$PREFIX == [^:]# ]]; then
        suf=( -qS: )
        tmp=(
          'column:specify coloring for column numbers'
          'line:specify coloring for line numbers'
          'match:specify coloring for match text'
          'path:specify coloring for file names'
        )
        descr='color/style type'
      elif [[ ${IPREFIX#--*=}$PREFIX == (column|line|match|path):[^:]# ]]; then
        suf=( -qS: )
        tmp=(
          'none:clear color/style for type'
          'bg:specify background color'
          'fg:specify foreground color'
          'style:specify text style'
        )
        descr='color/style attribute'
      elif [[ ${IPREFIX#--*=}$PREFIX == [^:]##:(bg|fg):[^:]# ]]; then
        tmp=( black blue green red cyan magenta yellow white )
        descr='color name or r,g,b'
      elif [[ ${IPREFIX#--*=}$PREFIX == [^:]##:style:[^:]# ]]; then
        tmp=( {,no}bold {,no}intense {,no}underline )
        descr='style name'
      else
        _message -e colorspec 'no more arguments'
      fi

      (( $#tmp )) && {
        compset -P '*:'
        _describe -t colorspec $descr tmp $suf && ret=0
      }
      ;;

    typespec)
      if compset -P '[^:]##:include:'; then
        _sequence -s , _rg_types && ret=0
      # @todo This bit in particular could be better, but it's a little
      # complex, and attempting to solve it seems to run us up against a crash
      # bug — zsh # 40362
      elif compset -P '[^:]##:'; then
        _message 'glob or include directive' && ret=1
      elif [[ ! -prefix *:* ]]; then
        _rg_types -qS : && ret=0
      fi
      ;;
  esac

  return ret
}

# Complete encodings
_rg_encodings() {
  local -a expl
  local -aU _encodings

  # This is impossible to read, but these encodings rarely if ever change, so it
  # probably doesn't matter. They are derived from the list given here:
  # https://encoding.spec.whatwg.org/#concept-encoding-get
  _encodings=(
    {{,us-}ascii,arabic,chinese,cyrillic,greek{,8},hebrew,korean}
    logical visual mac {,cs}macintosh x-mac-{cyrillic,roman,ukrainian}
    866 ibm{819,866} csibm866
    big5{,-hkscs} {cn-,cs}big5 x-x-big5
    cp{819,866,125{0..8}} x-cp125{0..8}
    csiso2022{jp,kr} csiso8859{6,8}{e,i}
    csisolatin{{1..6},9} csisolatin{arabic,cyrillic,greek,hebrew}
    ecma-{114,118} asmo-708 elot_928 sun_eu_greek
    euc-{jp,kr} x-euc-jp cseuckr cseucpkdfmtjapanese
    {,x-}gbk csiso58gb231280 gb18030 {,cs}gb2312 gb_2312{,-80} hz-gb-2312
    iso-2022-{cn,cn-ext,jp,kr}
    iso8859{,-}{{1..11},13,14,15}
    iso-8859-{{1..11},{6,8}-{e,i},13,14,15,16} iso_8859-{{1..9},15}
    iso_8859-{1,2,6,7}:1987 iso_8859-{3,4,5,8}:1988 iso_8859-9:1989
    iso-ir-{58,100,101,109,110,126,127,138,144,148,149,157}
    koi{,8,8-r,8-ru,8-u,8_r} cskoi8r
    ks_c_5601-{1987,1989} ksc{,_}5691 csksc56011987
    latin{1..6} l{{1..6},9}
    shift{-,_}jis csshiftjis {,x-}sjis ms_kanji ms932
    utf{,-}8 utf-16{,be,le} unicode-1-1-utf-8
    windows-{31j,874,949,125{0..8}} dos-874 tis-620 ansi_x3.4-1968
    x-user-defined auto
  )

  _wanted encodings expl encoding compadd -a "$@" - _encodings
}

# Complete file types
_rg_types() {
  local -a expl
  local -aU _types

  _types=( ${(@)${(f)"$( _call_program types rg --type-list )"}%%:*} )

  _wanted types expl 'file type' compadd -a "$@" - _types
}

_rg "$@"


# ------------------------------------------------------------------------------
# Copyright (c) 2011 Github zsh-users - http://github.com/zsh-users
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the zsh-users nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# Description
# -----------
#
#  Completion script for ripgrep
#
# ------------------------------------------------------------------------------
# Authors
# -------
#
#  * arcizan <ghostrevery@gmail.com>
#  * MaskRay <i@maskray.me>
#
# ------------------------------------------------------------------------------

# Local Variables:
# mode: shell-script
# coding: utf-8-unix
# indent-tabs-mode: nil
# sh-indentation: 2
# sh-basic-offset: 2
# End:
# vim: ft=zsh sw=2 ts=2 et