Skip to content

Commit

Permalink
Calculate each section when generating string
Browse files Browse the repository at this point in the history
Also:
- Group directories first
- update gen_date so it will show %b %d $Y if last modified is not from
  this year
- Bug fix for symbolic links
- Show resolved symbolic link, like this:
  a -> b
  • Loading branch information
Conni2461 committed Feb 7, 2021
1 parent a022a1b commit 2aa188f
Showing 1 changed file with 94 additions and 28 deletions.
122 changes: 94 additions & 28 deletions lua/plenary/scandir.lua
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ local conv_to_octal = function(nr)
return octal;
end

local type_tbl = { [1] = 'p', [2] = 'c', [4] = 'd', [6] = 'b', [10] = '-', [12] = 'l', [14] = 's' }
local type_tbl = { [1] = 'p', [2] = 'c', [4] = 'd', [6] = 'b', [10] = '.', [12] = 'l', [14] = 's' }
local permissions_tbl = { [0] = '---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx' }
local bit_tbl = { 4, 2, 1 }

Expand All @@ -201,7 +201,7 @@ local gen_permissions = function(stat)
for i = 2, #l4 do
result = result .. permissions_tbl[tonumber(l4:sub(i, i))]
if bit - bit_tbl[i - 1] >= 0 then
result = result:sub(1, -2) .. (bit_tbl[i - 1] == 1 and 't' or 's')
result = result:sub(1, -2) .. (bit_tbl[i - 1] == 1 and 'T' or 'S')
bit = bit - bit_tbl[i - 1]
end
end
Expand All @@ -223,7 +223,12 @@ local gen_size = function(stat)
return string.format("%.1f%s", size, 'Y')
end

local current_year = os.date('%Y')

local gen_date = function(stat)
if current_year ~= os.date('%Y', stat.mtime.sec) then
return os.date('%b %d %Y', stat.mtime.sec)
end
return os.date('%b %d %H:%M', stat.mtime.sec)
end

Expand Down Expand Up @@ -291,10 +296,21 @@ local get_groupname = (function()
end
end)()

local gen_ls = function(data, path)
if not data or table.getn(data) == 0 then return {} end
local gen_ls = function(data, path, opts)
if not data or table.getn(data) == 0 then return {}, {} end

