Skip to content

Commit 08cc230

Browse files
committed
feat(filesystem): use fd/find as first level filter in fzy, cancel jobs as needed
1 parent c5036c5 commit 08cc230

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

lua/neo-tree/sources/filesystem/init.lua

+2
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ end
184184

185185
M.reset_search = function(state, refresh, open_current_node)
186186
log.trace("reset_search")
187+
-- Cancel any pending search
188+
require("neo-tree.sources.filesystem.lib.filter_external").cancel()
187189
-- reset search state
188190
state.fuzzy_finder_mode = nil
189191
state.use_fzy = nil

lua/neo-tree/sources/filesystem/lib/filter_external.lua

+45-7
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,22 @@ local get_find_command = function(state)
4343
return state.find_command
4444
end
4545

46+
local running_jobs = {}
47+
M.cancel = function()
48+
while #running_jobs > 0 do
49+
local job = table.remove(running_jobs, 1)
50+
local pid = job.pid
51+
job:shutdown()
52+
if pid ~= nil then
53+
if utils.is_windows then
54+
vim.fn.system("taskkill /F /T /PID " .. pid)
55+
else
56+
vim.fn.system("kill -9 " .. pid)
57+
end
58+
end
59+
end
60+
end
61+
4662
---@class FileTypes
4763
---@field file boolean
4864
---@field directory boolean
@@ -68,9 +84,12 @@ end
6884
---@param on_insert? fun(err: string, line: string): any Executed for each line of stdout and stderr.
6985
---@param on_exit? fun(return_val: table): any Executed at the end.
7086
M.filter_files_external = function(cmd, path, glob, regex, full_path, types, ignore, limit, find_args, on_insert, on_exit)
87+
-- First cancel the last job if it is still running
88+
M.cancel()
89+
7190
if glob ~= nil and regex ~= nil then
7291
local log_msg = string.format([[glob: %s, regex: %s]], glob, regex)
73-
log.warning("both glob and regex are set. glob will take precedence. " .. log_msg)
92+
log.warn("both glob and regex are set. glob will take precedence. " .. log_msg)
7493
end
7594
ignore = ignore or {}
7695
types = types or {}
@@ -182,7 +201,7 @@ M.filter_files_external = function(cmd, path, glob, regex, full_path, types, ign
182201
limit = math.huge -- `fd` manages limit on its own
183202
end
184203
local item_count = 0
185-
Job:new({
204+
local job = Job:new({
186205
command = cmd,
187206
cwd = path,
188207
args = args,
@@ -204,7 +223,10 @@ M.filter_files_external = function(cmd, path, glob, regex, full_path, types, ign
204223
on_exit(return_val)
205224
end
206225
end,
207-
}):start()
226+
})
227+
M.cancel()
228+
job:start()
229+
table.insert(running_jobs, job)
208230
end
209231

210232
local function fzy_sort_get_total_score(terms, path)
@@ -247,11 +269,24 @@ M.fzy_sort_files = function(opts, state)
247269
for term in string.gmatch(opts.term, "[^%s]+") do -- space split opts.term
248270
terms[#terms + 1] = term
249271
end
272+
273+
-- The base search is anything that contains the characters in the term
274+
-- The fzy score is then used to sort the results
275+
local chars = {}
276+
local regex = ".*"
277+
for _, term in ipairs(terms) do
278+
for c in term:gmatch(".") do
279+
if not chars[c] then
280+
regex = regex .. c .. "+.*"
281+
end
282+
chars[c] = true
283+
end
284+
end
285+
250286
local result_counter = 0
251287

252-
-- fetch file list for the first time and calculate scores along the way
253288
local index = 1
254-
state.fzy_sort_result_scores = { foo = 0, baz = 0 }
289+
state.fzy_sort_result_scores = {}
255290
local function on_insert(err, path)
256291
if not err then
257292
if result_counter >= limit then
@@ -262,6 +297,9 @@ M.fzy_sort_files = function(opts, state)
262297
relative_path = "./" .. path:sub(pwd_length + 1)
263298
end
264299
index = index + 1
300+
if state.fzy_sort_result_scores == nil then
301+
state.fzy_sort_result_scores = {}
302+
end
265303
state.fzy_sort_result_scores[path] = 0
266304
local score = fzy_sort_get_total_score(terms, relative_path)
267305
if score > 0 then
@@ -273,11 +311,11 @@ M.fzy_sort_files = function(opts, state)
273311
end
274312
end
275313

276-
M.filter_files_external(get_find_command(state), pwd, nil, nil, true,
314+
M.filter_files_external(get_find_command(state), pwd, nil, regex, true,
277315
{ directory = fuzzy_finder_mode == "directory", file = fuzzy_finder_mode ~= "directory" },
278316
{ dotfiles = not filters.visible and filters.hide_dotfiles,
279317
gitignore = not filters.visible and filters.hide_gitignored },
280-
nil, opts.find_args, on_insert, opts.on_exit)
318+
limit * 10, opts.find_args, on_insert, opts.on_exit)
281319
end
282320

283321
M.find_files = function(opts)

0 commit comments

Comments
 (0)