summaryrefslogtreecommitdiffstats
path: root/complete
diff options
context:
space:
mode:
authordana <dana@dana.is>2017-07-06 19:04:14 -0500
committerAndrew Gallant <jamslam@gmail.com>2017-07-18 07:03:36 -0400
commit5613df3034d13160acf692154df476b019335295 (patch)
treeaedd2677a2b9c998cb3e6d3ef30d719756ab78d6 /complete
parent79ad81626f6089ad7009c1b1094f4beb686c070b (diff)
Refactor zsh completion function
- Improve documentation - Reorganise into functions - Order options lexicographically - Correct minor wording inconsistencies - Fix --count error - Fix --maxdepth error - Fix --path-separator error - Fix --version error - Adjust exclusivity for --files, -h, -j, -o, -r, -t, -T, -v, -V, &c. - Improve pattern-operand guard behaviour - Partially fix issue with colorspec state - Fix issue with typespec state - Add completion for <type>:include: sequence - Move licence info out of the way
Diffstat (limited to 'complete')
-rw-r--r--complete/_rg360
1 files changed, 200 insertions, 160 deletions
diff --git a/complete/_rg b/complete/_rg
index a29debae..bd4482aa 100644
--- a/complete/_rg
+++ b/complete/_rg
@@ -1,4 +1,204 @@
#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]'
+ '(-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}'[prefix each match with name of file that contains it]'
+ '(-w --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'
+ )
+
+ _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.
@@ -39,166 +239,6 @@
#
# ------------------------------------------------------------------------------
-local context state state_descr line
-local -A opt_args
-local -i ret=1
-
-local -a common_options
-common_options=(
- '(-a --text)'{-a,--text}'[search binary files as if they were text]'
- '(-c, --count)'{-c,--count}'[only show count of matches for each file]'
- '--color=[specify when to use colors in output]:when:( never auto always ansi )'
- '(1)*'{-e,--regexp=}'[specify pattern]:pattern'
- '(-E --encoding)'{-E,--encoding=}'[specify text encoding of files to search]: :->encoding'
- '(-F --fixed-strings)'{-F,--fixed-strings}'[treat pattern as literal string instead of regular expression]'
- '*'{-g,--glob=}'[include or exclude files for searching that match the specified glob]:glob'
- '(-h --help)'{-h,--help}'[display help information]'
- '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-i,--ignore-case}'[search case-insensitively]'
- '(-n -N --line-number --no-line-number)'{-n,--line-number}'[show line numbers]'
- '(-n -N --line-number --no-line-number)'{-N,--no-line-number}'[suppress line numbers]'
- '(-o --only-matching)'{-o,--only-matching}'[show only matching part of each line]'
- '(-q --quiet)'{-q,--quiet}'[suppress normal output]'
- '(-T --type-not)*'{-t,--type=}'[only search files matching specified type]: :->type'
- '(-t --type)*'{-T,--type-not=}"[don't search files matching specified type]: :->type"
- '*'{-u,--unrestricted}'[reduce level of "smart" searching]'
- '(-v --invert-match)'{-v,--invert-match}'[invert matching]'
- '(-w --word-regexp)'{-w,--word-regexp}'[only show matches surrounded by word boundaries]'
-)
-
-local -a less_common_options
-less_common_options=(
- '(-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'
- '(-A -B -C --after-context --before-context --context)'{-C,--context=}'[specify lines to show before and after each match]:number of lines'
- '*--colors=[specify color settings and styles]: :->colorspec'
- '--column[show column numbers]'
- '--context-separator=[specify string used to separate non-continuous context lines in output]:separator string'
- '--debug[show debug messages]'
- '--dfa-size-limit=[specify upper size limit of generated DFA]:DFA size'
- '*'{-f,--file=}'[specify file containing patterns to search for]:file:_files'
- "--ignore-file=[specify additional ignore file]:file:_files"
- "--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]'
- '(-H --with-filename --no-filename)'{-H,--with-filename}'[prefix each match with name of file that contains it]'
- '(-H --with-filename --no-filename)--no-filename[suppress all file names]'
- '(-p --no-heading --pretty --vimgrep)--heading[show matches grouped by file name]'
- "(-p --heading --pretty --vimgrep)--no-heading[don't group matches by file name]"
- '--hidden[search hidden files and directories]'
- '*--iglob=[include or exclude files for searching that match the specified case-insensitive glob]:glob'
- '(-L --follow)'{-L,--follow}'[follow symlinks]'
- '(-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]:size'
- '--maxdepth[specify max number of directories to descend]:number of directories'
- '(--no-mmap)--mmap[search using memory maps when possible]'
- '--no-messages[suppress all error messages]'
- "(--mmap)--no-mmap[don't search using memory maps]"
- "(--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]"
- '(-0 --null)'{-0,--null}'[print NUL byte after file names]'
- '--path-separator=[specify path separator to use when printing file names]'
- '(-p --heading --no-heading --pretty --vimgrep)'{-p,--pretty}'[alias for --color=always --heading -n]'
- '--regex-size-limit=[specify upper size limit of compiled regex]:regex size'
- '(-r --replace)'{-r,--replace=}'[specify string used to replace matches]:replace string'
- '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-s,--case-sensitive}'[search case-sensitively]'
- '(-i -s -S --ignore-case --case-sensitive --smart-case)'{-S,--smart-case}'[search case-insensitively if the pattern is all lowercase]'
- '--sort-files[sort results by file path (disables parallelism)]'
- '(-j --threads)'{-j,--threads=}'[specify approximate number of threads to use]:number of threads'
- '(-v --version)'{-V,--version}'[display version information]'
- '(-p --heading --no-heading --pretty)--vimgrep[show results in vim-compatible format]'
-)
-
-local -a file_type_management_options
-file_type_management_options=(
- '--type-list[show all supported file types and their associated globs]'
- '*--type-add=[add new glob for file type]: :->typespec'
- '*--type-clear=[clear globs previously defined for specified file type]: :->type'
-)
-
-_arguments -S -s : \
- $common_options \
- $less_common_options \
- $file_type_management_options \
- '(-e --regexp)1: :_guard "^--*" pattern' \
- '*:file:_files' \
- && ret=0
-
-case "$state" in
- colorspec)
- _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' && ret=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' && ret=0
-
- [[ "$state" == 'color' ]] &&
- _values -S ':' 'color value' \
- black blue green red cyan magenta yellow white && ret=0
-
- [[ "$state" == 'style' ]] &&
- _values -S ':' 'style value' \
- bold nobold intense nointense && ret=0
- ;;
-
- encoding)
- # 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
- local -U encodings
- 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
- )
-
- _describe -t encodings 'encoding' encodings && ret=0
- ;;
-
- type|typespec)
- local -U types
- types=( ${${(f)"$(_call_program types rg --type-list)"}%%:*} )
-
- if [[ "$case" == 'type' ]]; then
- _describe -t types "type" types && ret=0
- else
- # @todo: Would be nice to complete type names if an include: directive is
- # provided here
- _values -S ':' 'type spec' \
- ${^types}':glob or include directive' && ret=0
- fi
- ;;
-esac
-
-return ret
-
# Local Variables:
# mode: shell-script
# coding: utf-8-unix