diff options
| author | William Boman <william@redwill.se> | 2023-10-13 15:40:24 +0200 |
|---|---|---|
| committer | William Boman <william@redwill.se> | 2025-02-19 09:23:19 +0100 |
| commit | 3bc4b74f12303319e088c963a7c13486c4e4e776 (patch) | |
| tree | 8ed4f5deef05605337a371795cb9f2fd994a53eb | |
| parent | refactor(path): use InstallLocation to produce paths, remove static path methods (diff) | |
| download | mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar.gz mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar.bz2 mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar.lz mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar.xz mason-3bc4b74f12303319e088c963a7c13486c4e4e776.tar.zst mason-3bc4b74f12303319e088c963a7c13486c4e4e776.zip | |
feat(path): add relative(from, to)
| -rw-r--r-- | lua/mason-core/path.lua | 33 | ||||
| -rw-r--r-- | tests/mason-core/path_spec.lua | 51 |
2 files changed, 83 insertions, 1 deletions
diff --git a/lua/mason-core/path.lua b/lua/mason-core/path.lua index 9eeed3ba..66f0f964 100644 --- a/lua/mason-core/path.lua +++ b/lua/mason-core/path.lua @@ -24,7 +24,38 @@ end ---@path root_path string ---@path path string function M.is_subdirectory(root_path, path) - return root_path == path or path:sub(1, #root_path + 1) == root_path .. sep + local root_path_normalized = vim.fs.normalize(root_path) + local path_normalized = vim.fs.normalize(path) + if path_normalized == root_path_normalized then + return true + end + for dir in vim.fs.parents(path_normalized) do + if root_path_normalized == dir then + return true + end + end + return false +end + +local function find_closest_common_parent(from, to) + local distance = 0 + for parent in vim.fs.parents(from) do + if to:find(parent, 1, true) then + return parent, distance + else + distance = distance + 1 + end + end + return "/", distance +end + +function M.relative(from, to) + local from_normalized = vim.fs.normalize(from) + local to_normalized = vim.fs.normalize(to) + + local common_parent, distance = find_closest_common_parent(from_normalized, to_normalized) + local relative_path_component = distance == 0 and "." or (".."):rep(distance, "/") + return vim.fs.joinpath(relative_path_component, to_normalized:sub(#common_parent + 1)) end return M diff --git a/tests/mason-core/path_spec.lua b/tests/mason-core/path_spec.lua index 3d0c2e25..4aeb48f1 100644 --- a/tests/mason-core/path_spec.lua +++ b/tests/mason-core/path_spec.lua @@ -22,4 +22,55 @@ describe("path", function() assert.is_false(path.is_subdirectory("/foo/bar", "/foo/bas/baz")) assert.is_false(path.is_subdirectory("/foo/bar", "/foo/bars/baz")) end) + + describe("relative ::", function() + local matrix = { + { + from = "/home/user/dir1/fileA", + to = "/home/user/dir1/fileB", + expected = "./fileB", + }, + { + from = "/home/user/dir1/fileA", + to = "/home/user/dir2/fileC", + expected = "../dir2/fileC", + }, + { + from = "/home/user/dir1/subdir/fileD", + to = "/home/user/dir1/fileE", + expected = "../fileE", + }, + { + from = "/home/user/dir1/subdir/fileD", + to = "/home/user/dir1/subdir/fileF", + expected = "./fileF", + }, + { + from = "/home/user/dir1/fileG", + to = "/home/user/dir2/subdir/fileH", + expected = "../dir2/subdir/fileH", + }, + { + from = "/home/user/dir1/subdir1/subdir2/fileI", + to = "/home/user/dir1/fileJ", + expected = "../../fileJ", + }, + { + from = "/fileK", + to = "/home/fileL", + expected = "./home/fileL", + }, + { + from = "/home/user/fileM", + to = "/home/user/dir1/dir2/fileL", + expected = "./dir1/dir2/fileL", + }, + } + + for _, test_case in ipairs(matrix) do + it(("should resolve from %s to %s: %s"):format(test_case.from, test_case.to, test_case.expected), function() + assert.equals(test_case.expected, path.relative(test_case.from, test_case.to)) + end) + end + end) end) |