local check_link = function(per, file)
if per:sub(1, 1) == 'l' then
local resolved = uv.fs_realpath(path .. os_sep .. file)
if not resolved then return file end
if resolved:sub(1, #path) == path then resolved = resolved:sub(#path + 2, -1) end
return string.format('%s -> %s', file, resolved)
end
return file
end

local results = {}
local sections = {}

local users_tbl = os_sep ~= '\\' and {} or nil
local groups_tbl = os_sep ~= '\\' and {} or nil
Expand All @@ -303,58 +319,108 @@ local gen_ls = function(data, path)
if not users_tbl and not groups_tbl then
insert_in_results = function(...)
local args = {...}
table.insert(results, string.format('%10s %5s %s %s', args[1], args[2], args[5], args[6]))
local section = {
{ start_index = 01, end_index = 11 }, -- permissions, hardcoded indexes
{ start_index = 12, end_index = 17 }, -- size, hardcoded indexes
}
local cur_index = 19
for k, v in pairs({ [5] = 2, [6] = 0 }) do
local end_index = cur_index + #tostring(args[k])
table.insert(section, { start_index = cur_index, end_index = end_index })
cur_index = end_index + v
end
table.insert(sections, section)
table.insert(results, string.format('%10s %5s %s %s', args[1], args[2], args[5], check_link(args[1], args[6])))
end
else
insert_in_results = function(...)
table.insert(results, string.format('%10s %5s %s %s %s %s', ...))
local args = {...}
local section = {
{ start_index = 01, end_index = 11 }, -- permissions, hardcoded indexes
{ start_index = 12, end_index = 17 }, -- size, hardcoded indexes
}
local cur_index = 18
for k, v in pairs({ [3] = 1, [4] = 2, [5] = 2, [6] = 0 }) do
local end_index = cur_index + #tostring(args[k])
table.insert(section, { start_index = cur_index, end_index = end_index })
cur_index = end_index + v
end
table.insert(sections, section)
table.insert(results,
string.format(
'%10s %5s %s %s %s %s',
args[1], args[2], args[3], args[4], args[5], check_link(args[1], args[6])
)
)
end
end

for _, v in ipairs(data) do
local stat = Path:new(v):_stat()

insert_in_results(
gen_permissions(stat),
gen_size(stat),
get_username(users_tbl, stat.uid),
get_groupname(groups_tbl, stat.gid),
gen_date(stat),
v:sub(#path + 2, -1)
)
local stat = uv.fs_lstat(v)

if stat then
insert_in_results(
gen_permissions(stat),
gen_size(stat),
get_username(users_tbl, stat.uid),
get_groupname(groups_tbl, stat.gid),
gen_date(stat),
v:sub(#path + 2, -1)
)
end
end
if opts and opts.group_directories_first then
local sorted_results = {}
local sorted_sections = {}
for k, v in ipairs(results) do
if v:sub(1, 1) == 'd' then
table.insert(sorted_results, v)
table.insert(sorted_sections, sections[k])
end
end
for k, v in ipairs(results) do
if v:sub(1, 1) ~= 'd' then
table.insert(sorted_results, v)
table.insert(sorted_sections, sections[k])
end
end
return sorted_results, sorted_sections
else
return results, sections
end
return results
end

--- m.ls
-- List directory contents. Will always apply --long option. Use scan_dir for without --long
-- @param path: string
-- string has to be a valid path
-- @param opts: table to change behavior
-- opts.hidden (bool): if true hidden files will be added
-- opts.add_dirs (bool): if true dirs will also be added to the results, default: true
-- opts.respect_gitignore (bool): if true will only add files that are not ignored by git
-- opts.depth (int): depth on how deep the search should go, default: 1
-- opts.hidden (bool): if true hidden files will be added
-- opts.add_dirs (bool): if true dirs will also be added to the results, default: true
-- opts.respect_gitignore (bool): if true will only add files that are not ignored by git
-- opts.depth (int): depth on how deep the search should go, default: 1
-- opts.group_directories_first (bool): same as real ls
-- @return array with formatted output
m.ls = function(path, opts)
opts = opts or {}
opts.depth = opts.depth or 1
opts.add_dirs = opts.add_dirs or true
local data = m.scan_dir(path, opts)

return gen_ls(data, path)
return gen_ls(data, path, opts)
end

--- m.ls_async
-- List directory contents. Will always apply --long option. Use scan_dir for without --long
-- @param path: string
-- string has to be a valid path
-- @param opts: table to change behavior
-- opts.hidden (bool): if true hidden files will be added
-- opts.add_dirs (bool): if true dirs will also be added to the results, default: true
-- opts.respect_gitignore (bool): if true will only add files that are not ignored by git
-- opts.depth (int): depth on how deep the search should go, default: 1
-- opts.on_exit function(results): will be called at the end (required)
-- opts.hidden (bool): if true hidden files will be added
-- opts.add_dirs (bool): if true dirs will also be added to the results, default: true
-- opts.respect_gitignore (bool): if true will only add files that are not ignored by git
-- opts.depth (int): depth on how deep the search should go, default: 1
-- opts.group_directories_first (bool): same as real ls
-- opts.on_exit function(results): will be called at the end (required)
m.ls_async = function(path, opts)
opts = opts or {}
opts.depth = opts.depth or 1
Expand All @@ -363,7 +429,7 @@ m.ls_async = function(path, opts)
local opts_copy = vim.deepcopy(opts)

opts_copy.on_exit = function(data)
if opts.on_exit then opts.on_exit(gen_ls(data, path)) end
if opts.on_exit then opts.on_exit(gen_ls(data, path, opts_copy)) end
end

m.scan_dir_async(path, opts_copy)
Expand Down

0 comments on commit 2aa188f

Please sign in to comment.