@@ -1628,25 +1628,47 @@ fu! s:highlight(pat, grp)
16281628 el
16291629 let pat = a: pat
16301630
1631- " calculate how many letters are here
1632- let lettercount = len (split (pat, ' \\{-}' ))
1633- for i in range (lettercount)
1634- " surround the letter we care about with \zs and \ze so only it is
1635- " highlighted in this go. Prefer the letter right next to the previous
1636- " one, otherwise scan out to the last one
1637- let letterpat = substitute (pat,
1638- \ ' ^\%(\\\?.\zs\[\^\\\?.\]\\{-}\)\{' .i .' }\(\\\?.\)\%(\[\^\\\?.\]\\{-}\)\?\ze.*$' ,
1639- \ ' \\(\\zs\1\\|.*\\zs\1\\)\\ze.\\{-}' , ' ' )
1640-
1641- if s: byfname
1642- " replace [^x] with [^/x] to make sure no slashes between letters
1643- let letterpat = substitute (letterpat, ' \[\^\(.\{-}\)\]\\{-}' , ' [^\\/\1]\\{-}' , ' g' )
1644- " replace the end to make sure no slashes follow the pattern
1645- let letterpat = substitute (letterpat, ' \$\@<!$' , ' [^\\/]*$' , ' g' )
1646- en
1647-
1648- cal matchadd (a: grp , ( s: martcs == ' ' ? ' \c' : ' \C' ).letterpat)
1649- endfo
1631+ " get original characters so we can rebuild pat
1632+ let chars = split (pat, ' \[\^\\\?.\]\\{-}' )
1633+
1634+ " Build a pattern like /a.*b.*c/ from abc (but with .\{-} non-greedy
1635+ " matchers instead)
1636+ let pat = join (chars, ' .\{-}' )
1637+ " Ensure we match the last version of our pattern
1638+ let ending = ' \(.*' .pat.' \)\@!'
1639+ " Case sensitive?
1640+ let beginning = ( s: martcs == ' ' ? ' \c' : ' \C' ).' ^.*'
1641+ if s: byfname
1642+ " Make sure there are no slashes in our match
1643+ let beginning = beginning.' \([^\/]*$\)\@='
1644+ end
1645+
1646+ for i in range (len (chars))
1647+ " Surround our current target letter with \zs and \ze so it only
1648+ " actually matches that one letter, but has all preceding and trailing
1649+ " letters as well.
1650+ " \zsa.*b.*c
1651+ " a\(\zsb\|.*\zsb)\ze.*c
1652+ let charcopy = copy (chars)
1653+ if i == 0
1654+ let charcopy[i ] = ' \zs' .charcopy[i ].' \ze'
1655+ let middle = join (charcopy, ' .\{-}' )
1656+ else
1657+ let before = join (charcopy[0 :i - 1 ], ' .\{-}' )
1658+ let after = join (charcopy[i + 1 :-1 ], ' .\{-}' )
1659+ let c = charcopy[i ]
1660+ " for abc, match either ab.\{-}c or a.*b.\{-}c in that order
1661+ let cpat = ' \(\zs' .c .' \|' .' .*\zs' .c .' \)\ze.*'
1662+ let middle = before.cpat.after
1663+ endif
1664+
1665+ " Now we matchadd for each letter, the basic form being:
1666+ " ^.*\zsx\ze.*$, but with our pattern we built above for the letter,
1667+ " and a negative lookahead ensuring that we only highlight the last
1668+ " occurrence of our letters. We also ensure that our matcher is case
1669+ " insensitive or sensitive depending.
1670+ cal matchadd (a: grp , beginning.middle.ending)
1671+ endfor
16501672 en
16511673
16521674 cal matchadd (' CtrlPLinePre' , ' ^>' )
0 commit comments