From 67dd7e1923f8084de1064bf54659100626c1e0ef Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sun, 9 Feb 2025 13:22:33 +0900 Subject: Add 'exclude' action for excluding current/selected items from the result (#4231) Close #4185 --- src/pattern.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'src/pattern.go') diff --git a/src/pattern.go b/src/pattern.go index 8919ad87..93640cb6 100644 --- a/src/pattern.go +++ b/src/pattern.go @@ -63,6 +63,7 @@ type Pattern struct { revision revision procFun map[termType]algo.Algo cache *ChunkCache + denylist map[int32]struct{} } var _splitRegex *regexp.Regexp @@ -73,7 +74,7 @@ func init() { // BuildPattern builds Pattern object from the given arguments func BuildPattern(cache *ChunkCache, patternCache map[string]*Pattern, fuzzy bool, fuzzyAlgo algo.Algo, extended bool, caseMode Case, normalize bool, forward bool, - withPos bool, cacheable bool, nth []Range, delimiter Delimiter, revision revision, runes []rune) *Pattern { + withPos bool, cacheable bool, nth []Range, delimiter Delimiter, revision revision, runes []rune, denylist map[int32]struct{}) *Pattern { var asString string if extended { @@ -144,6 +145,7 @@ func BuildPattern(cache *ChunkCache, patternCache map[string]*Pattern, fuzzy boo revision: revision, delimiter: delimiter, cache: cache, + denylist: denylist, procFun: make(map[termType]algo.Algo)} ptr.cacheKey = ptr.buildCacheKey() @@ -243,6 +245,9 @@ func parseTerms(fuzzy bool, caseMode Case, normalize bool, str string) []termSet // IsEmpty returns true if the pattern is effectively empty func (p *Pattern) IsEmpty() bool { + if len(p.denylist) > 0 { + return false + } if !p.extended { return len(p.text) == 0 } @@ -296,14 +301,38 @@ func (p *Pattern) Match(chunk *Chunk, slab *util.Slab) []Result { func (p *Pattern) matchChunk(chunk *Chunk, space []Result, slab *util.Slab) []Result { matches := []Result{} + if len(p.denylist) == 0 { + // Huge code duplication for minimizing unnecessary map lookups + if space == nil { + for idx := 0; idx < chunk.count; idx++ { + if match, _, _ := p.MatchItem(&chunk.items[idx], p.withPos, slab); match != nil { + matches = append(matches, *match) + } + } + } else { + for _, result := range space { + if match, _, _ := p.MatchItem(result.item, p.withPos, slab); match != nil { + matches = append(matches, *match) + } + } + } + return matches + } + if space == nil { for idx := 0; idx < chunk.count; idx++ { + if _, prs := p.denylist[chunk.items[idx].Index()]; prs { + continue + } if match, _, _ := p.MatchItem(&chunk.items[idx], p.withPos, slab); match != nil { matches = append(matches, *match) } } } else { for _, result := range space { + if _, prs := p.denylist[result.item.Index()]; prs { + continue + } if match, _, _ := p.MatchItem(result.item, p.withPos, slab); match != nil { matches = append(matches, *match) } -- cgit v1.2.3