From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8089 invoked from network); 19 Oct 2000 09:11:35 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 19 Oct 2000 09:11:35 -0000 Received: (qmail 20229 invoked by alias); 19 Oct 2000 09:11:29 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 13038 Received: (qmail 20222 invoked from network); 19 Oct 2000 09:11:29 -0000 Date: Thu, 19 Oct 2000 11:11:27 +0200 (MET DST) Message-Id: <200010190911.LAA16317@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: "E. Jay Berkenbilt"'s message of Tue, 17 Oct 2000 15:30:55 -0400 Subject: Re: still confused about completion and matching E. Jay Berkenbilt wrote: > ... > > zsh% ls u?/q/e?/ TAB > > finds no matches. The problem has to do with the code that is in the > if (( tmp4 )) block in _path_files starting at line 463. Yes, it couldn't match the paths with the way $PREFIX and $SUFFIX were set up. > ... > > The functionality I was able to get differs from what I originally > described in two ways: if partial expansion is possible (i.e., > expansion of the first metacharacter but not the second), it is still > not done. Expansion is done only when *all* metacharacters match > unambiguously. This is fine -- in fact, it's probably better than > what I originally specified. The patch below should be a bit better (also fixing the `u1// ...' thing you reported). > The other thing is that the code doesn't > complete as far as possible. For example, ls u?/ TAB should complete > through u?/q since all the choices start with q. I can live without > this too though I don't see exactly why it doesn't work. It's because of the change in _match. That keeps the command line from being changed if completion is ambiguous (btw., the patch below slightly changes that test, too, giving a better behaviour, but it can't be perfect, I'm sorry). The problem really is that the completion can only: 1) leave the command line unchanged, 2) insert a match (menu completion like or if the match is unambiguous) or 3) insert the unambiguous part of a match. That last one can't work if the matches were generated using pattern matching -- how should it detect which wildcards should be left unchanged and which have been used to match something unambiguously. And note that the stuff I'm talking about is in the C-code, at the very heart of the completion code. We could change the strings generated as matches in _path_files to contain the patterns in the ambiguous components, but that would break menu completion (in the list this could be fixed using display strings, but with menu completion: no way). So, sorry, I don't see a way to implement what you want exactly, without breaking one style of completion or the other. Bye Sven diff -u -r ../oz/Completion/Builtins/_zstyle ./Completion/Builtins/_zstyle --- ../oz/Completion/Builtins/_zstyle Wed Oct 18 20:54:45 2000 +++ ./Completion/Builtins/_zstyle Wed Oct 18 21:47:59 2000 @@ -44,7 +44,7 @@ ignored-patterns c: insert-ids c:insert-ids insert-tab c:bool - insert-unambiguous c:bool + insert-unambiguous c:insunambig keep-prefix c:keep-prefix last-prompt c:bool list c:listwhen @@ -52,6 +52,7 @@ list-packed c:bool list-prompt c: list-rows-first c:bool + list-suffixes c:bool local c: match-original c:match-orig matcher c: @@ -290,6 +291,10 @@ oldmatches) _wanted values expl 'use list of old matches' compadd true false only + ;; + + insunambig) + _wanted values expl 'insert unambiguous string compadd true false pattern ;; urgh) diff -u -r ../oz/Completion/Core/_match ./Completion/Core/_match --- ../oz/Completion/Core/_match Wed Oct 18 20:54:45 2000 +++ ./Completion/Core/_match Wed Oct 18 21:57:34 2000 @@ -11,41 +11,55 @@ ### Shouldn't be needed any more: [[ _matcher_num -gt 1 ]] && return 1 -local tmp opm="$compstate[pattern_match]" ret=0 orig ins +local tmp opm="$compstate[pattern_match]" ret=1 orig ins +local oms="$_old_match_string" ocsi="$compstate[insert]" # Do nothing if we don't have a pattern. tmp="${${:-$PREFIX$SUFFIX}#[~=]}" [[ "$tmp:q" = "$tmp" ]] && return 1 +_old_match_string="$PREFIX$SUFFIX$HISTNO" + zstyle -s ":completion:${curcontext}:" match-original orig -zstyle -b ":completion:${curcontext}:" insert-unambiguous ins +zstyle -s ":completion:${curcontext}:" insert-unambiguous ins # Try completion without inserting a `*'? if [[ -n "$orig" ]]; then compstate[pattern_match]='-' - _complete && ret=1 + _complete && ret=0 compstate[pattern_match]="$opm" - if (( ret )); then - [[ "$ins" = yes && - $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && - compstate[pattern_insert]=unambiguous - return 0 - fi + # No completion with inserting `*'? + + [[ ret -eq 1 && "$orig" = only ]] && return 1 +fi + +if (( ret )); then + compstate[pattern_match]='*' + _complete && ret=0 + compstate[pattern_match]="$opm" fi -# No completion with inserting `*'? +if (( ! ret )); then + + if [[ "$ins" = pattern && $compstate[nmatches] -gt 1 ]]; then -[[ "$orig" = only ]] && return 1 + [[ "$oms" = "$PREFIX$SUFFIX$HISTNO" && + "$compstate[insert]" = automenu-unambiguous ]] && + compstate[insert]=automenu + [[ "$compstate[insert]" != *menu ]] && + compstate[pattern_insert]= compstate[insert]= -compstate[pattern_match]='*' -_complete && ret=1 -compstate[pattern_match]="$opm" + [[ $compstate[unambiguous_cursor] -gt $#compstate[unambiguous] ]] && + ins=yes compstate[insert]="$ocsi" + fi -[[ ret -eq 1 && "$ins" = yes && - $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && - compstate[pattern_insert]=unambiguous + [[ "$ins" = (true|yes|on|1) && + $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && + compstate[pattern_insert]=unambiguous + +fi -return 1-ret +return ret diff -u -r ../oz/Completion/Core/_path_files ./Completion/Core/_path_files --- ../oz/Completion/Core/_path_files Wed Oct 18 20:54:45 2000 +++ ./Completion/Core/_path_files Wed Oct 18 21:48:57 2000 @@ -5,7 +5,7 @@ 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 pfxsfx sopt gopt opt sdirs ignpar cfopt +local pats haspats ignore pfxsfx sopt gopt opt sdirs ignpar cfopt listsfx local nm=$compstate[nmatches] menu matcher mopts sort match mid accex fake typeset -U prepaths exppaths @@ -137,6 +137,8 @@ fi zstyle -s ":completion:${curcontext}:paths" special-dirs sdirs +zstyle -t ":completion:${curcontext}:paths" list-suffixes && + listsfx=yes [[ "$pats" = ((|*[[:blank:]])\*(|[[:blank:]]*)|*\([^[:blank:]]#/[^[:blank:]]#\)*) ]] && sopt=$sopt/ @@ -460,9 +462,11 @@ SUFFIX="${tsuf}" fi - if (( tmp4 )) || - [[ -n "$compstate[pattern_match]" && - "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then + # This once tested `|| [[ -n "$compstate[pattern_match]" && + # "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]' but it should now be smart + # enough to handle multiple components with patterns. + + if (( tmp4 )); then # It is. For menucompletion we now add the possible completions # for this component with the unambigous prefix we have built # and the rest of the string from the line as the suffix. @@ -480,15 +484,33 @@ compquote tmp1 tmp2 fi + if [[ -z "$_comp_correct" && + "$compstate[pattern_match]" = \* && -n "$listsfx" && + "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then + PREFIX="$opre" + SUFFIX="$osuf" + fi + if [[ -n $menu || -z "$compstate[insert]" ]] || - ! zstyle -t ":completion:${curcontext}:paths" expand suffix; then + ! zstyle -t ":completion:${curcontext}:paths" expand suffix || + [[ -z "$listsfx" && + ( -n "$_comp_correct" || + -z "$compstate[pattern_match]" || "$SUFFIX" != */* || + "${SUFFIX#*/}" = (|*[^\\])[][*?#~^\|\<\>]* ) ]]; then (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" ambiguous && compstate[to_end]= if [[ "$tmp3" = */* ]]; then - compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \ - -W "$prepath$realpath$testpath" \ - "$pfxsfx[@]" -M "r:|/=* r:|=*" \ - - "${(@)tmp1%%/*}" + if [[ -z "$listsfx" || "$tmp3" != */?* ]]; then + compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \ + -W "$prepath$realpath$testpath" \ + "$pfxsfx[@]" -M "r:|/=* r:|=*" \ + - "${(@)tmp1%%/*}" + else + compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \ + -W "$prepath$realpath$testpath" \ + "$pfxsfx[@]" -M "r:|/=* r:|=*" \ + - "${(@)^tmp1%%/*}/${tmp3#*/}" + fi else compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \ -W "$prepath$realpath$testpath" \ @@ -497,12 +519,20 @@ fi else if [[ "$tmp3" = */* ]]; then - tmp3=( -Qf "$mopts[@]" -p "$linepath$tmp2" + tmp4=( -Qf "$mopts[@]" -p "$linepath$tmp2" -W "$prepath$realpath$testpath" "$pfxsfx[@]" -M "r:|/=* r:|=*" ) - for i in "$tmp1[@]"; do - compadd "$tmp3[@]" -s "/${i#*/}" - "${i%%/*}" - done + if [[ -z "$listsfx" ]]; then + for i in "$tmp1[@]"; do + compadd "$tmp4[@]" -s "/${i#*/}" - "${i%%/*}" + done + else + [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:s./.*/}*" + + for i in "$tmp1[@]"; do + compadd "$tmp4[@]" - "$i" + done + fi else compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \ -W "$prepath$realpath$testpath" \ @@ -526,22 +556,33 @@ # take it from the filenames. testpath="${testpath}${tmp1[1]%%/*}/" - tmp1=( "${(@)tmp1#*/}" ) tmp3="${tmp3#*/}" if [[ "$tpre" = */* ]]; then - cpre="${cpre}${tpre%%/*}/" + if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" && + "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then + cpre="${cpre}${tmp1[1]%%/*}/" + else + cpre="${cpre}${tpre%%/*}/" + fi tpre="${tpre#*/}" elif [[ "$tsuf" = */* ]]; then [[ "$tsuf" != /* ]] && mid="$testpath" - cpre="${cpre}${tpre}/" + if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" && + "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then + cpre="${cpre}${tmp1[1]%%/*}/" + else + cpre="${cpre}${tpre}/" + fi tpre="${tsuf#*/}" tsuf= else tpre= tsuf= fi + + tmp1=( "${(@)tmp1#*/}" ) done if [[ -z "$tmp4" ]]; then diff -u -r ../oz/Doc/Zsh/compsys.yo ./Doc/Zsh/compsys.yo --- ../oz/Doc/Zsh/compsys.yo Wed Oct 18 20:54:38 2000 +++ ./Doc/Zsh/compsys.yo Wed Oct 18 21:48:15 2000 @@ -1367,6 +1367,10 @@ in the context name to one of tt(correct-)var(num) or tt(approximate-)var(num), where var(num) is the number of errors that were accepted. + +When used for the tt(_match) completer, the style may also be set to +the string `tt(pattern)'. This makes the pattern on the line be left +unchanged if it didn't match unambiguously. ) kindex(keep-prefix, completion style) item(tt(keep-prefix))( @@ -1466,6 +1470,14 @@ determines if matches are to be listed in a rows-first fashion, as for the tt(LIST_ROWS_FIRST) option. ) +kindex(list-suffixes, completion style) +item(tt(list-suffixes))( +This style is used by the function used to complete filenames. If +completion is attempted on a string containing multiple partially +typed pathname components and this style is set to `true', all +components starting with the first one for which more than one match +could be generated will be shown. +) kindex(local, completion style) item(tt(local))( This style is used by completion functions which generate URLs as @@ -2416,6 +2428,9 @@ tt(insert-unambiguous) style is set to `true'. In this case menu completion will only be started if no unambiguous string could be generated that is at least as long as the original string. +The style may also be set to the string `tt(pattern)'. This will keep +the pattern on the line intact as long as there isn't an unambiguous +completion with which it could be replaced. Note that the matcher specifications defined globally or used by the completion functions will not be used. @@ -3474,7 +3489,7 @@ `tt(-r)', and `tt(-R)' options from the tt(compadd) builtin. Finally, the tt(_path_files) function uses the styles tt(expand), -tt(ambiguous) and tt(special-dirs) and tt(file-sort). +tt(ambiguous), tt(special-dirs), tt(list-suffixes) and tt(file-sort). ) findex(_regex_arguments) item(tt(_regex_arguments) var(name) var(specs) ...)( -- Sven Wischnowsky wischnow@informatik.hu-berlin.de