diff options
Diffstat (limited to 'Completion')
-rw-r--r-- | Completion/Base/Utility/_alternative | 2 | ||||
-rw-r--r-- | Completion/Unix/Type/_path_files | 17 | ||||
-rw-r--r-- | Completion/Zsh/Type/_delimiters | 16 | ||||
-rw-r--r-- | Completion/Zsh/Type/_globqual_delims | 24 | ||||
-rw-r--r-- | Completion/Zsh/Type/_globquals | 233 | ||||
-rw-r--r-- | Completion/Zsh/Type/_history_modifiers | 84 |
6 files changed, 373 insertions, 3 deletions
diff --git a/Completion/Base/Utility/_alternative b/Completion/Base/Utility/_alternative index c7b71d9bc..bfb34a604 100644 --- a/Completion/Base/Utility/_alternative +++ b/Completion/Base/Utility/_alternative @@ -75,7 +75,7 @@ while _tags; do done for descr in "$mesgs[@]"; do - _message -e "${descr%%:*}" "${desc#*:}" + _message -e "${descr%%:*}" "${descr#*:}" done return 1 diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files index 4176005c3..e75e81efd 100644 --- a/Completion/Unix/Type/_path_files +++ b/Completion/Unix/Type/_path_files @@ -6,8 +6,9 @@ local linepath realpath donepath prepath testpath exppath skips skipped local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre local pats haspats ignore pfx pfxsfx sopt gopt opt sdirs ignpar cfopt listsfx -local nm=$compstate[nmatches] menu matcher mopts sort match mid accex fake +local nm=$compstate[nmatches] menu matcher mopts sort mid accex fake local listfiles listopts tmpdisp +local -a match mbegin mend typeset -U prepaths exppaths @@ -349,7 +350,19 @@ for prepath in "$prepaths[@]"; do tmp2=( "$tmp1[@]" ) - if [[ "$tpre$tsuf" = */* ]]; then + # Look for glob qualifiers. + # Extra nastiness to be careful about a quoted parenthesis. + # The initial tests look for parentheses with zero or an + # even number of backslashes in front. + # The later test looks for an outstanding quote. + if [[ ( -o bareglobqual && \ + "$tpre/$tsuf" = (#b)((*[^\\]|)(\\\\)#\()([^\)]#) || \ + -o extendedglob && \ + "$tpre/$tsuf" = (#b)((*[^\\]|)(\\\\)#"(#q")([^\)]#) \ + ) && -z $compstate[quote] ]]; then + compset -p ${#match[1]} + _globquals + elif [[ "$tpre$tsuf" = */* ]]; then compfiles -P$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake elif [[ "$sopt" = *[/f]* ]]; then compfiles -p$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake "$pats[@]" diff --git a/Completion/Zsh/Type/_delimiters b/Completion/Zsh/Type/_delimiters new file mode 100644 index 000000000..bb5bba8d0 --- /dev/null +++ b/Completion/Zsh/Type/_delimiters @@ -0,0 +1,16 @@ +#autoload + +# Simple function to offer delimiters for modifiers and qualifers. +# Single argument is tag to use. + +local expl +local -a list + +zstyle -a ":completion:${curcontext}:$1" delimiters list || + list=(: + / - %) + +if (( ${#list} )); then + _wanted delimiters expl delimiter compadd -S '' -a list +else + _message delimiter +fi diff --git a/Completion/Zsh/Type/_globqual_delims b/Completion/Zsh/Type/_globqual_delims new file mode 100644 index 000000000..bba4241e8 --- /dev/null +++ b/Completion/Zsh/Type/_globqual_delims @@ -0,0 +1,24 @@ +#autoload + +# Helper for _globquals. Sets delim to delimiter to match. + +# don't restore special parameters +compstate[restore]=no + +delim=$PREFIX[1] +compset -p 1 + +# One of matching brackets? +# These don't actually work: the parser gets very confused. +local matchl="<({[" matchr=">)}]" +integer ind=${matchl[(I)$delim]} + +(( ind )) && delim=$matchr[ind] + +if compset -P "[^$delim]#$delim"; then + # Completely matched. + return 0 +else + # Still in delimiter + return 1 +fi diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals new file mode 100644 index 000000000..0262c8b6f --- /dev/null +++ b/Completion/Zsh/Type/_globquals @@ -0,0 +1,233 @@ +#autoload + +local state=qual expl char delim +local -a alts + +while [[ -n $PREFIX ]]; do + char=$PREFIX[1] + compset -p 1 + case $char in + ([-/F.@=p*rwxAIERWXsStUG^MTNDn,]) + # no argument + ;; + + (%) + # optional b, c + if [[ $PREFIX[1] = [bc] ]]; then + compset -p 1 + fi + ;; + + (f) + if ! compset -P "[-=+][0-7?]##"; then + if [[ -z $PREFIX ]]; then + _delimiters qualifier-f + return + elif ! _globqual_delims; then + # still completing mode spec + _message "mode spec" + return + fi + fi + ;; + + (e) + # complete/skip delimited command line + if [[ -z $PREFIX ]]; then + _delimiters qualifer-e + return + elif ! _globqual_delims; then + # still completing command to eval + compset -q + _normal + return + fi + ;; + + (+) + # complete/skip command name (no delimiters) + if [[ $PREFIX = [[:IDENT:]]# ]]; then + # either nothing there yet, or still on name + _command_names + return + fi + compset -P '[[:IDENT:]]##' + ;; + + (d) + # complete/skip device + if [[ -z $PREFIX ]]; then + _message device ID + return + fi + # It's pointless trying to complete the device. + # Simply assume it's done. + compset -p '[[:digit:]]##' + ;; + + (l) + # complete/skip link count + if [[ PREFIX = ([-+]|) ]]; then + _message link count + return + fi + # It's pointless trying to complete the link count. + # Simply assume it's done. + compset -P '([-+]|)[[:digit:]]##' + ;; + + (u) + # complete/skip UID or delimited user + if ! compset -P '[[:digit:]]##'; then + if [[ -z $PREFIX ]]; then + _delimiters qualifier-u + return + elif ! _globqual_delims; then + # still completing user + _users -S $delim + return + fi + fi + ;; + + (g) + # complete/skip GID or delimited group + if ! compset -P '[[:digit:]]##'; then + if [[ -z $PREFIX ]]; then + _delimiter qualifier-g + return + elif ! _globqual_delims; then + # still completing group + _groups -S $delim + return + fi + fi + ;; + + ([amc]) + if ! compset -P '([Mwhms]|)([-+]|)<->'; then + # complete/skip relative time spec + alts=() + if ! compset -P '[Mwhms]' && [[ -z $PREFIX ]]; then + alts+=( + "time-specifiers:time specifier:\ +((M\:months w\:weeks h\:hours m:\minutes s\:seconds))") + fi + if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then + alts+=("senses:sense:((-\:less\ than +\:more\ than))") + fi + alts+=('digits:digit: ') + _alternative $alts + return + fi + ;; + + (L) + # complete/skip file size + if ! compset -P '([kKmMpP]|)([-+]|)<->'; then + # complete/skip size spec + alts=() + if ! compset -P '[kKmMpP]' && [[ -z $PREFIX ]]; then + alts+=( + "size-specifiers:size specifier:\ +((k\:kb m\:mb p\:512-byte\ blocks))") + fi + if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then + alts+=("senses:sense:((-\:less\ than +\:more\ than))") + fi + alts+=('digits:digit: ') + _alternative $alts + return + fi + ;; + + ([oO]) + # complete/skip sort spec + if ! compset -P "?"; then + alts=( + "n:lexical order of name" + "L:size of file" + "l:number of hard links" + "a:last access time" + "m:last modification time" + "c:last inode change time" + "d:directory depth" + ) + _describe -t sort-specifiers "sort specifier" alts -Q -S '' + return + fi + ;; + + (\[) + # complete/skip range: check for closing bracket + if ! compset -P "(-|)[[:digit:]]##(,(-|)[[:digit:]]##|)]"; then + if compset -P "(-|)[[:digit:]]##,"; then + _message end of range + else + _message start of range + fi + return + fi + ;; + + (:) + # complete modifiers and don't stop completing them + _history_modifiers + return + ;; + esac +done + +case $state in + (qual) + local -a quals + quals=( + "/:directories" + "F:non-empty directories" + ".:plain files" + "@:symbolic links" + "=:sockets" + "p:name pipes (FIFOS)" + "*:executable plain files" + "%:device files" + "r:owner-readable" + "w:owner-writeable" + "x:owner-executable" + "A:group-readable" + "I:group-writeable" + "E:group-executable" + "R:world-readable" + "W:world-writeable" + "X:world-executable" + "s:setuid" + "S:setgid" + "t:sticky bit set" + "f:+ access rights" + "e:execute code" + "+:+ command name" + "d:+ device" + "l:+ link count" + "U:owned by EUID" + "G:owned by EGID" + "u:+ owning user" + "g:+ owning group" + "a:+ access time" + "m:+ modification time" + "c:+ inode change time" + "L:+ size" + "^:negate qualifiers" + "-:follow symlinks toggle" + "M:mark directories" + "T:mark types" + "N:use NULL_GLOB" + "D:glob dots" + "n:numeric glob sort" + "o:+ sort order, up" + "O:+ sort order, down" + "[:+ range of files" + "):end of qualifiers" + "\::modifier" + ) + _describe -t globquals "glob qualifier" quals -Q -S '' + ;; +esac diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers new file mode 100644 index 000000000..085867159 --- /dev/null +++ b/Completion/Zsh/Type/_history_modifiers @@ -0,0 +1,84 @@ +#autoload + +# Complete history-style modifiers; the first : will have +# been matched and compset -p 1'd. +# The single argument is the type of context: +# h history +# q glob qualifier +# p parameter + +local -a list + +local type=$1 delim expl +integer global + +while true; do + if [[ -n $PREFIX ]]; then + local char=$PREFIX[1] + + global=0 + compset -p 1 + case $char in + ([hretpqQxlu\&]) + # single character modifiers + ;; + + (s) + # match delimiter string delimiter string delimiter + if [[ -z $PREFIX ]]; then + _delimiters modifier-s + return + fi + delim=$PREFIX[1] + compset -p 1 + if ! compset "[^$delim]#$delim[^$delim]#$delim"; then + if compset "[^$delim]#$delim"; then + _message original string + else + _message replacement string + fi + return + fi + ;; + + (g) + global=1 + continue + ;; + esac + + # modifier completely matched, see what's next. + compset -P : && continue + # if there's something other than colon next, bummer + [[ -n $PREFIX ]] && return 1 + + list=("\::modifier") + [[ $type = g ]] && list+=("):end of qualifiers") + # strictly we want a normal suffix if end of qualifiers + _describe -t delimiters "delimiter" list -Q -S '' + else + list=( + "s:substitute string" + "&:repeat substitution" + ) + if (( ! global )); then + list+=( + "g:globally apply s or &" + "h:head - strip trailing path element" + "t:tail - strip directories" + "r:root - strip suffix" + "e:leave only extension" + "Q:strip quotes" + "l:lower case all words" + "u:upper case all words" + ) + [[ $type = h ]] && list+=( + "p:print without executing" + "x:quote words, breaking on whitespace" + ) + [[ $type = [hp] ]] && list+=("q:quote to escape further substitutions") + fi + _describe -t modifiers "modifier" list -Q -S '' + return + fi +done |