summaryrefslogtreecommitdiff
path: root/lua/quicker/fs.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/quicker/fs.lua')
-rw-r--r--lua/quicker/fs.lua98
1 files changed, 98 insertions, 0 deletions
diff --git a/lua/quicker/fs.lua b/lua/quicker/fs.lua
new file mode 100644
index 0000000..f0e94dc
--- /dev/null
+++ b/lua/quicker/fs.lua
@@ -0,0 +1,98 @@
+local M = {}
+
+---@type boolean
+M.is_windows = vim.uv.os_uname().version:match("Windows")
+
+M.is_mac = vim.uv.os_uname().sysname == "Darwin"
+
+M.is_linux = not M.is_windows and not M.is_mac
+
+---@type string
+M.sep = M.is_windows and "\\" or "/"
+
+---@param ... string
+M.join = function(...)
+ return table.concat({ ... }, M.sep)
+end
+
+---Check if OS path is absolute
+---@param dir string
+---@return boolean
+M.is_absolute = function(dir)
+ if M.is_windows then
+ return dir:match("^%a:\\")
+ else
+ return vim.startswith(dir, "/")
+ end
+end
+
+M.abspath = function(path)
+ if not M.is_absolute(path) then
+ path = vim.fn.fnamemodify(path, ":p")
+ end
+ return path
+end
+
+local home_dir = assert(vim.uv.os_homedir())
+
+---@param path string
+---@param relative_to? string Shorten relative to this path (default cwd)
+---@return string
+M.shorten_path = function(path, relative_to)
+ if not relative_to then
+ relative_to = vim.fn.getcwd()
+ end
+ local relpath
+ if M.is_subpath(relative_to, path) then
+ local idx = relative_to:len() + 1
+ -- Trim the dividing slash if it's not included in relative_to
+ if not vim.endswith(relative_to, "/") and not vim.endswith(relative_to, "\\") then
+ idx = idx + 1
+ end
+ relpath = path:sub(idx)
+ if relpath == "" then
+ relpath = "."
+ end
+ end
+ if M.is_subpath(home_dir, path) then
+ local homepath = "~" .. path:sub(home_dir:len() + 1)
+ if not relpath or homepath:len() < relpath:len() then
+ return homepath
+ end
+ end
+ return relpath or path
+end
+
+--- Returns true if candidate is a subpath of root, or if they are the same path.
+---@param root string
+---@param candidate string
+---@return boolean
+M.is_subpath = function(root, candidate)
+ if candidate == "" then
+ return false
+ end
+ root = vim.fs.normalize(M.abspath(root))
+ -- Trim trailing "/" from the root
+ if root:find("/", -1) then
+ root = root:sub(1, -2)
+ end
+ candidate = vim.fs.normalize(M.abspath(candidate))
+ if M.is_windows then
+ root = root:lower()
+ candidate = candidate:lower()
+ end
+ if root == candidate then
+ return true
+ end
+ local prefix = candidate:sub(1, root:len())
+ if prefix ~= root then
+ return false
+ end
+
+ local candidate_starts_with_sep = candidate:find("/", root:len() + 1, true) == root:len() + 1
+ local root_ends_with_sep = root:find("/", root:len(), true) == root:len()
+
+ return candidate_starts_with_sep or root_ends_with_sep
+end
+
+return M