Skip to content

Commit 545e82e

Browse files
committed
update
1 parent da19b70 commit 545e82e

File tree

1 file changed

+82
-162
lines changed

1 file changed

+82
-162
lines changed

lua/dired/init.lua

Lines changed: 82 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ int os_get_uname(uv_uid_t uid, char *s, size_t len);
2828
---@field show_hidden boolean
2929
---@field normal_when_fits boolean
3030
---@field use_trash boolean
31-
---@field file_dir_based boolean
3231
---@field keymaps KeyMapConfig
3332

3433
---@type DiredConfig
@@ -37,7 +36,6 @@ local Config = setmetatable({}, {
3736
local default = {
3837
show_hidden = true,
3938
normal_when_fits = false,
40-
file_dir_based = true,
4139
shortcuts = 'sdfhlwertyuopzxcvbnmSDFGHLQWERTYUOPZXCVBNM',
4240
use_trash = true,
4341
keymaps = {
@@ -234,10 +232,10 @@ local Actions = {}
234232
UI.Entry = {
235233
render = function(state, row, entry)
236234
local formatted = {
237-
perms = Format.permissions(entry.stat.mode),
235+
perms = entry.perms or Format.permissions(entry.stat.mode),
238236
user = entry.user or Format.username(entry.stat.uid),
239-
size = Format.size(entry.stat.size),
240-
time = Format.friendly_time(entry.stat.mtime.sec),
237+
size = entry.size or Format.size(entry.stat.size),
238+
time = entry.date or Format.friendly_time(entry.stat.mtime.sec),
241239
name = entry.name .. (entry.stat.type == 'directory' and SEPARATOR or ''),
242240
}
243241
api.nvim_buf_set_lines(
@@ -729,101 +727,43 @@ local function create_shortcut_manager()
729727
end
730728

731729
local function parse_fd_output(line, current_path)
732-
local perms, links, user, group, size_str, month, day, time, path
733-
perms, links, user, group, size_str, month, day, time, path =
734-
line:match('^(%S+)%s+(%d+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(.+)$')
735-
736-
if not path then
730+
if #line == 0 then
737731
return nil
738732
end
739-
740-
local is_directory = perms:sub(1, 1) == 'd'
741-
742-
local mode = 0
743-
if perms:match('r', 2) then
744-
mode = mode + 0x100
745-
end
746-
if perms:match('w', 3) then
747-
mode = mode + 0x080
748-
end
749-
if perms:match('x', 4) then
750-
mode = mode + 0x040
751-
end
752-
if perms:match('r', 5) then
753-
mode = mode + 0x020
754-
end
755-
if perms:match('w', 6) then
756-
mode = mode + 0x010
757-
end
758-
if perms:match('x', 7) then
759-
mode = mode + 0x008
760-
end
761-
if perms:match('r', 8) then
762-
mode = mode + 0x004
763-
end
764-
if perms:match('w', 9) then
765-
mode = mode + 0x002
766-
end
767-
if perms:match('x', 10) then
768-
mode = mode + 0x001
769-
end
770-
771-
local size = 0
772-
local size_num, size_unit = size_str:match('^([%d%.]+)(.*)$')
773-
if size_num then
774-
size = tonumber(size_num) or 0
775-
if size_unit == 'K' or size_unit == 'KB' then
776-
size = size * 1024
777-
elseif size_unit == 'M' or size_unit == 'MB' then
778-
size = size * 1024 * 1024
779-
elseif size_unit == 'G' or size_unit == 'GB' then
780-
size = size * 1024 * 1024 * 1024
733+
local entry = {}
734+
local data = Iter(vim.split(line, '%s')):map(function(item)
735+
if #item > 0 then
736+
return item
781737
end
738+
end):totable()
739+
if #data < 9 then
740+
return
782741
end
783-
784-
local timestamp = os.time({
785-
year = os.date('%Y'),
786-
month = ({
787-
Jan = 1,
788-
Feb = 2,
789-
Mar = 3,
790-
Apr = 4,
791-
May = 5,
792-
Jun = 6,
793-
Jul = 7,
794-
Aug = 8,
795-
Sep = 9,
796-
Oct = 10,
797-
Nov = 11,
798-
Dec = 12,
799-
})[month] or 1,
800-
day = tonumber(day) or 1,
801-
hour = tonumber(time:match('^(%d+)')) or 0,
802-
min = tonumber(time:match(':(%d+)')) or 0,
803-
})
804-
805-
-- local name = vim.fs.basename(path)
806-
local entry = {
807-
name = path:sub(#current_path + 1):gsub('^' .. SEPARATOR, ''),
808-
path = path,
809-
user = user,
810-
stat = {
811-
mode = mode,
812-
size = size,
813-
mtime = { sec = timestamp },
814-
type = is_directory and 'directory' or 'file',
815-
},
742+
entry.perms = data[1]:gsub('@$', '')
743+
entry.user = data[3]
744+
entry.size = data[5]
745+
entry.date = ('%s %s %s'):format(data[6], data[7], data[8])
746+
747+
local name = data[9]:sub(#current_path + 1)
748+
if name:sub(1, 1) == '/' or name:sub(1, 1) == '\\' then
749+
name = name:sub(2)
750+
end
751+
entry.name = name
752+
entry.stat = {
753+
type = entry.perms:sub(1, 1) == 'd' and 'directory' or 'file',
816754
}
817-
818755
return entry
819756
end
820757

821758
local function create_debounced_search()
822759
local timer = nil
823760
local last_search = ''
824761
local is_searching = false
762+
---@type vim.SystemObj | nil
825763
local current_job = nil
826764
local pending_search = nil
765+
local search_id = 0
766+
local handled_results = 0
827767

828768
local function cleanup()
829769
if timer then
@@ -833,21 +773,30 @@ local function create_debounced_search()
833773
timer:close()
834774
timer = nil
835775
end
836-
837776
if current_job and not current_job:is_closing() then
838777
current_job:kill(9)
839778
current_job = nil
840779
end
841780
end
842781

843-
local function process_and_display_results(results, search_text, callback)
844-
local filters = {}
782+
local reset = function()
783+
last_search = ''
784+
is_searching = false
785+
handled_results = 0
786+
search_id = search_id + 1
787+
cleanup()
788+
end
789+
790+
local function process_and_display_results(results, search_text, callback, id)
791+
if id ~= search_id then
792+
return
793+
end
845794

795+
local filters = {}
846796
if #results > 0 then
847797
local names = Iter(results):map(function(entry)
848798
return entry.name
849799
end):totable()
850-
851800
local res = vim.fn.matchfuzzypos(names, search_text)
852801
for _, entry in ipairs(results) do
853802
for k, v in ipairs(res[1]) do
@@ -858,41 +807,41 @@ local function create_debounced_search()
858807
end
859808
end
860809
end
861-
862810
table.sort(filters, function(a, b)
863811
return a.score > b.score
864812
end)
865813
end
866-
867-
callback(filters)
814+
callback(filters, handled_results)
868815
end
869816

870817
local function execute_search(state, search_text, callback)
871-
if search_text == last_search and not pending_search then
818+
if search_text == last_search then
872819
return
873820
end
874-
875-
if current_job and not current_job:is_closing() then
876-
current_job:kill(9)
877-
current_job = nil
878-
end
879-
821+
reset()
880822
is_searching = true
881823
last_search = search_text
882-
883-
local results = {}
824+
search_id = search_id + 1
825+
local current_search_id = search_id
884826
current_job = vim.system({
885827
'fd',
886828
'-l',
887829
'-i',
888830
'-H',
831+
'--max-depth',
832+
'5',
889833
'--color',
890834
'never',
891835
search_text,
892836
state.current_path,
893837
}, {
894838
text = true,
895839
stdout = function(_, data)
840+
if current_search_id ~= search_id then
841+
return
842+
end
843+
844+
local results = {}
896845
if data then
897846
for _, line in ipairs(vim.split(data, '\n')) do
898847
if #line > 0 then
@@ -905,77 +854,37 @@ local function create_debounced_search()
905854
end
906855
end
907856

908-
if #results >= 50 then
909-
local current_results = vim.deepcopy(results)
857+
if current_search_id == search_id and #results > 0 then
858+
handled_results = handled_results + #results
910859
vim.schedule(function()
911-
process_and_display_results(current_results, search_text, callback)
860+
process_and_display_results(results, search_text, callback, current_search_id)
912861
end)
913862
end
914863
end
915864
end,
916865
}, function(obj)
866+
if current_search_id ~= search_id then
867+
return
868+
end
869+
917870
if obj.code ~= 0 and obj.code ~= 1 then
918871
Notify.err('Search error: ' .. (obj.stderr or 'Unknown error'))
919872
end
920-
921-
vim.schedule(function()
922-
process_and_display_results(results, search_text, callback)
923-
924-
is_searching = false
925-
current_job = nil
926-
927-
if pending_search then
928-
local pending = pending_search
929-
pending_search = nil
930-
execute_search(state, pending.text, pending.callback)
931-
end
932-
end)
933873
end)
934874
end
935875

936876
return {
937877
search = function(state, search_text, callback, delay)
938878
delay = delay or 100
939-
940879
if is_searching then
941-
pending_search = { text = search_text, callback = callback }
942-
return
880+
reset()
943881
end
944-
945-
if not timer then
946-
timer = assert(vim.uv.new_timer())
947-
end
948-
949-
if timer:is_active() then
950-
timer:stop()
951-
end
952-
953-
if #search_text == 0 then
954-
last_search = ''
955-
return vim.schedule(function()
956-
callback(state.entries)
957-
end)
958-
end
959-
960-
timer:start(
961-
delay,
962-
0,
963-
vim.schedule_wrap(function()
964-
execute_search(state, search_text, callback)
965-
end)
966-
)
882+
timer = assert(vim.uv.new_timer())
883+
timer:start(delay, 0, function()
884+
execute_search(state, search_text, callback)
885+
end)
967886
end,
968887
destroy = cleanup,
969-
reset = function()
970-
last_search = ''
971-
is_searching = false
972-
pending_search = nil
973-
974-
if current_job and not current_job:is_closing() then
975-
current_job:kill(9) -- SIGKILL
976-
current_job = nil
977-
end
978-
end,
979888
}
980889
end
981890

@@ -1065,9 +974,25 @@ Browser.State = {
1065974
update_display(state, state.entries)
1066975
return
1067976
end
1068-
state.search_engine.search(state, query, function(entries)
977+
state.entries = {}
978+
state.search_engine.search(state, query, function(entries, count)
979+
state.entries = vim.list_extend(state.entries, entries)
980+
if count > 100 then
981+
state.count_mark =
982+
api.nvim_buf_set_extmark(new_state.search_buf, ns_id, 0, 0, {
983+
id = state.count_mark or nil,
984+
virt_text = {
985+
{
986+
('[1/%d] Find File: '):format(count),
987+
'DiredTitle',
988+
},
989+
},
990+
virt_text_pos = 'inline',
991+
})
992+
return
993+
end
1069994
update_display(state, entries)
1070-
end, 80)
995+
end, 50)
1071996
end,
1072997
on_detach = function()
1073998
if state.search_engine then
@@ -1711,12 +1636,7 @@ end
17111636

17121637
local function browse_directory(path)
17131638
path = path:find(SEPARATOR .. '$') and path or path .. SEPARATOR
1714-
if Config.file_dir_based then
1715-
local fname = api.nvim_buf_get_name(0)
1716-
if #fname > 0 then
1717-
path = vim.fs.dirname(fname) .. SEPARATOR
1718-
end
1719-
end
1639+
17201640
F.IO
17211641
.chain(Browser.State.create(path), function(state)
17221642
return F.IO.chain(Browser.setup(state), function(s)

0 commit comments

Comments
 (0)