Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Feature request: #a (approximate matching) only for spaces



On Dec 7,  5:44am, Mikael Magnusson wrote:
}
} % print -l ${~s//(#b)(?)/$match[1]*} # make the pattern g*i*t*p*u*r*g*e*

Yeah, but that also matches gfooifootfooifoopfooufoorfoogfooefoo, which
I'm not sure is what Sebastian wants.  The pattern

(g*tpurge|gi*tpurge|git*purge|gitp*urge|gitpu*rge|gitpur*ge|gitpurg*e)*

is probably closer to what he wants, but it's a bit ugly to generate a
pattern like that:

    setopt histsubstpattern extendedglob
    s="gitpurge"			# string is $#s chars long
    a=( ( "${(@)${(s::)s}/?/}" )	# array of $#s empty elements
    x=( ${s:^^a} )			# array of $#s copies of $s
    i=1
    p=( ${x:s/(#b)(#s)(?(#c$[i++]))/$match[1]*} )	# $#s patterns
    print -lr - (${(j:|:)~p})*		# join and enable matching

Amazingly, you can write that as a one-liner, if you don't count the
necessity of the setopts and declaring the parameters:

    (${(j:|:)~${i::=1}+${${:-$INPUT"${(@)^${(s::)INPUT}/?/}"}:s/(#b)(#s)(?(#c$[i++]))/$match[1]*}})*

I renamed $s to $INPUT to make it easier to pick out from the rest of
the chicken scratching.

Breaking that down ...

    1. ${i::=1} forces $i to reset to 1 before the rest of this expands.
    2. The "+" after that says that if $i is set, substitute what follows
       instead.  Since we just forced $i to be set, this always happens.
    3. ${:-words} inserts those words as a nested expansion where they
       otherwise would be a parse error.
    4. "${(@)^${(s::)INPUT}/?/}" forms an array of $#INPUT empty elements
       and also turns on rc_expand_param [the caret after (@)].
    5. Juxtaposing (4) with $INPUT results in $#INPUT copies of $INPUT
       as an array for the rest of the substitution to act upon.
    6. The :s// expression applies to that array such that $[i++] is
       evaluated for each element.  This is unlike ${..//pat/rep} which
       evaluates pat only once, and thus why we need hist_subst_pattern.
    7. Hence (?(#c$[i++])) matches $i characters at array index $i, and
       we front-anchor that with (#s) and grab a reference to it with
       (#b), then use it in the replacement as $match[1].
    8. Then (j:|:) combines the resulting $#INPUT patterns and ~ makes
       active both the | and the * inserted by :s/.../$match[1]* so the
       whole expansion becomes a single pattern.

Theoretically it should work to use this pattern as a subscript of the
$history associative array with the (r) or (R) subscript flags to find
all matching history events.

-- 
Barton E. Schaefer



Messages sorted by: Reverse Date, Date, Thread, Author