diff options
Diffstat (limited to 'lua/conform')
-rw-r--r-- | lua/conform/fs.lua | 68 | ||||
-rw-r--r-- | lua/conform/runner.lua | 13 |
2 files changed, 80 insertions, 1 deletions
diff --git a/lua/conform/fs.lua b/lua/conform/fs.lua index d303dbd..6f92e18 100644 --- a/lua/conform/fs.lua +++ b/lua/conform/fs.lua @@ -15,4 +15,72 @@ M.join = function(...) return table.concat({ ... }, M.sep) end +M.is_absolute = function(path) + if M.is_windows then + return path:lower():match("^%a:") + else + return vim.startswith(path, "/") + end +end + +M.abspath = function(path) + if not M.is_absolute(path) then + path = vim.fn.fnamemodify(path, ":p") + end + return 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 + +---Create a relative path from the source to the target +---@param source string +---@param target string +---@return string +M.relative_path = function(source, target) + source = M.abspath(source) + target = M.abspath(target) + local path = {} + while not M.is_subpath(source, target) do + table.insert(path, "..") + local new_source = vim.fs.dirname(source) + assert(source ~= new_source) + source = new_source + end + + local offset = vim.endswith(source, M.sep) and 1 or 2 + local rel_target = target:sub(source:len() + offset) + table.insert(path, rel_target) + return M.join(unpack(path)) +end + return M diff --git a/lua/conform/runner.lua b/lua/conform/runner.lua index 0f31e64..b3a1e61 100644 --- a/lua/conform/runner.lua +++ b/lua/conform/runner.lua @@ -33,8 +33,17 @@ M.build_cmd = function(formatter_name, ctx, config) end end + local cwd + if config.cwd then + cwd = config.cwd(config, ctx) + end + local relative_filename = fs.relative_path(cwd or vim.fn.getcwd(), ctx.filename) + if type(args) == "string" then - local interpolated = args:gsub("$FILENAME", ctx.filename):gsub("$DIRNAME", ctx.dirname) + local interpolated = args + :gsub("$FILENAME", ctx.filename) + :gsub("$DIRNAME", ctx.dirname) + :gsub("$RELATIVE_FILEPATH", relative_filename) return command .. " " .. interpolated else local cmd = { command } @@ -44,6 +53,8 @@ M.build_cmd = function(formatter_name, ctx, config) v = ctx.filename elseif v == "$DIRNAME" then v = ctx.dirname + elseif v == "$RELATIVE_FILEPATH" then + v = relative_filename end table.insert(cmd, v) end |