@@ -36,7 +36,7 @@ local Config = setmetatable({}, {
3636 __index = function (_ , scope )
3737 local default = {
3838 show_hidden = true ,
39- normal_when_fits = true ,
39+ normal_when_fits = false ,
4040 file_dir_based = true ,
4141 shortcuts = ' sdfhlwertyuopzxcvbnmSDFGHLQWERTYUOPZXCVBNM' ,
4242 use_trash = true ,
@@ -233,7 +233,7 @@ UI.Entry = {
233233 render = function (state , row , entry )
234234 local formatted = {
235235 perms = Format .permissions (entry .stat .mode ),
236- user = Format .username (entry .stat .uid ),
236+ user = entry . user or Format .username (entry .stat .uid ),
237237 size = Format .size (entry .stat .size ),
238238 time = Format .friendly_time (entry .stat .mtime .sec ),
239239 name = entry .name .. (entry .stat .type == ' directory' and SEPARATOR or ' ' ),
@@ -733,7 +733,6 @@ local function create_debounced_search()
733733 local is_searching = false
734734 local pending_search = nil
735735
736- -- 清理函数
737736 local function cleanup ()
738737 if timer then
739738 if timer :is_active () then
@@ -826,6 +825,96 @@ local function create_debounced_search()
826825 }
827826end
828827
828+ local function parse_fd_output (line , current_path )
829+ local perms , links , user , group , size_str , month , day , time , path
830+ perms , links , user , group , size_str , month , day , time , path =
831+ line :match (' ^(%S+)%s+(%d+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(.+)$' )
832+
833+ if not path then
834+ return nil
835+ end
836+
837+ local is_directory = perms :sub (1 , 1 ) == ' d'
838+
839+ local mode = 0
840+ if perms :match (' r' , 2 ) then
841+ mode = mode + 0x100
842+ end
843+ if perms :match (' w' , 3 ) then
844+ mode = mode + 0x080
845+ end
846+ if perms :match (' x' , 4 ) then
847+ mode = mode + 0x040
848+ end
849+ if perms :match (' r' , 5 ) then
850+ mode = mode + 0x020
851+ end
852+ if perms :match (' w' , 6 ) then
853+ mode = mode + 0x010
854+ end
855+ if perms :match (' x' , 7 ) then
856+ mode = mode + 0x008
857+ end
858+ if perms :match (' r' , 8 ) then
859+ mode = mode + 0x004
860+ end
861+ if perms :match (' w' , 9 ) then
862+ mode = mode + 0x002
863+ end
864+ if perms :match (' x' , 10 ) then
865+ mode = mode + 0x001
866+ end
867+
868+ local size = 0
869+ local size_num , size_unit = size_str :match (' ^([%d%.]+)(.*)$' )
870+ if size_num then
871+ size = tonumber (size_num ) or 0
872+ if size_unit == ' K' or size_unit == ' KB' then
873+ size = size * 1024
874+ elseif size_unit == ' M' or size_unit == ' MB' then
875+ size = size * 1024 * 1024
876+ elseif size_unit == ' G' or size_unit == ' GB' then
877+ size = size * 1024 * 1024 * 1024
878+ end
879+ end
880+
881+ local timestamp = os.time ({
882+ year = os.date (' %Y' ),
883+ month = ({
884+ Jan = 1 ,
885+ Feb = 2 ,
886+ Mar = 3 ,
887+ Apr = 4 ,
888+ May = 5 ,
889+ Jun = 6 ,
890+ Jul = 7 ,
891+ Aug = 8 ,
892+ Sep = 9 ,
893+ Oct = 10 ,
894+ Nov = 11 ,
895+ Dec = 12 ,
896+ })[month ] or 1 ,
897+ day = tonumber (day ) or 1 ,
898+ hour = tonumber (time :match (' ^(%d+)' )) or 0 ,
899+ min = tonumber (time :match (' :(%d+)' )) or 0 ,
900+ })
901+
902+ -- local name = vim.fs.basename(path)
903+ local entry = {
904+ name = path :sub (# current_path + 1 ):gsub (' ^' .. SEPARATOR , ' ' ),
905+ path = path ,
906+ user = user ,
907+ stat = {
908+ mode = mode ,
909+ size = size ,
910+ mtime = { sec = timestamp },
911+ type = is_directory and ' directory' or ' file' ,
912+ },
913+ }
914+
915+ return entry
916+ end
917+
829918Browser .State = {
830919 create = function (path )
831920 local width = math.floor (vim .o .columns * 0.8 )
@@ -893,25 +982,82 @@ Browser.State = {
893982 if change_mode == nil then
894983 change_mode = true
895984 end
896- if change_mode and # entries_to_show <= api .nvim_win_get_height (new_state .win ) then
985+ if
986+ change_mode
987+ and Config .normal_when_fits
988+ and # entries_to_show <= api .nvim_win_get_height (new_state .win )
989+ then
897990 api .nvim_feedkeys (api .nvim_replace_termcodes (' <ESC>' , true , false , true ), ' n' , true )
898991 end
899992
900993 if not s .initialized then
901- -- Attach buffer for search
902994 api .nvim_buf_attach (state .search_buf , false , {
903995 on_lines = function ()
904996 -- Get search text without prompt path
905997 local query =
906998 api .nvim_get_current_line ():gsub (state .abbr_path or state .current_path , ' ' )
907999
1000+ -- Empty query or directory navigation
9081001 if query == ' ' or query :match (SEPARATOR .. ' $' ) then
9091002 update_display (state , state .entries )
9101003 return
9111004 end
912- state .search_engine .search (state , query , function (filtered_entries )
913- update_display (state , filtered_entries , false )
914- end , 80 )
1005+
1006+ if vim .fn .executable (' rg' ) == 1 then
1007+ vim .system ({
1008+ ' fd' ,
1009+ ' -l' ,
1010+ ' -i' ,
1011+ ' -H' ,
1012+ ' --color' ,
1013+ ' never' ,
1014+ query ,
1015+ state .current_path ,
1016+ }, {
1017+ text = true ,
1018+ }, function (obj )
1019+ local results = {}
1020+ if obj .code ~= 0 and obj .code ~= 1 then
1021+ Notify .err (vim .inspect (obj ))
1022+ return
1023+ end
1024+ if obj .stdout and # obj .stdout > 0 then
1025+ for _ , line in ipairs (vim .split (obj .stdout , ' \n ' )) do
1026+ if # line > 0 then
1027+ local entry = parse_fd_output (line , state .current_path )
1028+ if entry then
1029+ local len = # entry .name
1030+ + (entry .stat .type == ' directory' and 1 or 0 )
1031+ state .maxwidth = math.max (state .maxwidth , len )
1032+ table.insert (results , entry )
1033+ end
1034+ end
1035+ end
1036+ end
1037+
1038+ vim .schedule (function ()
1039+ if # results > 0 then
1040+ local names = Iter (results ):map (function (entry )
1041+ return entry .name
1042+ end ):totable ()
1043+ local res = vim .fn .matchfuzzypos (names , query )
1044+ for _ , entry in ipairs (results ) do
1045+ for k , v in ipairs (res [1 ]) do
1046+ if v == entry .name then
1047+ entry .match_pos = res [2 ][k ]
1048+ entry .score = res [3 ][k ]
1049+ end
1050+ end
1051+ end
1052+ table.sort (results , function (a , b )
1053+ return a .score > b .score
1054+ end )
1055+ state .search_results = results
1056+ end
1057+ update_display (state , results , false )
1058+ end )
1059+ end )
1060+ end
9151061 end ,
9161062 on_detach = function ()
9171063 if state .search_engine then
0 commit comments