You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lua/fuzzy/match.lua
+12-5Lines changed: 12 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -116,7 +116,8 @@ end
116
116
117
117
functionMatch:_clean_context()
118
118
ifself._state.bufferthen
119
-
-- clear the buffer to avoid holding references to old data, do return them to the pool, from where we can easily pull them back
119
+
-- clear the buffer to avoid holding references to old data, do return them to the pool, from where we can easily pull
120
+
-- them back
120
121
fori, valueinipairs(self._state.buffer) do
121
122
ifi==1then
122
123
utils.fill_table(
@@ -250,7 +251,11 @@ end
250
251
--- Returns true if the matcher is considered finalized and no longer processing data in-flight, and there is a valid set of data present for consumption produced by the matcher
251
252
--- @returnboolean True if the matcher has finalized and matched results data is ready to be consumed by the client
@@ -182,12 +183,14 @@ function Picker:_close_picker()
182
183
self.select:close()
183
184
self.match:destroy()
184
185
self.stream:destroy()
186
+
self:_running_match()
185
187
self:_caching_display()
186
188
end
187
189
188
190
functionPicker:_cancel_picker()
189
191
self.select:close()
190
192
self.match:destroy()
193
+
self:_running_match()
191
194
ifself.stream:running() then
192
195
self.stream:destroy()
193
196
self:_caching_display()
@@ -199,6 +202,7 @@ end
199
202
functionPicker:_clear_picker()
200
203
self.select:clear()
201
204
self.match:destroy()
205
+
self:_running_match()
202
206
ifself.stream:running() then
203
207
self.stream:destroy()
204
208
self:_caching_display()
@@ -360,10 +364,12 @@ function Picker:_input_prompt()
360
364
ifnotself.stream:isvalid() then
361
365
return
362
366
end
367
+
-- the picker is ensured to be valid
363
368
data=assert(self.stream.results)
364
369
elseifself:_is_static() then
365
370
data=assert(self._state.content)
366
371
else
372
+
-- at this point what is that here !
367
373
assert(false, "unknown picker state")
368
374
end
369
375
@@ -401,6 +407,7 @@ function Picker:_input_prompt()
401
407
"%d/%d", #data, #data
402
408
))
403
409
end
410
+
self:_running_match()
404
411
end
405
412
end)
406
413
end
@@ -566,6 +573,110 @@ function Picker:_compute_headers(headers, actions)
566
573
returnvim.list_extend(headers, action_headers)
567
574
end
568
575
576
+
functionPicker:_running_match(matching, query)
577
+
-- Maintain a running accumulator of match results while a stream is active; it is a
578
+
-- {matches, positions, scores} triplet that grows per chunk, resets on query change,
579
+
-- and is released when matching is nil.
580
+
localstate=assert(self._state)
581
+
ifmatching==nilandstate.matchingthen
582
+
localmatch_state=state.matching
583
+
localfunctionrelease_table(tbl)
584
+
fori, valueinipairs(tbl) do
585
+
ifnotPool.is_pooled(value) then
586
+
utils.fill_table(
587
+
value,
588
+
i==1andutils.EMPTY_STRING
589
+
or (i==2andutils.EMPTY_TABLEor0)
590
+
)
591
+
gotocontinue
592
+
end
593
+
ifi==1then
594
+
utils.fill_table(
595
+
value,
596
+
utils.EMPTY_STRING
597
+
)
598
+
elseifi==2then
599
+
utils.fill_table(
600
+
value,
601
+
utils.EMPTY_TABLE
602
+
)
603
+
else
604
+
utils.fill_table(
605
+
value, 0
606
+
)
607
+
end
608
+
Pool._return(value)
609
+
::continue::
610
+
end
611
+
end
612
+
613
+
ifmatch_state.bufferthen
614
+
release_table(match_state.buffer)
615
+
match_state.buffer=nil
616
+
end
617
+
ifmatch_state.accumthen
618
+
release_table(match_state.accum)
619
+
match_state.accum=nil
620
+
end
621
+
match_state.query=nil
622
+
state.matching=nil
623
+
returnmatching
624
+
elseifmatching~=nilthen
625
+
ifnotstate.matchingthen
626
+
state.matching= {
627
+
accum=nil,
628
+
buffer=nil,
629
+
query=query,
630
+
debounced=nil,
631
+
}
632
+
end
633
+
ifstate.matching.query~=querythen
634
+
self:_running_match()
635
+
state.matching= {}
636
+
end
637
+
localmatch_state=state.matching
638
+
match_state.query=assert(query)
639
+
640
+
ifnotmatch_state.accumor#match_state.accum==0then
641
+
localobtain_table=Pool.prime_min~=nil
642
+
and#matching[1] >=Pool.prime_min
643
+
match_state.accum= {
644
+
obtain_tableandPool.obtain(#matching[1]) or {},
645
+
obtain_tableandPool.obtain(#matching[2]) or {},
646
+
obtain_tableandPool.obtain(#matching[3]) or {},
647
+
}
648
+
fori=1, 3, 1do
649
+
utils.resize_table(
650
+
match_state.accum[i],
651
+
#matching[i], nil
652
+
)
653
+
forj=1, #matching[i], 1do
654
+
match_state.accum[i][j] =matching[i][j]
655
+
end
656
+
end
657
+
else
658
+
ifnotmatch_state.bufferthen
659
+
localobtain_table=Pool.prime_min~=nil
660
+
and#matching[1] >=Pool.prime_min
661
+
match_state.buffer= {
662
+
obtain_tableandPool.obtain(#matching[1]) or {},
663
+
obtain_tableandPool.obtain(#matching[2]) or {},
664
+
obtain_tableandPool.obtain(#matching[3]) or {},
665
+
}
666
+
end
667
+
localresult, _=utils.timed_call(Match.merge,
668
+
match_state.buffer, match_state.accum, matching
669
+
)
670
+
match_state.buffer=match_state.accum
671
+
match_state.accum=assert(result)
672
+
assert(#result[1] ==#result[2])
673
+
assert(#result[2] ==#result[3])
674
+
end
675
+
returnassert(match_state.accum)
676
+
end
677
+
returnmatching
678
+
end
679
+
569
680
functionPicker:_caching_display(init)
570
681
localstate=assert(self._state)
571
682
ifnotinitandstate.cachingthen
@@ -625,9 +736,10 @@ function Picker:_ticking_counter(init)
625
736
end
626
737
627
738
functionPicker:_flush_interactive()
628
-
-- Interactive stream flush: stream is the source of truth (no fuzzy match), render accumulated results and status, debounce to coalesce very fast flushes.
-- Stream finished: if it produced nothing, explicitly render an empty list, then signal completion.
632
744
ifnotself.stream:isvalid() orself.stream:isempty() then
633
745
self.select:list(
@@ -636,7 +748,8 @@ function Picker:_flush_interactive()
636
748
)
637
749
self.select:status("0/0")
638
750
end
639
-
-- Final nil list marks end of streaming: Select stops incremental updates and treats the list as stable until new data arrives (or re-open).
751
+
-- Final nil list marks end of streaming: Select stops incremental updates and treats the list as stable until new data arrives
752
+
-- (or re-open).
640
753
self.select:list(nil, nil)
641
754
else
642
755
-- Streaming in progress: show all accumulated results so far.
@@ -649,9 +762,10 @@ function Picker:_flush_interactive()
649
762
end
650
763
651
764
functionPicker:_flush_direct()
652
-
-- Direct stream flush (non-interactive): match per chunk and merge into accumulator when query is present, render all results when empty, debounce to coalesce rapid flushes.
-- No query, render all of the results as-is and reset any running accumulator, as it will have become
701
853
-- invalid anyway with an empty query
702
854
self.select:list(all, nil)
703
855
self.select:status(string.format(
704
856
"%d/%d", #all, #all
705
857
))
858
+
self:_running_match()
706
859
end
707
860
end
708
861
end)
@@ -886,6 +1039,7 @@ end
886
1039
--- @fieldheaders? table[]|nil a list of headers to display in the picker, each header must be a list of tuples, where each tuple is a pair of a string and a highlight group name, the string is the text to display, and the highlight group name is the highlight group to use for displaying the text, for example: { {"<c-n>", "PickerHeaderActionKey"}, {"::", "PickerHeaderActionSeparator"}, {"next", "PickerHeaderActionLabel"} }.
887
1040
--- @fieldmatch_limit? number|nil the maximum number of matches to keep, nil means no limit.
888
1041
--- @fieldmatch_timer? number the time in milliseconds to wait before flushing the matching results, this is useful when dealing with large result sets.
1042
+
--- @fieldmatch_debounce? number the time in milliseconds to debounce streaming match starts, this is useful to avoid re-matching the full list on every flush.
889
1043
--- @fieldmatch_step? number the number of entries to process in each matching step, this is useful when dealing with large result sets.
890
1044
--- @fieldstream_type? "lines"|"bytes" whether the stream produces lines or bytes, when lines is used the stream will be split on newlines, when bytes is used the stream will be split on byte size.
891
1045
--- @fieldstream_step? number the number of bytes or lines to read in each streaming step, this is useful when dealing with large result sets.
0 commit comments