#compdef rg ## # zsh completion function for ripgrep # # Run ci/test_complete.sh after building to ensure that the options supported by # this function stay in synch with the `rg` binary. # # @see https://github.com/zsh-users/zsh/blob/master/Etc/completion-style-guide # # Based on code from the zsh-users project — see copyright notice below. _rg() { local state_descr ret curcontext="${curcontext:-}" local -a context line state local -A opt_args val_args local -a rg_args # Sort by long option name to match `rg --help` rg_args=( '(-A -C --after-context --context)'{-A+,--after-context=}'[specify lines to show after each match]:number of lines' '(-B -C --before-context --context)'{-B+,--before-context=}'[specify lines to show before each match]:number of lines' '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-s,--case-sensitive}'[search case-sensitively]' '--color=[specify when to use colors in output]:when:( never auto always ansi )' '*--colors=[specify color settings and styles]: :->colorspec' '--column[show column numbers]' '(-A -B -C --after-context --before-context --context)'{-C+,--context=}'[specify lines to show before and after each match]:number of lines' '--context-separator=[specify string used to separate non-continuous context lines in output]:separator' '(-c --count)'{-c,--count}'[only show count of matches for each file]' '--debug[show debug messages]' '--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size' '(-E --encoding)'{-E+,--encoding=}'[specify text encoding of files to search]: :_rg_encodings' '*'{-f+,--file=}'[specify file containing patterns to search for]:file:_files' "(1)--files[show each file that would be searched (but don't search)]" '(-l --files-with-matches --files-without-match)'{-l,--files-with-matches}'[only show names of files with matches]' '(-l --files-with-matches --files-without-match)--files-without-match[only show names of files without matches]' '(-F --fixed-strings)'{-F,--fixed-strings}'[treat pattern as literal string instead of regular expression]' '(-L --follow)'{-L,--follow}'[follow symlinks]' '*'{-g+,--glob=}'[include or exclude files for searching that match the specified glob]:glob' '(: -)'{-h,--help}'[display help information]' '(-p --no-heading --pretty --vimgrep)--heading[show matches grouped by file name]' '--hidden[search hidden files and directories]' '*--iglob=[include or exclude files for searching that match the specified case-insensitive glob]:glob' '(-i -s -S --case-sensitive --ignore-case --smart-case)'{-i,--ignore-case}'[search case-insensitively]' '--ignore-file=[specify additional ignore file]:file:_files' '(-v --invert-match)'{-v,--invert-match}'[invert matching]' '(-n -N --line-number --no-line-number)'{-n,--line-number}'[show line numbers]' '(-w -x --line-regexp --word-regexp)'{-x,--line-regexp}'[only show matches surrounded by line boundaries]' '(-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' '--maxdepth=[specify max number of directories to descend]:number of directories' '(--mmap --no-mmap)--mmap[search using memory maps when possible]' '(-H --with-filename --no-filename)--no-filename[suppress all file names]' "(-p --heading --pretty --vimgrep)--no-heading[don't group matches by file name]" "(--no-ignore-parent)--no-ignore[don't respect ignore files]" "--no-ignore-parent[don't respect ignore files in parent directories]" "--no-ignore-vcs[don't respect version control ignore files]" '(-n -N --line-number --no-line-number)'{-N,--no-line-number}'[suppress line numbers]' '--no-messages[suppress all error messages]' "(--mmap --no-mmap)--no-mmap[don't search using memory maps]" '(-0 --null)'{-0,--null}'[print NUL byte after file names]' '(-o --only-matching -r --replace)'{-o,--only-matching}'[show only matching part of each line]' '--path-separator=[specify path separator to use when printing file names]:separator' '(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]' '(-q --quiet)'{-q,--quiet}'[suppress normal output]' '--regex-size-limit=[specify upper size limit of compiled regex]:regex size' '(1 -f --file)*'{-e+,--regexp=}'[specify pattern]:pattern' '(-o --only-matching -r --replace)'{-r+,--replace=}'[specify string used to replace matches]:replace string' '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case-insensitively if the pattern is all lowercase]' '(-j --threads)--sort-files[sort results by file path (disables parallelism)]' '(-a --text)'{-a,--text}'[search binary files as if they were text]' '(-j --sort-files --threads)'{-j+,--threads=}'[specify approximate number of threads to use]:number of threads' '*'{-t+,--type=}'[only search files matching specified type]: :_rg_types' '*--type-add=[add new glob for 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 type]: :_rg_types" '*'{-u,--unrestricted}'[reduce level of "smart" searching]' '(: -)'{-V,--version}'[display version information]' '(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]' '(-H --no-filename --with-filename)'{-H,--with-filename}'[display the file name for matches]' '(-w -x --line-regexp --word-regexp)'{-w,--word-regexp}'[only show matches surrounded by word boundaries]' '(-e -f --file --files --regexp --type-list)1: :_rg_pattern' '(--type-list)*:file:_files' ) [[ ${_RG_COMPLETE_LIST_ARGS:-} == (1|t*|y*) ]] && { printf '%s\n' "${rg_args[@]}" return 0 } _arguments -s -S : "${rg_args[@]}" && return 0 while (( $#state )); do case "${state[1]}" in colorspec) # @todo I don't like this because it allows you to do weird things like # `line:line:bg:`. Also, i would like the `compadd -q` behaviour [[ -prefix *:none: ]] && return 1 [[ -prefix *:*:*:* ]] && return 1 _values -S ':' 'color/style type' \ 'column[specify coloring for column numbers]: :->attribute' \ 'line[specify coloring for line numbers]: :->attribute' \ 'match[specify coloring for match text]: :->attribute' \ 'path[specify color for file names]: :->attribute' && return 0 [[ "${state}" == 'attribute' ]] && _values -S ':' 'color/style attribute' \ 'none[clear color/style for type]' \ 'bg[specify background color]: :->color' \ 'fg[specify foreground color]: :->color' \ 'style[specify text style]: :->style' && return 0 [[ "${state}" == 'color' ]] && _values -S ':' 'color value' \ black blue green red cyan magenta yellow white && return 0 [[ "${state}" == 'style' ]] && _values -S ':' 'style value' \ bold nobold intense nointense && return 0 ;; typespec) if compset -P '[^:]##:include:'; then _sequence -s ',' _rg_types && return 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' && return 1 elif [[ ! -prefix *:* ]]; then _rg_types -qS ':' && return 0 fi ;; esac shift state done return 1 } # zsh 5.1 refuses to complete options if a 'match-less' operand like our pattern # could be 'completed' instead. We can use _guard() to avoid this problem, but # it introduces another one: zsh won't print the message if we try to complete # the pattern after having passed `--`. To work around *that* problem, we can # use this function to bypass the _guard() when `--` is on the command line. # This is inaccurate (it'd get confused by e.g. `rg -e --`), but zsh's handling # of `--` isn't accurate anyway _rg_pattern() { if (( ${words[(I)--]} )); then _message 'pattern' else _guard '^-*' 'pattern' fi } # 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 rg-encodings expl 'encoding' compadd -a "${@}" - _encodings } # Complete file types _rg_types() { local -a expl local -aU _types _types=( ${${(f)"$( _call_program rg-types rg --type-list )"}%%:*} ) _wanted rg-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 # * MaskRay # # ------------------------------------------------------------------------------ # 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