From 6c1fb551ba0973c9a86e1ea479d553d66c6bf6b7 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:24:09 +0000 Subject: zsh-3.1.5-pws-14 --- Completion/Core/.distfiles | 5 +- Completion/Core/_approximate | 197 ++++++++++++++++++++++++++++++++ Completion/Core/_complete | 52 +++++++++ Completion/Core/_correct | 19 ++++ Completion/Core/_expand | 149 ++++++++++++++++++++++++ Completion/Core/_list | 61 ++++++++++ Completion/Core/_main_complete | 249 +++++++---------------------------------- Completion/Core/_match | 53 +++++++++ Completion/Core/_multi_parts | 25 +++-- Completion/Core/_options | 5 + Completion/Core/_parameters | 8 ++ Completion/Core/_path_files | 84 +++++++++++--- Completion/Core/_sep_parts | 7 +- Completion/Core/_set_options | 7 ++ Completion/Core/_unset_options | 7 ++ Completion/Core/compdump | 2 +- Completion/Core/compinit | 13 ++- 17 files changed, 696 insertions(+), 247 deletions(-) create mode 100644 Completion/Core/_approximate create mode 100644 Completion/Core/_complete create mode 100644 Completion/Core/_correct create mode 100644 Completion/Core/_expand create mode 100644 Completion/Core/_list create mode 100644 Completion/Core/_match create mode 100644 Completion/Core/_options create mode 100644 Completion/Core/_parameters create mode 100644 Completion/Core/_set_options create mode 100644 Completion/Core/_unset_options (limited to 'Completion/Core') diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles index ddf2a707e..6babe9701 100644 --- a/Completion/Core/.distfiles +++ b/Completion/Core/.distfiles @@ -1,5 +1,6 @@ DISTFILES_SRC=' .distfiles - _compalso _files _main_complete _multi_parts _normal _path_files - _sep_parts compdump compinit + _approximate _compalso _complete _correct _expand _files _list + _main_complete _match _multi_parts _normal _options _parameters + _path_files _sep_parts _set_options _unset_options compdump compinit ' diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate new file mode 100644 index 000000000..1b40f7cbf --- /dev/null +++ b/Completion/Core/_approximate @@ -0,0 +1,197 @@ +#autoload + +# This code will try to correct the string on the line based on the +# strings generated for the context if `compconfig[correct]' is set. +# These corrected strings will be shown in a list and one can +# cycle through them as in a menucompletion or get the corrected prefix. +# +# Supported configuration keys: +# +# approximate_accept +# This should be set to a number, specifying the maximum number +# of errors that should be accepted. If the string also contains +# a `n' or `N', the code will use the numeric argument as the +# maximum number of errors if a numeric argument was given. If no +# numeric argument was given, the number from the value of this +# key will be used. E.g. with `compconf approximate_accept=2n' two +# errors will be accepted, but if the user gives another number +# with the numeric argument, this will be prefered. Also, with +# `compconf approximate_accept=0n', normally no correction will be +# tried, but if a numeric argument is given, automatic correction +# will be used. On the other hand, if the string contains an `!' +# and a `n' or `N', correction is not attempted if a numeric +# argument is given. Once the number of errors to accept is +# determined, the code will repeatedly try to generate matches by +# allowing one error, two errors, and so on. Independent of the +# number of errors the user wants to accept, the code will allow +# only fewer errors than there are characters in the string from +# the line. +# +# approximate_original +# This value is used to determine if the original string should +# be included in the list (and thus be presented to the user when +# cycling through the corrections). If it is set to any non-empty +# value, the original string will be offered. If it contains the +# sub-string `last', the original string will appear as the last +# string when cycling through the corrections, otherwise it will +# appear as the first one (so that the command line does not +# change immediately). Also, if the value contains the sub-string +# `always', the original string will always be included, whereas +# normally it is included only if more than one possible +# correction was generated. +# +# approximate_prompt +# This can be set to a string that should be printed before the +# list of corrected strings when cycling through them. This string +# may contain the control sequences `%n', `%B', etc. known from +# the `-X' option of `compctl'. Also, the sequence `%e' will be +# replaced by the number of errors accepted to generate the +# corrected strings. +# +# approximate_insert +# If this is set to a string starting with `unambig', the code +# will try to insert a usable unambiguous string in the command +# line instead of always cycling through the corrected strings. +# If such a unambiguous string could be found, the original +# string is not used, independent of the setting of +# `approximate_original'. If no sensible string could be found, +# one can cycle through the corrected strings as usual. +# +# If any of these keys is not set, but the the same key with the +# prefix `correct' instead of `approximate' is set, that value will +# be used. + +local _comp_correct _correct_prompt comax +local cfgacc cfgorig cfgps cfgins + +# Only if all global matchers hav been tried. + +[[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1 + +# We don't try correction if the string is too short. + +[[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1 + +# Get the configuration values, using either the prefix `correct' or +# `approximate'. + +if [[ "$compstate[pattern_match]" = (|\**) ]]; then + cfgacc="${compconfig[approximate_accept]:-$compconfig[correct_accept]}" + cfgorig="${compconfig[approximate_original]:-$compconfig[correct_original]}" + cfgps="${compconfig[approximate_prompt]:-$compconfig[correct_prompt]}" + cfgins="${compconfig[approximate_insert]:-$compconfig[correct_insert]}" +else + cfgacc="$compconfig[correct_accept]" + cfgorig="$compconfig[correct_original]" + cfgps="$compconfig[correct_prompt]" + cfgins="$compconfig[correct_insert]" +fi + +# Get the number of errors to accept. + +if [[ "$cfgacc" = *[nN]* && NUMERIC -ne 1 ]]; then + # Stop if we also have a `!'. + + [[ "$cfgacc" = *\!* ]] && return 1 + + # Prefer the numeric argument if that has a sensible value. + + comax="$NUMERIC" +else + comax="${cfgacc//[^0-9]}" +fi + +# If the number of errors to accept is too small, give up. + +[[ "$comax" -lt 1 ]] && return 1 + +# Otherwise temporarily define functions to use instead of +# the builtins that add matches. This is used to be able +# to stick the `(#a...)' into the right place (after an +# ignored prefix). + +compadd() { + [[ "$*" != *-([a-zA-Z/]#|)U* && + "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return + + if [[ "$PREFIX" = \~*/* ]]; then + PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" + else + PREFIX="(#a${_comp_correct})$PREFIX" + fi + if [[ -n "$_correct_prompt" ]]; then + builtin compadd -X "$_correct_prompt" -J _correct "$@" + else + builtin compadd -J _correct "$@" + fi +} + +compgen() { + [[ "$*" != *-([a-zA-Z/]#|)U* && + "${#:-$PREFIX$SUFFIX}" -le _comp_correct ]] && return + + if [[ "$PREFIX" = \~*/* ]]; then + PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" + else + PREFIX="(#a${_comp_correct})$PREFIX" + fi + if [[ -n "$_correct_prompt" ]]; then + builtin compgen "$@" -X "$_correct_prompt" -J _correct + else + builtin compgen "$@" -J _correct + fi +} + +# Now initialise our counter. We also set `compstate[matcher]' +# to `-1'. This allows completion functions to use the simple +# `[[ compstate[matcher] -gt 1 ]] && return' to avoid being +# called for multiple global match specs and still be called +# again when correction is done. Also, this makes it easy to +# test if correction is attempted since `compstate[matcher]' +# will never be set to a negative value by the completion code. + +_comp_correct=1 +compstate[matcher]=-1 + +_correct_prompt="${cfgps//\%e/1}" + +# We also need to set `extendedglob' and make the completion +# code behave as if globcomplete were set. + +setopt extendedglob + +[[ -z "$compstate[pattern_match]" ]] && compstate[pattern_match]='*' + +while [[ _comp_correct -le comax ]]; do + if _complete; then + if [[ "$cfgins" = unambig* && + "${#compstate[unambiguous]}" -ge "${#:-$PREFIX$SUFFIX}" ]]; then + compstate[pattern_insert]=unambiguous + elif [[ compstate[nmatches] -gt 1 || "$cfgorig" = *always* ]]; then + if [[ "$cfgorig" = *last* ]]; then + builtin compadd -U -V _correct_original -nQ - "$PREFIX$SUFFIX" + elif [[ -n "$cfgorig" ]]; then + builtin compadd -U -nQ - "$PREFIX$SUFFIX" + fi + + # If you always want to see the list of possible corrections, + # set `compstate[list]=list' here. + + compstate[force_list]=list + fi + compstate[matcher]="$compstate[total_matchers]" + unfunction compadd compgen + + return 0 + fi + + [[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break + (( _comp_correct++ )) + + _correct_prompt="${cfgps//\%e/$_comp_correct}" +done + +compstate[matcher]="$compstate[total_matchers]" +unfunction compadd compgen + +return 1 diff --git a/Completion/Core/_complete b/Completion/Core/_complete new file mode 100644 index 000000000..0f4d5ff4b --- /dev/null +++ b/Completion/Core/_complete @@ -0,0 +1,52 @@ +#autoload + +# Generate all possible completions. Note that this is not intended as +# a normal completion function, but as one possible value for the +# compconfig[completer] parameter. + +local comp name + +# An entry for `-first-' is the replacement for `compctl -T' +# Completion functions may set `_compskip' to any value to make the +# main loops stop calling other completion functions. + +comp="$_comps[-first-]" +if [[ ! -z "$comp" ]]; then + "$comp" + if (( $+_compskip )); then + unset _compskip + (( compstate[nmatches] )) + return + fi +fi + +# For arguments and command names we use the `_normal' function. + +if [[ "$compstate[context]" = command ]]; then + _normal +else + # Let's see if we have a special completion definition for the other + # possible contexts. + + comp='' + + case $compstate[context] in + equal) comp="$_comps[-equal-]";; + tilde) comp="$_comps[-tilde-]";; + redirect) comp="$_comps[-redirect-]";; + math) comp="$_comps[-math-]";; + subscript) comp="$_comps[-subscript-]";; + value) comp="$_comps[-value-]";; + array_value) comp="$_comps[-array-value-]";; + condition) comp="$_comps[-condition-]";; + parameter) comp="$_comps[-parameter-]";; + brace_parameter) comp="$_comps[-brace-parameter-]";; + esac + + # If not, we use default completion, if any. + + [[ -z "$comp" ]] && comp="$_comps[-default-]" + [[ -z "$comp" ]] || "$comp" +fi + +(( compstate[nmatches] )) diff --git a/Completion/Core/_correct b/Completion/Core/_correct new file mode 100644 index 000000000..35ab01cf1 --- /dev/null +++ b/Completion/Core/_correct @@ -0,0 +1,19 @@ +#autoload + +# This is mainly a wrapper around the more general `_approximate. +# By setting `compstate[pattern_match]' to something unequal to `*' and +# then calling `_approximate, we get only corrections, not all strings +# with the corrected prefix and something after it. +# +# Supported configuration keys are the same as for `_approximate', only +# starting with `correct'. + +local ret=1 opm="$compstate[pattern_match]" + +compstate[pattern_match]='-' + +_approximate && ret=0 + +compstate[pattern_match]="$opm" + +return ret diff --git a/Completion/Core/_expand b/Completion/Core/_expand new file mode 100644 index 000000000..9172b6cbf --- /dev/null +++ b/Completion/Core/_expand @@ -0,0 +1,149 @@ +#autoload + +# This completer function is intended to be used as the first completer +# function and allows one to say more explicitly when and how the word +# from the line should be expanded than expand-or-complete. +# This function will allow other completer functions to be called if +# the expansions done produce no result or do not change the original +# word from the line. +# +# Configuration keys: +# +# expand_substitute +# If this is unset or set to the empty string, the code will first +# try to expand all substitutions in the string (such as $(...) and +# ${...}). If this is set to an non-empty string it should be +# an expression usable inside a $[...] arithmetical expression. +# In this case, expansion of substitutions will be done if the +# expression evaluates to `1'. For example, with +# +# compconf expand_substitute='NUMERIC != 1' +# +# substitution will be performed only if given an explicit numeric +# argument other than `1', as by typing ESC 2 TAB. +# +# expand_glob +# If this is unset or set to an empty string, globbing will be +# attempted on the word resulting from substitution or the +# original string. The values accepted for this key are the same +# as for expand_substitute. +# +# expand_menu +# If this is unset or set to the empty string, the words resulting +# from expansion (if any) will simply be inserted in the ommand line, +# replacing the original string. However, if this key is set to an +# non-empty string, the user can cycle through the expansion as in +# a menucompletion. Unless the value contains the sub-string `only', +# the user will still be offered all expansions at once as one of +# the strings to insert in the command line. Also, if the value +# contains the sub-string `last', the string with all expansion will +# be offered first, whereas normally it is offered as the last string +# to insert. Finally, if the value contains the sub-string `sort', +# the expansions will be sorted alphabetically, normally they are +# kept in the order the expansion produced them in. +# +# expand_original +# If this is set to an non-empty string, the original string from the +# line will be included in the list of strings the user can cycle +# through as in a menucompletion. If the value contains the sub-string +# `last', the original string will appear as the last string, with +# other values it is inserted as the first one (so that the command +# line does not change immediatly). +# +# expand_prompt +# This may be set to a string that should be displayed before the +# possible expansions. This is given to the -X option and thus may +# contain the control sequences `%n', `%B', etc. Also, the sequence +# `%o' in this string will be replaced by the original string. + +local exp word="$PREFIX$SUFFIX" group=-V + +# Do this only for the first global matcher. + +[[ "$compstate[matcher]" -le 1 ]] || return 1 + +# In exp we will collect the expansion. + +exp=("$word") + +# First try substitution. That weird thing spanning multiple lines +# changes quoted spaces, tabs, and newlines into spaces. + +[[ -z "$compconfig[expand_substitute]" || + "${(e):-\$[$compconfig[expand_substitute]]}" -eq 1 ]] && + exp=( "${(e)exp//\\[ +]/ }" ) + +# If the array is empty, store the original string again. + +[[ -z "$exp" ]] && exp=("$word") + +# Now try globbing. + +[[ -z "$compconfig[expand_glob]" || + "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ]] && + exp=( ${~exp}(N) ) + +# If we don't have any expansions or only one and that is the same +# as the original string, we let other completers run. + +[[ $#exp -eq 0 || + ( $#exp -eq 1 && "$exp[1]" = "$word" ) ]] && return 1 + +# We have expansions, should we menucomplete them? + +if [[ -z "$compconfig[expand_menu]" ]]; then + + # No, so if the user only wants a list, we add the strings + # separately. Otherwise we add the whole array as one string, + # probably also adding the original string. + + if [[ -z "$compstate[insert]" ]]; then + compadd -U -V _expand -Q - "$exp[@]" + else + [[ -n "$compconfig[expand_original]" && + "$compconfig[expand_original]" != *last* ]] && + compadd -UnQ -V _expand_original - "$word" + + compadd -UQ -V _expand - "$exp" + + [[ -n "$compconfig[expand_original]" && + "$compconfig[expand_original]" = *last* ]] && + compadd -UnQ -V _expand_original - "$word" + + compstate[insert]=menu + fi +else + # Sorting? We just use a different group type then. + + [[ "$compconfig[expand_menu]" = *sort* ]] && group=-J + + # Now add the expansion string, probably also adding the original + # and/or the string containing all expanded string. + + [[ -n "$compconfig[expand_original]" && + "$compconfig[expand_original]" != *last* ]] && + compadd -UnQ -V _expand_original - "$word" + + [[ "$compconfig[expand_menu]" = *last* && + "$compconfig[expand_menu]" != *only* ]] && + compadd -UnQ -V _expand_all - "$exp" + + if [[ -z "$compconfig[expand_prompt]" ]]; then + compadd -UQ $group _expand - "$exp[@]" + else + compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \ + $group _expand - "$exp[@]" + fi + [[ "$compconfig[expand_menu]" != *last* && + "$compconfig[expand_menu]" != *only* ]] && + compadd -UnQ -V _expand_all - "$exp" + + [[ -n "$compconfig[expand_original]" && + "$compconfig[expand_original]" = *last* ]] && + compadd -UnQ -V _expand_original - "$word" + + compstate[insert]=menu +fi + +return 0 diff --git a/Completion/Core/_list b/Completion/Core/_list new file mode 100644 index 000000000..099c6bc7b --- /dev/null +++ b/Completion/Core/_list @@ -0,0 +1,61 @@ +#autoload + +# This completer function makes the other completer functions used +# insert possible completions only after once the list has been +# shown. +# +# Configuration keys: +# +# list_condition +# If this key is unset or set to the empty string, this completer +# will delay the insertion of matches unconditionally. However, +# if this value is set, it should be set to an expression usable +# inside a $[...] arithmetical expression. In this case, delaying +# will be done if the expression evaluates to `1'. +# For example, with +# +# compconf list_condition='NUMERIC != 1' +# +# delaying will be done only if given an explicit numeric argument +# other than `1'. +# +# list_word +# To find out if only listing should be done, the code normally +# compares the contents of the line with the contents the line +# had at the time of the last invocation. If this key is set to +# an non-empty string comparison is done using only the current +# word. So if it is set, attempting completion on a word equal +# to the one completion was called on the last time will not +# delay the generation of matches. + +local pre suf + +# Get the strings to compare. + +if [[ -z "$compconfig[list_word]" ]]; then + pre="$HISTNO$LBUFFER" + suf="$RBUFFER" +else + pre="$PREFIX" + suf="$SUFFIX" +fi + +# Should we only show a list now? + +if [[ ( -z "$compconfig[list_condition]" || + "${(e):-\$[$compconfig[expand_glob]]}" -eq 1 ) && + ( "$pre" != "$_list_prefix" || "$suf" != "$_list_suffix" ) ]]; then + + # Yes. Tell the completion code about it and save the new values + # to compare the next time. + + compstate[insert]='' + compstate[list]=list + compstate[force_list]=yes + _list_prefix="$pre" + _list_suffix="$suf" +fi + +# We always return one, because we don't really do any work here. + +return 1 diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete index 3571b712c..62e60a1cc 100644 --- a/Completion/Core/_main_complete +++ b/Completion/Core/_main_complete @@ -3,229 +3,56 @@ # The main loop of the completion code. This is what is called when # completion is attempted from the command line. # -# This code will automatically try to correct the string on the line -# based on the strings generated for the context if -# `compconfig[correct]' is set and normal completion didn't yield any -# matches. These corrected strings will be shown in a list and one can -#cycle through them as in a menucompletion. To use this feature, -#`compconfig[correct]' should be set to a number, specifying the -# maximum number of errors that should be accepted. If the string also -# contains a `n' or `N', the code will use the numeric argument as the -# maximum number of errors if a numeric argument was given. If no -# numeric argument was given, the number from the value of -# `compconfig[correct]' will be used. E.g. with `compconfig[correct]=2n' -# two errors will be accepted, but if the user gives another number -# with the numeric argument, this will be prefered. Also, with -# `compconfig[correct]=0n',normally no automatic correction will be -# tried, but if a numeric argument is given, automatic correction will -# be used. Once the number of errors to accept is determined, the code -# will repeatedly try to generate matches by allowing one error, two -# errors, and so on. Independent of the number of errors the user -# wants to accept, the code will allow only fewer errors than there -# are characters in the string from the line. -# The value of `compconfig[correct_orig]' is used to determine if the -# original string should be included in the list (and thus be -# presented to the user when cycling through the corrections). If it -# is set to any non-empty value, the original string will be -# offered. If it contains the sub-string `last', the original string -# will apear as the last string when cycling through the corrections, -# otherwise it will appear as the first one (so that the command line -# does not change immediatly). Also, if the value of -# `compconfig[correct_orig]' contains the sub-string `always', the -# original string will always be included, whereas normally it is -# included only if more than one possible correction was generated. -# Finally, `compconfig[correct_prompt]' may be set to a string that -# should be printed before the list of corrected strings when cycling -# through them. This string may contain the control sequences `%n', -# `%B', etc. known from the `-X' option of `compctl'. Also, the -# sequence `%e' will be replaced by the number of errors accepted to -# generate the corrected strings. +# Configuration keys used: +# +# completer +# This should be set to the names of the functions to generate the +# matches separated by colons. E.g. with +# +# compconf completer=_complete:_correct:_approximate +# +# the code will first try normal completion. If that doesn't yield +# any matches, correction is tried and if that doesn't yield +# anything either, correcting completion is attempted. +# +# These completer functions are only used when this function is called +# without arguments. If arguments are given, they should be names of +# completer functions which will then be called. + + +# If you want to complete only set or unset options for the unsetopt +# and setopt builtin, un-comment these lines: +# +# local _set_options _unset_options +# +# _set_options=("${(@f)$({ unsetopt kshoptionprint; setopt } 2>/dev/null)}") +# _unset_options=("${(@f)$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)}") +# +# This is needed because completion function may set options locally +# which makes the output of setopt and unsetopt reflect a different +# state than the global one for which you are completing. -local comp name _comp_correct _correct_prompt comax + +local comp setopt localoptions nullglob rcexpandparam unsetopt markdirs globsubst shwordsplit nounset ksharrays # Special completion contexts after `~' and `='. -if [[ -iprefix '=' ]]; then +if compset -P 1 '\='; then compstate[context]=equal -elif [[ "$PREFIX$SUFFIX" != */* && -iprefix '~' ]]; then +elif [[ "$PREFIX" != */* && "$PREFIX[1]" = '~' ]]; then + compset -p 1 compstate[context]=tilde fi -# This is not an endless loop. - -while true; do - - # An entry for `-first-' is the replacement for `compctl -T' - # Completion functions may set `_compskip' to any value to make the - # main loops stop calling other completion functions. - - comp="$_comps[-first-]" - if [[ ! -z "$comp" ]]; then - "$comp" - if (( $+_compskip )); then - unset _compskip - return - fi - fi - - # For arguments and command names we use the `_normal' function. - - if [[ "$compstate[context]" = command ]]; then - _normal - else - # Let's see if we have a special completion definition for the other - # possible contexts. - - comp='' - - case $compstate[context] in - equal) comp="$_comps[-equal-]";; - tilde) comp="$_comps[-tilde-]";; - redirect) comp="$_comps[-redirect-]";; - math) comp="$_comps[-math-]";; - subscript) comp="$_comps[-subscript-]";; - value) comp="$_comps[-value-]";; - array_value) comp="$_comps[-array-value-]";; - condition) comp="$_comps[-condition-]";; - parameter) comp="$_comps[-parameter-]";; - brace_parameter) comp="$_comps[-brace-parameter-]";; - esac - - # If not, we use default completion, if any. - - [[ -z "$comp" ]] && comp="$_comps[-default-]" - [[ -z "$comp" ]] || "$comp" - fi - - # Use automatic correction? - - if (( $+compconfig[correct] )); then - - # Do we have matches? - if (( compstate[nmatches] )); then - - # Yes, were they added using correction? (More than one match?) +# Get the names of the completers to use in the positional parameters. - if [[ -n "$_comp_correct" && - ( "$compconfig[correct_orig]" = *always* || - compstate[nmatches] -gt 1 ) ]]; then +(( $# )) || set ${(s.:.)compconfig[completer]} - if [[ "$compconfig[correct_orig]" = *last* ]]; then - builtin compadd -V _correct_orig -nQ - "$PREFIX$SUFFIX" - elif [[ -n "$compconfig[correct_orig]" ]]; then - builtin compadd -nQ - "$PREFIX$SUFFIX" - fi +# And now just call the completer functions defined. - # If you always want to see the list of possible corrections, - # set `compstate[list]=list' here. - - compstate[force_list]=list - fi - # Since we have matches, we don't want to try again. - - break - fi - - # No matches, so let's see if we already tried correction. - - if [[ -n "$_comp_correct" ]]; then - - # Yes, give up if we reached the maximum number of tries or the - # string from the line is too short, otherwise increment our - # counter. - - [[ _comp_correct -eq comax || - "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct+1 ]] && break - (( _comp_correct++ )) - - _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}" - - elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then - - # We don't try correction if the string is too short. - - [[ "${#${:-$PREFIX$SUFFIX}}" -le 1 ]] && return - - # No matches and no correction tried yet, but we just tried the - # last global match specification, so let's see if we should use - # correction now. First, get the maximum number of errors. - - if [[ "$compconfig[correct]" = *[nN]* && NUMERIC -ne 1 ]]; then - # Prefer the numeric argument if that has a sensible value. - comax="$NUMERIC" - else - comax="${compconfig[correct]//[^0-9]}" - fi - # If the number of errors to accept is too small, give up. - - [[ "$comax" -lt 1 ]] && break - - # Otherwise temporarily define functions to use instead of - # the builtins that add matches. This is used to be able - # to stick the `(#a...)' into the right place (after an - # ignored prefix). - - compadd() { - [[ "$*" != *-([a-zA-Z/]#|)U* && - "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return - - if [[ "$PREFIX" = \~*/* ]]; then - PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" - else - PREFIX="(#a${_comp_correct})$PREFIX" - fi - if [[ -n "$_correct_prompt" ]]; then - builtin compadd -X "$_correct_prompt" -J _correct "$@" - else - builtin compadd -J _correct "$@" - fi - } - compgen() { - [[ "$*" != *-([a-zA-Z/]#|)U* && - "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return - - if [[ "$PREFIX" = \~*/* ]]; then - PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}" - else - PREFIX="(#a${_comp_correct})$PREFIX" - fi - if [[ -n "$_correct_prompt" ]]; then - builtin compgen "$@" -X "$_correct_prompt" -J _correct - else - builtin compgen "$@" -J _correct - fi - } - # Now initialise our counter. We also set `compstate[matcher]' - # to `-1'. This allows completion functions to use the simple - # `[[ compstate[matcher] -gt 1 ]] && return' to avoid being - # called for multiple global match specs and still be called - # again when correction is done. Also, this makes it easy to - # test if correction is attempted since `compstate[matcher]' - # will never be set to a negative value by the completion code. - - _comp_correct=1 - compstate[matcher]=-1 - - _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}" - - # We also need to set `extendedglob' and to make the completion - # code behave as if globcomplete were set. - - setopt extendedglob - compstate[pattern_match]=yes - else - # We are still trying global match specifications... - break - fi - else - # No automatic correction to try, just give up. - break - fi +for comp; do + "$comp" && return done - -# If we added wrapper functions, remove them. - -[[ -n "$_comp_correct" ]] && unfunction compadd compgen diff --git a/Completion/Core/_match b/Completion/Core/_match new file mode 100644 index 000000000..3c639935c --- /dev/null +++ b/Completion/Core/_match @@ -0,0 +1,53 @@ +#autoload + +# This is intended to be used as a completer function after the normal +# completer as in: `compconf completer=_complete:_match'. +# It temporarily switches on pattern matching, allowing you to try +# completion on patterns without having to setopt glob_complete. +# +# Note, however, that this is only really useful if you don't use the +# expand-or-complete function because otherwise the pattern will +# be expanded using globbing. +# +# Configuration key used: +# +# match_original +# If this is set to a `only', pattern matching will only be tried +# with the string from the line. If it is set to any other non-empty +# string, the original pattern will be tried first and if that yields +# no completions, matching will be tried again with a `*' inserted +# at the cursor position. If this key is not set or set to an empty +# string, matching will only be attempted with the `*' inserted. + +local tmp opm="$compstate[pattern_match]" ret=0 + +# Do nothing if we don't have a pattern or there are still global +# match specifications to try. + +tmp="${${:-$PREFIX$SUFFIX}#[~=]}" +[[ "$tmp:q" = "$tmp" || + compstate[matcher] -ne compstate[total_matchers] ]] && return 1 + +# Try completion without inserting a `*'? + +if [[ -n "$compconfig[match_original]" ]]; then + compstate[matcher]=-1 + compstate[pattern_match]='-' + _complete && ret=1 + compstate[pattern_match]="$opm" + compstate[matcher]="$compstate[total_matchers]" + + (( ret )) && return 0 +fi + +# No completion with inserting `*'? + +[[ "$compconfig[match_original]" = only ]] && return 1 + +compstate[matcher]=-1 +compstate[pattern_match]='*' +_complete && ret=1 +compstate[pattern_match]="$opm" +compstate[matcher]="$compstate[total_matchers]" + +return 1-ret diff --git a/Completion/Core/_multi_parts b/Completion/Core/_multi_parts index 0c677aab7..ab9438494 100644 --- a/Completion/Core/_multi_parts +++ b/Completion/Core/_multi_parts @@ -45,7 +45,11 @@ fi # the original string in `orig'. if [[ $#compstate[pattern_match] -ne 0 ]]; then - patstr="${PREFIX}*${SUFFIX}*" + if [[ "${compstate[pattern_match]-*}" = \** ]]; then + str="${PREFIX}*${SUFFIX}*" + else + str="${PREFIX}${SUFFIX}" + fi else patstr="${PREFIX:q}*${SUFFIX:q}*" fi @@ -145,7 +149,8 @@ if (( $#tmp1 )); then # found. Strings that have a separator will be added with a suffix. if [[ -z "$orig" && "$PREFIX$SUFFIX" != "$pref$orig" ]]; then - compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -S '' - "${pref}${orig}" + compadd -QU "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" -S '' - \ + "${pref}${orig}" elif [[ -n "$menu" ]]; then if [[ "$orig" = *${sep}* ]]; then orig="${sep}${orig#*${sep}}" @@ -154,20 +159,21 @@ if (( $#tmp1 )); then fi for i in "$matches[@]" ; do if [[ "$i" = *${sep}* ]]; then - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \ + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ -p "$pref" -s "$orig" - "${i%%${sep}*}${sep}" else - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" \ + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ -p "$pref" -s "$orig" - "${i%%${sep}*}" fi done else for i in "$matches[@]" ; do if [[ "$i" = *${sep}* ]]; then - compadd -U -i "$IPREFIX" -p "$pref" -s "${i#*${sep}}" \ + compadd -U -i "$IPREFIX" -I "$ISUFFIX" -p "$pref" -s "${i#*${sep}}" \ "$group[@]" "$expl[@]" -M "r:|${sep:q}=*" - "${i%%${sep}*}${sep}" else - compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -p "$pref" - "$i" + compadd -U "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" - "$i" fi done fi @@ -201,8 +207,8 @@ elif [[ "$patstr" = *${sep}* ]]; then # the completion code together with our prefix and the rest of # the string from the line as the suffix. - compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" \ - -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}" + compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" -s "${sep}${orig#*${sep}}" - "${(@)matches%%${sep}*}" return 0 fi @@ -218,7 +224,8 @@ elif [[ "$patstr" = *${sep}* ]]; then # Finally, add the unambiguous prefix and the rest of the string # from the line. - compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -p "$pref" - "$orig" + compadd -U "$group[@]" "$expl[@]" -S '' -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$pref" - "$orig" fi # This sets the return value to indicate that we added matches (or not). diff --git a/Completion/Core/_options b/Completion/Core/_options new file mode 100644 index 000000000..0a852e6ce --- /dev/null +++ b/Completion/Core/_options @@ -0,0 +1,5 @@ +#autoload + +# This should be used to complete all option names. + +compgen "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters new file mode 100644 index 000000000..0e8c548f7 --- /dev/null +++ b/Completion/Core/_parameters @@ -0,0 +1,8 @@ +#autoload + +# This should be used to complete parameter names if you need some of the +# extra options of compadd. It first tries to complete only non-local +# parameters. All arguments are given to compadd. + +compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" || + compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }" diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files index 4c61ac7ef..54b04a368 100644 --- a/Completion/Core/_path_files +++ b/Completion/Core/_path_files @@ -12,6 +12,14 @@ # like files with one of the suffixes in the `fignore' array in normal # completion. # +# This function supports one configuration key: +# +# path_expand +# If this is set to a non-empty string, the partially typed path +# from the line will be expanded as far as possible even if trailing +# pathname components can not be completed. +# +# # This function uses the helper functions `_match_test' and `_match_pattern'. # First see if we should generate matches for the global matcher in use. @@ -20,14 +28,17 @@ _match_test _path_files || return 1 # Yes, so... -local nm prepaths str linepath realpath donepath patstr prepath testpath rest +local nm str linepath realpath donepath patstr prepath testpath rest local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt local addpfx addsfx expl orig ostr nm=$compstate[nmatches] menu remsfx patlast -local origflags mflags +local origflags mflags tmp3 tmp4 exppaths + +typeset -U prepaths setopt localoptions nullglob rcexpandparam extendedglob unsetopt markdirs globsubst shwordsplit nounset +exppaths=() prepaths=('') ignore=() group=() @@ -102,7 +113,11 @@ fi # the prefix and the suffix. Then we see if we will do menucompletion. if [[ $#compstate[pattern_match] -ne 0 ]]; then - str="${PREFIX}*${SUFFIX}" + if [[ "${compstate[pattern_match]-*}" = \** ]]; then + str="${PREFIX}*${SUFFIX}" + else + str="${PREFIX}${SUFFIX}" + fi else str="${PREFIX:q}*${SUFFIX:q}" [[ "$str" = \\\~* ]] && str="$str[2,-1]" @@ -200,7 +215,7 @@ origflags="$matchflags" # have special meaning for globbing, we remove them. But before that, we # add the pattern for matching any characters before a slash. -patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-" +patstr="$patstr:gs-/-*/-:gs/*.*./../:gs/**/*/:gs-.*/-./-" # We take the last pathname component from the pattern and store it in # `patlast', replacing `*'s in it with patterns that match any character @@ -214,16 +229,16 @@ patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-" if [[ "$patstr" = */* ]]; then if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then - patlast="*/${origflags}${${patstr##*/}//\*/[^/]#}" + patlast="*/${origflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}" else - patlast="*/${matchflags}${${patstr##*/}//\*/[^/]#}" + patlast="*/${matchflags}${${${patstr##*/}//\*/[^/]#}:gs.\[^/]#.\\\*.}" fi patstr="${patstr%/*}/" else if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then - patlast="${origflags}${patstr//\*/[^/]#}" + patlast="${origflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}" else - patlast="${matchflags}${patstr//\*/[^/]#}" + patlast="${matchflags}${${patstr//\*/[^/]#}:gs.\[^/]#.\\\*.}" fi patstr="" fi @@ -234,7 +249,7 @@ fi # to `donepath'. while [[ "$orig" = */* ]] do - tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}$^pats ) + tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}${^~pats} ) tmp1=("${(@M)tmp1:#$~patlast}") [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break donepath="$donepath${orig%%/*}/" @@ -311,6 +326,24 @@ for prepath in "$prepaths[@]"; do # next `-W' path. if [[ $#collect -eq 0 ]]; then + # Before giving, we first try to get the longest expandable path- + # prefix, though. The result is stored in `exppaths' + + tmp2=() + tmp3="$rest" + tmp4="${ostr##*/}" + ostr="${ostr%/*}" + while [[ "$tmp3" = */* ]]; do + tmp2=( ${^tmp1}/${~mflags}${~tmp3} ) + if [[ $#tmp2 -eq 1 ]]; then + exppaths=( "$exppaths[@]" "${tmp2[1]}${tmp4}" ) + exppaths=( "${(@)exppaths#${prepath}${realpath}}" ) + break; + fi + tmp3="${tmp3%/*}" + tmp4="${ostr##*/}/${tmp4}" + ostr="${ostr%/*}" + done continue 2 elif [[ $#collect -ne 1 ]]; then # If we have more than one possible match, this means that the @@ -338,13 +371,14 @@ for prepath in "$prepaths[@]"; do if [[ -n "$menu" ]]; then compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "$linepath${testpath:q}" \ + -i "$IPREFIX" -I "$ISUFFIX" -p "$linepath${testpath:q}" \ -s "/${ostr#*/}" \ -W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}" else for i in $collect; do compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \ + -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \ -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}" done fi @@ -371,7 +405,8 @@ for prepath in "$prepaths[@]"; do if [[ $#tmp1 -ne $#tmp2 ]]; then compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${ostr#*/}" \ + -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$linepath${testpath:q}" -s "/${ostr#*/}" \ - "${${tmp1#${prepath}${realpath}${testpath}}:q}" continue 2 fi @@ -399,8 +434,11 @@ for prepath in "$prepaths[@]"; do suffixes=( $str$^pats ) suffixes=( "${(@)suffixes:gs.**.*.}" ) tmp2=( ${~tmp1}${~matchflags}${~suffixes} ) - tmp2=("${(@M)tmp2:#$~patlast}") - + if [[ "$tmp1" = */* && "$patlast" != \*/* ]]; then + tmp2=("${(@M)tmp2:#*${~patlast}}") + else + tmp2=("${(@M)tmp2:#$~patlast}") + fi if [[ $#tmp2 -eq 0 ]]; then # No match, insert the expanded path and add the original tail. @@ -409,17 +447,29 @@ for prepath in "$prepaths[@]"; do [[ -n "$ostr" && -n "$linepath$testpath" ]] && ostr="/$ostr" # But only if something changed. - [[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1 + [[ "${PREFIX}${SUFFIX}" = $linepath$testpath$ostr(|/) ]] && return 1 compadd -QU -S '' "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -f - "$linepath${testpath:q}$ostr" + -i "$IPREFIX" -I "$ISUFFIX" -f - "$linepath${testpath:q}$ostr" else compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \ - -i "$IPREFIX" -p "$linepath${testpath:q}" -f "$ignore[@]" \ + -i "$IPREFIX" -I "$ISUFFIX" \ + -p "$linepath${testpath:q}" -f "$ignore[@]" \ -W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}" fi done +# If no matches were found but we have expanded paths which are different +# from the original string, use them. + +exppaths=( "${(@)exppaths:#$orig}" ) + +if [[ -n "$compconfig[path_expand]" && + nm -eq compstate[nmatches] && $#exppaths -ne 0 ]]; then + compadd -UQ -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" - \ + "${linepath}${(@)^exppaths}" +fi + # This sets the return value to indicate that we added matches (or not). [[ nm -ne compstate[nmatches] ]] diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts index c1cda2b9a..fc927163b 100644 --- a/Completion/Core/_sep_parts +++ b/Completion/Core/_sep_parts @@ -101,6 +101,8 @@ if [[ $# -le 1 || "$str" != *${2}* ]]; then _match_pattern _sep_parts test matchflags [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" + [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//" + test="${matchflags}${test}" testarr=( "${(@M)${(@P)arr}:#${~test}*}" ) testarr=( "${(@)testarr:#}" ) @@ -131,6 +133,9 @@ while [[ $# -gt 0 && "$str" == *${1}* ]]; do matchflags="" _match_pattern _sep_parts test matchflags [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)" + + [[ "${compstate[pattern_match]-*}" != \** ]] && test="$test:gs/*//" + test="${matchflags}${test}" # We incrementally add suffixes by appending to them the seperators @@ -163,7 +168,7 @@ done # Add the matches for each of the suffixes. for i in "$suffixes[@]"; do compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \ - -i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]" + -i "$IPREFIX" -I "$ISUFFIX" -p "$prefix" -s "$i" - "$testarr[@]" done # This sets the return value to indicate that we added matches (or not). diff --git a/Completion/Core/_set_options b/Completion/Core/_set_options new file mode 100644 index 000000000..5f634a2cd --- /dev/null +++ b/Completion/Core/_set_options @@ -0,0 +1,7 @@ +#autoload + +# Complete all set options. This relies on `_main_complete' to store the +# names of the options that were set when it was called in the array +# `_set_options'. + +compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_set_options diff --git a/Completion/Core/_unset_options b/Completion/Core/_unset_options new file mode 100644 index 000000000..c5150c2e5 --- /dev/null +++ b/Completion/Core/_unset_options @@ -0,0 +1,7 @@ +#autoload + +# Complete all unset options. This relies on `_main_complete' to store the +# names of the options that were set when it was called in the array +# `_set_options'. + +compadd "$@" -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' - $=_unset_options diff --git a/Completion/Core/compdump b/Completion/Core/compdump index 5fdee8c7a..6a46f3265 100644 --- a/Completion/Core/compdump +++ b/Completion/Core/compdump @@ -15,7 +15,7 @@ # Print the number of files used for completion. This is used in compinit # to see if auto-dump should re-dump the dump-file. -_d_file=${compconfig[dump_file]-${0:h}/compinit.dump} +_d_file=${compconfig[dumpfile]-${0:h}/compinit.dump} typeset -U _d_files _d_files=( ${^~fpath}/_*~*~(N:t) ) diff --git a/Completion/Core/compinit b/Completion/Core/compinit index 466c80d36..19a0fd1ad 100644 --- a/Completion/Core/compinit +++ b/Completion/Core/compinit @@ -71,11 +71,12 @@ typeset -A compconfig # Standard initialisation for `compconfig'. -(( $# )) && compconfig[dump_file]="$1" -[[ -z "$compconfig[dump_file]" ]] && compconfig[dump_file]="$0.dump" +(( $# )) && compconfig[dumpfile]="$1" +[[ -z "$compconfig[dumpfile]" ]] && compconfig[dumpfile]="$0.dump" +compconfig[correct_accept]=2n compconfig[correct_prompt]='correct to:' - +compconfig[completer]=_complete # This function is used to register or delete completion functions. For # registering completion functions, it is invoked with the name of the @@ -246,10 +247,10 @@ _i_done='' # If we have a dump file, load it. -if [[ -f "$compconfig[dump_file]" ]]; then - read -rA _i_line < "$compconfig[dump_file]" +if [[ -f "$compconfig[dumpfile]" ]]; then + read -rA _i_line < "$compconfig[dumpfile]" if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then - builtin . "$compconfig[dump_file]" + builtin . "$compconfig[dumpfile]" _i_done=yes fi unset _i_line -- cgit 1.4.1