Skip to content

Commit aff738e

Browse files
author
KristofferC
committed
make seen obligatory and remove the deduplicate kwarg
1 parent 0d6e7eb commit aff738e

File tree

3 files changed

+54
-45
lines changed

3 files changed

+54
-45
lines changed

stdlib/REPL/src/History/resumablefiltering.jl

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,25 +253,23 @@ end
253253

254254

255255
"""
256-
filterchunkrev!(out, candidates, spec; idx, maxtime, maxresults, seen, deduplicate) -> Int
256+
filterchunkrev!(out, candidates, spec, seen, idx; maxtime, maxresults) -> Int
257257
258258
Incrementally filter `candidates[1:idx]` in reverse order.
259259
260260
Pushes matches onto `out` until either `maxtime` is exceeded or `maxresults`
261-
collected, then returns the new resume index. When `deduplicate` is true,
262-
only unique entries (by mode and content) are added to avoid showing duplicate history items.
261+
collected, then returns the new resume index. Only unique entries (by mode and content)
262+
are added to avoid showing duplicate history items.
263263
"""
264264
function filterchunkrev!(out::Vector{HistEntry}, candidates::DenseVector{HistEntry},
265-
spec::FilterSpec, idx::Int = length(candidates);
266-
maxtime::Float64 = Inf, maxresults::Int = length(candidates),
267-
seen::Set{Tuple{Symbol,String}} = Set{Tuple{Symbol,String}}(),
268-
deduplicate::Bool = false)
265+
spec::FilterSpec, seen::Set{Tuple{Symbol,String}}, idx::Int = length(candidates);
266+
maxtime::Float64 = Inf, maxresults::Int = length(candidates))
269267
batchsize = clamp(length(candidates) ÷ 512, 10, 1000)
270268
for batch in Iterators.partition(idx:-1:1, batchsize)
271269
time() > maxtime && break
272270
for outer idx in batch
273271
entry = candidates[idx]
274-
if deduplicate && (entry.mode, entry.content) seen
272+
if (entry.mode, entry.content) seen
275273
continue
276274
end
277275
if !isempty(spec.modes)
@@ -299,7 +297,7 @@ function filterchunkrev!(out::Vector{HistEntry}, candidates::DenseVector{HistEnt
299297
end
300298
end
301299
matchfail && continue
302-
deduplicate && push!(seen, (entry.mode, entry.content))
300+
push!(seen, (entry.mode, entry.content))
303301
pushfirst!(out, entry)
304302
length(out) == maxresults && break
305303
end

stdlib/REPL/src/History/search.jl

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ function run_display!((; term, pstate), events::Channel{Symbol}, hist::Vector{Hi
6363
# Filter state
6464
filter_idx = 0
6565
filter_seen = Set{Tuple{Symbol,String}}()
66-
isfiltering = false
6766
# Event loop
6867
while true
6968
event = @lock events if !isempty(events) take!(events) end
@@ -157,14 +156,19 @@ function run_display!((; term, pstate), events::Channel{Symbol}, hist::Vector{Hi
157156
# Start filtering candidates
158157
# Only deduplicate when user has entered a search query. When browsing
159158
# with no filter (empty query), show all history including duplicates.
160-
isfiltering = !isempty(filter_spec.exacts) || !isempty(filter_spec.negatives) ||
161-
!isempty(filter_spec.regexps) || !isempty(filter_spec.modes)
162-
empty!(filter_seen)
163-
filter_idx = filterchunkrev!(
164-
state, cands_current;
165-
maxtime = time() + 0.01,
166-
maxresults = outsize[1],
167-
seen = filter_seen, deduplicate = isfiltering)
159+
if isempty(filter_spec.exacts) && isempty(filter_spec.negatives) &&
160+
isempty(filter_spec.regexps) && isempty(filter_spec.modes)
161+
# No filtering needed, just copy all candidates
162+
append!(state.candidates, cands_current)
163+
filter_idx = 0
164+
else
165+
# Filtering needed, deduplicate results
166+
empty!(filter_seen)
167+
filter_idx = filterchunkrev!(
168+
state, cands_current, filter_seen;
169+
maxtime = time() + 0.01,
170+
maxresults = outsize[1])
171+
end
168172
if filter_idx == 0
169173
cands_cachestate = addcache!(
170174
cands_cache, cands_cachestate, cands_cond => state.candidates)
@@ -194,9 +198,8 @@ function run_display!((; term, pstate), events::Channel{Symbol}, hist::Vector{Hi
194198
state.area, state.query, state.filter, cands_temp,
195199
state.scroll, state.selection, state.hover)
196200
filter_idx = filterchunkrev!(
197-
state, cands_current, filter_idx;
198-
maxtime = time() + 0.01,
199-
seen = filter_seen, deduplicate = isfiltering)
201+
state, cands_current, filter_seen, filter_idx;
202+
maxtime = time() + 0.01)
200203
if filter_idx == 0
201204
cands_cachestate = addcache!(
202205
cands_cache, cands_cachestate, cands_cond => state.candidates)
@@ -212,13 +215,12 @@ function run_display!((; term, pstate), events::Channel{Symbol}, hist::Vector{Hi
212215
end
213216
end
214217

215-
function filterchunkrev!(state::SelectorState, candidates::DenseVector{HistEntry}, idx::Int = length(candidates);
216-
maxtime::Float64 = Inf, maxresults::Int = length(candidates),
217-
seen::Set{Tuple{Symbol,String}} = Set{Tuple{Symbol,String}}(),
218-
deduplicate::Bool = false)
218+
function filterchunkrev!(state::SelectorState, candidates::DenseVector{HistEntry},
219+
seen::Set{Tuple{Symbol,String}}, idx::Int = length(candidates);
220+
maxtime::Float64 = Inf, maxresults::Int = length(candidates))
219221
oldlen = length(state.candidates)
220-
idx = filterchunkrev!(state.candidates, candidates, state.filter, idx;
221-
maxtime = maxtime, maxresults = maxresults, seen = seen, deduplicate = deduplicate)
222+
idx = filterchunkrev!(state.candidates, candidates, state.filter, seen, idx;
223+
maxtime = maxtime, maxresults = maxresults)
222224
newlen = length(state.candidates)
223225
newcands = view(state.candidates, (oldlen + 1):newlen)
224226
gfound = Int[]

stdlib/REPL/test/history.jl

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -279,69 +279,80 @@ end
279279
empty!(results)
280280
cset = ConditionSet("hello")
281281
spec = FilterSpec(cset)
282-
@test filterchunkrev!(results, entries, spec) == 0
282+
seen = Set{Tuple{Symbol,String}}()
283+
@test filterchunkrev!(results, entries, spec, seen) == 0
283284
@test results == [entries[1], entries[7]]
284285
empty!(results)
285286
cset2 = ConditionSet("world")
286287
spec2 = FilterSpec(cset2)
287-
@test filterchunkrev!(results, entries, spec2) == 0
288+
empty!(seen)
289+
@test filterchunkrev!(results, entries, spec2, seen) == 0
288290
@test results == [entries[1], entries[7]]
289291
empty!(results)
290292
cset3 = ConditionSet("World")
291293
spec3 = FilterSpec(cset3)
292-
@test filterchunkrev!(results, entries, spec3) == 0
294+
empty!(seen)
295+
@test filterchunkrev!(results, entries, spec3, seen) == 0
293296
@test results == [entries[7]]
294297
end
295298
@testset "Exact" begin
296299
empty!(results)
297300
cset = ConditionSet("=test")
298301
spec = FilterSpec(cset)
299-
@test filterchunkrev!(results, entries, spec, maxresults = 2) == 5
302+
seen = Set{Tuple{Symbol,String}}()
303+
@test filterchunkrev!(results, entries, spec, seen; maxresults = 2) == 5
300304
@test results == [entries[6], entries[9]]
301305
empty!(results)
302306
cset2 = ConditionSet("=test case")
303307
spec2 = FilterSpec(cset2)
304-
@test filterchunkrev!(results, entries, spec2) == 0
308+
empty!(seen)
309+
@test filterchunkrev!(results, entries, spec2, seen) == 0
305310
@test results == [entries[3]]
306311
end
307312
@testset "Negative" begin
308313
empty!(results)
309314
cset = ConditionSet("!hello ; !test;! cos")
310315
spec = FilterSpec(cset)
311-
@test filterchunkrev!(results, entries, spec) == 0
316+
seen = Set{Tuple{Symbol,String}}()
317+
@test filterchunkrev!(results, entries, spec, seen) == 0
312318
@test results == [entries[2], entries[7], entries[8]]
313319
end
314320
@testset "Initialism" begin
315321
empty!(results)
316322
cset = ConditionSet("`tc")
317323
spec = FilterSpec(cset)
318-
@test filterchunkrev!(results, entries, spec) == 0
324+
seen = Set{Tuple{Symbol,String}}()
325+
@test filterchunkrev!(results, entries, spec, seen) == 0
319326
@test results == [entries[3]]
320327
empty!(results)
321328
cset2 = ConditionSet("`fb")
322329
spec2 = FilterSpec(cset2)
323-
@test filterchunkrev!(results, entries, spec2) == 0
330+
empty!(seen)
331+
@test filterchunkrev!(results, entries, spec2, seen) == 0
324332
@test results == [entries[8]]
325333
end
326334
@testset "Regexp" begin
327335
empty!(results)
328336
cset = ConditionSet("/^c.s\\b")
329337
spec = FilterSpec(cset)
330-
@test filterchunkrev!(results, entries, spec) == 0
338+
seen = Set{Tuple{Symbol,String}}()
339+
@test filterchunkrev!(results, entries, spec, seen) == 0
331340
@test results == [entries[4], entries[5]]
332341
end
333342
@testset "Mode" begin
334343
empty!(results)
335344
cset = ConditionSet(">shell")
336345
spec = FilterSpec(cset)
337-
@test filterchunkrev!(results, entries, spec) == 0
346+
seen = Set{Tuple{Symbol,String}}()
347+
@test filterchunkrev!(results, entries, spec, seen) == 0
338348
@test results == [entries[7]]
339349
end
340350
@testset "Fuzzy" begin
341351
empty!(results)
342352
cset = ConditionSet("~cs")
343353
spec = FilterSpec(cset)
344-
@test filterchunkrev!(results, entries, spec) == 0
354+
seen = Set{Tuple{Symbol,String}}()
355+
@test filterchunkrev!(results, entries, spec, seen) == 0
345356
@test results == entries[3:6]
346357
end
347358
@testset "Uniqueness" begin
@@ -360,16 +371,14 @@ end
360371
cset = ConditionSet("cos")
361372
spec = FilterSpec(cset)
362373
seen = Set{Tuple{Symbol,String}}()
363-
@test filterchunkrev!(results, dup_entries, spec; seen=seen, deduplicate=true) == 0
374+
@test filterchunkrev!(results, dup_entries, spec, seen) == 0
364375
# Should only get unique entries matching the filter
365376
# Since we iterate in reverse (7->1), we keep the most recent occurrence of each unique content
366377
@test length(results) == 1
367378
@test results[1] == dup_entries[5] # cos(2π) - most recent
368-
# When browsing without seen Set, duplicates are kept
379+
# When browsing without filtering, duplicates are kept
369380
empty!(results)
370-
cset2 = ConditionSet("") # No filter
371-
spec2 = FilterSpec(cset2)
372-
@test filterchunkrev!(results, dup_entries, spec2) == 0
381+
append!(results, dup_entries)
373382
@test length(results) == 7 # All entries, including duplicates
374383
@test results == dup_entries
375384
# Test that same content in different modes is NOT deduplicated
@@ -380,10 +389,10 @@ end
380389
HistEntry(:julia, now(UTC), "ls", 3), # duplicate in :julia mode
381390
HistEntry(:shell, now(UTC), "pwd", 4),
382391
]
383-
seen = Set{Tuple{Symbol,String}}()
392+
empty!(seen)
384393
cset3 = ConditionSet("ls")
385394
spec3 = FilterSpec(cset3)
386-
@test filterchunkrev!(results, mode_entries, spec3; seen=seen, deduplicate=true) == 0
395+
@test filterchunkrev!(results, mode_entries, spec3, seen) == 0
387396
@test length(results) == 2 # "ls" from :julia and "ls" from :shell
388397
@test results[1] == mode_entries[2] # :shell ls
389398
@test results[2] == mode_entries[3] # :julia ls (most recent)

0 commit comments

Comments
 (0)