#autoload # This code will try to correct the string on the line based on the # strings generated for the context. These corrected strings will be # shown in a list and one can cycle through them as in a menucompletion # or get the corrected prefix. local _comp_correct _correct_prompt comax local cfgacc cfgorig cfgps cfgins # Only if all global matchers have 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:-1} -ne 1 ]]; then # Stop if we also have a `!'. [[ "$cfgacc" = *\!* ]] && return 1 # Prefer the numeric argument if that has a sensible value. comax="${NUMERIC:-1}" 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 } # 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}" [[ -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 local expl if [[ "$cfgorig" = *show* ]]; then if [[ -n "$compconfig[description_format]" ]]; then expl=(-X "${compconfig[description_format]//\\%d/original}") else expl=() fi else expl=(-n) fi if [[ "$cfgorig" = *last* ]]; then builtin compadd "$expl[@]" -U -V _correct_original -Q - "$PREFIX$SUFFIX" elif [[ -n "$cfgorig" ]]; then builtin compadd "$expl[@]" -U -Q - "$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 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 return 1