optimize: make relative (#1529)

This commit is contained in:
yetone
2025-03-08 21:15:07 +08:00
committed by GitHub
parent 4766e76a31
commit 3741460541
6 changed files with 268 additions and 9 deletions

View File

@@ -18,6 +18,7 @@ local FileSelector = {}
local function has_scheme(path) return path:find("^%w+://") ~= nil end
function FileSelector:process_directory(absolute_path, project_root)
if absolute_path:sub(-1) == Utils.path_sep then absolute_path = absolute_path:sub(1, -2) end
local files = scan.scan_dir(absolute_path, {
hidden = false,
depth = math.huge,
@@ -26,7 +27,7 @@ function FileSelector:process_directory(absolute_path, project_root)
})
for _, file in ipairs(files) do
local rel_path = Path:new(file):make_relative(project_root)
local rel_path = Utils.make_relative_path(file, project_root)
if not vim.tbl_contains(self.selected_filepaths, rel_path) then table.insert(self.selected_filepaths, rel_path) end
end
self:emit("update")
@@ -61,10 +62,10 @@ end
local function get_project_filepaths()
local project_root = Utils.get_project_root()
local files = Utils.scan_directory({ directory = project_root, add_dirs = true })
files = vim.iter(files):map(function(filepath) return Path:new(filepath):make_relative(project_root) end):totable()
files = vim.iter(files):map(function(filepath) return Utils.make_relative_path(filepath, project_root) end):totable()
return vim.tbl_map(function(path)
local rel_path = Path:new(path):make_relative(project_root)
local rel_path = Utils.make_relative_path(path, project_root)
local stat = vim.loop.fs_stat(path)
if stat and stat.type == "directory" then rel_path = rel_path .. "/" end
return rel_path

View File

@@ -34,7 +34,7 @@ local function has_permission_to_access(abs_path)
-- Specifically, it should not check the project root itself
-- Otherwise if the binary is named the same as the project root (such as Go binary), any paths
-- insde the project root will be ignored
local rel_path = Path:new(abs_path):make_relative(project_root)
local rel_path = Utils.make_relative_path(abs_path, project_root)
return not Utils.is_ignored(rel_path, gitignore_patterns, gitignore_negate_patterns)
end

View File

@@ -35,6 +35,14 @@ end
function M.is_win() return jit.os:find("Windows") ~= nil end
M.path_sep = (function()
if M.is_win() then
return "\\"
else
return "/"
end
end)()
---@return "linux" | "darwin" | "windows"
function M.get_os_name()
local os_name = vim.uv.os_uname().sysname
@@ -765,7 +773,7 @@ function M.scan_directory(options)
:filter(function(file)
local base_dir = options.directory
if base_dir:sub(-2) == "/." then base_dir = base_dir:sub(1, -3) end
local rel_path = tostring(Path:new(file):make_relative(base_dir))
local rel_path = M.make_relative_path(file, base_dir)
local pieces = vim.split(rel_path, "/")
return #pieces <= options.max_depth
end)
@@ -776,8 +784,7 @@ function M.scan_directory(options)
local dirs = {}
local dirs_seen = {}
for _, file in ipairs(files) do
local dir = tostring(Path:new(file):parent())
dir = dir .. "/"
local dir = M.get_parent_path(file)
if not dirs_seen[dir] then
table.insert(dirs, dir)
dirs_seen[dir] = true
@@ -789,6 +796,64 @@ function M.scan_directory(options)
return files
end
function M.get_parent_path(filepath)
if filepath == nil then error("filepath cannot be nil") end
if filepath == "" then return "" end
local is_abs = M.is_absolute_path(filepath)
if filepath:sub(-1) == M.path_sep then filepath = filepath:sub(1, -2) end
if filepath == "" then return "" end
local parts = vim.split(filepath, M.path_sep)
local parent_parts = vim.list_slice(parts, 1, #parts - 1)
local res = table.concat(parent_parts, M.path_sep)
if res == "" then
if is_abs then return M.path_sep end
return "."
end
return res
end
function M.make_relative_path(filepath, base_dir)
if filepath:sub(-2) == M.path_sep .. "." then filepath = filepath:sub(1, -3) end
if base_dir:sub(-2) == M.path_sep .. "." then base_dir = base_dir:sub(1, -3) end
if filepath == base_dir then return "." end
if filepath:sub(1, #base_dir) == base_dir then
filepath = filepath:sub(#base_dir + 1)
if filepath:sub(1, 2) == "." .. M.path_sep then
filepath = filepath:sub(3)
elseif filepath:sub(1, 1) == M.path_sep then
filepath = filepath:sub(2)
end
end
return filepath
end
function M.is_absolute_path(path)
if not path then return false end
if M.is_win() then return path:match("^%a:[/\\]") ~= nil end
return path:match("^/") ~= nil
end
function M.join_paths(...)
local paths = { ... }
local result = paths[1] or ""
for i = 2, #paths do
local path = paths[i]
if path == nil or path == "" then goto continue end
if M.is_absolute_path(path) then
result = path
goto continue
end
if path:sub(1, 2) == "." .. M.path_sep then path = path:sub(3) end
if result ~= "" and result:sub(-1) ~= M.path_sep then result = result .. M.path_sep end
result = result .. path
::continue::
end
return result
end
function M.is_first_letter_uppercase(str) return string.match(str, "^[A-Z]") ~= nil end
---@param content string
@@ -954,8 +1019,8 @@ function M.uniform_path(path)
if type(path) ~= "string" then path = tostring(path) end
if not M.file.is_in_cwd(path) then return path end
local project_root = M.get_project_root()
local abs_path = Path:new(path):is_absolute() and path or Path:new(project_root):joinpath(path):absolute()
local relative_path = Path:new(abs_path):make_relative(project_root)
local abs_path = M.is_absolute_path(path) and path or M.join_paths(project_root, path)
local relative_path = M.make_relative_path(abs_path, project_root)
return relative_path
end