diff options
Diffstat (limited to 'Completion')
-rw-r--r-- | Completion/Base/_arguments | 88 | ||||
-rw-r--r-- | Completion/Base/_long_options | 8 |
2 files changed, 77 insertions, 19 deletions
diff --git a/Completion/Base/_arguments b/Completion/Base/_arguments index 86cd1c498..d51e6d0af 100644 --- a/Completion/Base/_arguments +++ b/Completion/Base/_arguments @@ -7,6 +7,7 @@ setopt localoptions extendedglob local long args rest ws cur nth def nm expl descr action opt arg tmp local single uns ret=1 soptseq soptseq1 sopts prefix line +local beg optbeg argbeg # Associative arrays used to collect information about the options. @@ -122,7 +123,10 @@ fi ws=( "${(@)words[2,-1]}" ) cur=$(( CURRENT-2 )) nth=1 -liine=( "$words[1]" ) +line=( "$words[1]" ) +beg=2 +argbeg=2 +optbeg=2 # ...until the current word is reached. @@ -138,15 +142,27 @@ while [[ cur -gt 0 ]]; do fi arg='' + # See if we are after an option getting n arguments ended by something + # that matches the current word. + + if [[ "$def" = \**[^\\]:* && "$ws[1]" = ${~${(M)def#*[^\\]:}[2,-2]} ]]; then + def='' + shift 1 ws + (( cur-- )) + (( beg++ )) + continue + fi + # Remove one description/action pair from `def' if that isn't empty. - if [[ -n "$def" ]]; then - if [[ "$def" = ?*:*:* ]]; then - def="${def#?*:*:}" + if [[ -n "$def" && "$def" != \** ]]; then + if [[ "$def" = ?*[^\\]:*[^\\]:* ]]; then + def="${def#?*[^\\]:*[^\\]:}" + argbeg="$beg" else def='' fi - else + elif [[ -z "$def" ]]; then # If it is empty, and the word starts with `--' and we should # complete long options, just ignore this word, otherwise make sure @@ -179,6 +195,8 @@ while [[ cur -gt 0 ]]; do tmp="${ws[1][1]}${ws[1][-1]}" if (( $+opts[$tmp] )); then def="$opts[$tmp]" + optbeg="$beg" + argbeg="$beg" uns="${ws[1][2,-1]}" opt='' fi @@ -217,9 +235,11 @@ while [[ cur -gt 0 ]]; do opt='' def="$dopts[$tmp[1]]" + optbeg="$beg" + argbeg="$beg" [[ -n "$oneshot[$tmp[1]]" ]] && unset "dopts[$tmp[1]]" - if [[ "$def" = ?*:*:* ]]; then - def="${def#?*:*:}" + if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then + def="${def#?*[^\\]:*[^\\]:}" else def='' fi @@ -242,6 +262,8 @@ while [[ cur -gt 0 ]]; do if (( $#tmp )); then opt='' def="$odopts[$tmp[1]]" + optbeg="$beg" + argbeg="$beg" [[ -n "$oneshot[$tmp[1]]" ]] && unset "odopts[$tmp[1]]" # For options whose first argument *may* come after the @@ -251,8 +273,10 @@ while [[ cur -gt 0 ]]; do if [[ ( -z "$sopts" && "$ws[1]" != "$tmp[1]" ) || ( -n "$sopts" && ( ( $tmp[1] = [-+]? && "$ws[1]" != "${tmp[1][1]}"${~soptseq}"${tmp[1][2]}" ) || ( $tmp[1] != [-+]? && "$ws[1]" != "$tmp[1]" ) ) ) ]]; then - if [[ "$def" = ?*:*:* ]]; then - def="${def#?*:*:}" + if [[ "$def" = [^*]*[^\\]:*[^\\]:* ]]; then + def="${def#?*[^\\]:*[^\\]:}" + optbeg="$beg" + argbeg="$beg" else def='' fi @@ -284,6 +308,7 @@ while [[ cur -gt 0 ]]; do shift 1 ws (( cur-- )) + (( beg++ )) done # Now generate the matches. @@ -313,10 +338,16 @@ else def="$args[nth]" [[ -z "$def" ]] && def="$rest" + + if [[ "$def" = \** ]]; then + def="${def#*[^\\]:}" + [[ "$def" = :* ]] && def="$def[2,-1]" + [[ "$def" = :* ]] && def="$def[2,-1]" + fi fi # In any case, we have to complete option names here, but we may - # be in a string that starts with an option names and continues with + # be in a string that starts with an option name and continues with # the first argument, test that (again, two loops). opt=yes @@ -407,14 +438,41 @@ else if [[ -n "$def" ]]; then - # Ignore the leading colon describing optional arguments. + # Ignore the leading colon or `*...' describing optional arguments. - [[ "$def" = :* ]] && def="$def[2,-1]" + if [[ "$def" = :* ]]; then + def="$def[2,-1]" + elif [[ "$def" = \** ]]; then + tmp="${${(M)def#*[^\\]:}[2,-2]}" + def="${def#*[^\\]:}" + + if [[ "$def" = :* ]]; then + if [[ "$def" = ::* ]]; then + def="$def[3,-1]" + beg=$argbeg + else + def="$def[2,-1]" + beg=$optbeg + fi + + shift beg words + (( CURRENT -= beg )) + + if [[ -n "$tmp" ]]; then + tmp="$words[(ib:CURRENT:)${~tmp}]" + [[ tmp -le $#words ]] && words=( "${(@)words[1,tmp-1]}" ) + fi + fi + fi # Get the description and the action. - descr="${def%%:*}" - action="${${def#*:}%%:*}" + descr="${${${(M)def#*[^\\]:}[1,-2]}//\\\\:/:}" + if [[ "$def" = *[^\\]:*[^\\]:* ]]; then + action="${${${(M)${def#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}" + else + action="${${def#*[^\\]:}//\\\\:/:}" + fi _description expl "$descr" @@ -423,7 +481,7 @@ else # An empty action means that we should just display a message. _message "$descr" return ret - elif [[ "$action[1]" = \(*\) ]]; then + elif [[ "$action" = \(*\) ]]; then # Anything inside `(...)' is added directly. diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options index 716ff8884..f0aa2eaff 100644 --- a/Completion/Base/_long_options +++ b/Completion/Base/_long_options @@ -141,9 +141,9 @@ if [[ "$tmp" != $_lo_cache_cmd ]]; then # First, we get the pattern and the action to use and take them # from the positional parameters. - pattern="${1%%:*}" - descr="${${1#*:}%%:*}" - action="${1#*:*:}" + pattern="${${${(M)1#*[^\\]:}[1,-2]}//\\\\:/:}" + descr="${${${(M)${1#*[^\\]:}#*[^\\]:}[1,-2]}//\\\\:/:}" + action="${${1#*[^\\]:*[^\\]:}//\\\\:/:}" shift # We get all options matching the pattern and take them from the @@ -257,7 +257,7 @@ if [[ "$str" = *\=* ]]; then _description expl "$descr" - if [[ "$action[1]" = (\[*\]|\(*\)) ]]; then + if [[ "$action" = (\[*\]|\(*\)) ]]; then compadd "$expl[@]" - ${=action[2,-2]} elif [[ "$action" = \{*\} ]]; then eval "$action[2,-2]" |