diff --git a/lua/telescope/utils.lua b/lua/telescope/utils.lua index 5754c7a..ca4a887 100644 --- a/lua/telescope/utils.lua +++ b/lua/telescope/utils.lua @@ -15,7 +15,7 @@ local get_status = require("telescope.state").get_status local utils = {} -local iswin = vim.loop.os_uname().sysname == "Windows_NT" +utils.iswin = vim.loop.os_uname().sysname == "Windows_NT" --- Hybrid of `vim.fn.expand()` and custom `vim.fs.normalize()` --- @@ -53,7 +53,7 @@ utils.path_expand = function(path) path = path:gsub("%$([%w_]+)", vim.loop.os_getenv) path = path:gsub("/+", "/") - if iswin then + if utils.iswin then path = path:gsub("\\+", "\\") if path:match "^%w:\\$" then return path @@ -161,14 +161,15 @@ end utils.path_smart = (function() local paths = {} + local os_sep = utils.get_separator() return function(filepath) local final = filepath if #paths ~= 0 then - local dirs = vim.split(filepath, "/") + local dirs = vim.split(filepath, os_sep) local max = 1 for _, p in pairs(paths) do if #p > 0 and p ~= filepath then - local _dirs = vim.split(p, "/") + local _dirs = vim.split(p, os_sep) for i = 1, math.min(#dirs, #_dirs) do if (dirs[i] ~= _dirs[i]) and i > max then max = i @@ -184,7 +185,7 @@ utils.path_smart = (function() final = "" for k, v in pairs(dirs) do if k >= max - 1 then - final = final .. (#final > 0 and "/" or "") .. v + final = final .. (#final > 0 and os_sep or "") .. v end end end @@ -194,7 +195,7 @@ utils.path_smart = (function() table.insert(paths, filepath) end if final and final ~= filepath then - return "../" .. final + return ".." .. os_sep .. final else return filepath end @@ -264,11 +265,11 @@ end --- this function outside of telescope might yield to undefined behavior and will --- not be addressed by us ---@param opts table: The opts the users passed into the picker. Might contains a path_display key ----@param path string: The path that should be formatted +---@param path string?: The path that should be formatted ---@return string: The transformed path ready to be displayed utils.transform_path = function(opts, path) if path == nil then - return + return "" end if utils.is_uri(path) then return path @@ -288,7 +289,7 @@ utils.transform_path = function(opts, path) elseif vim.tbl_contains(path_display, "smart") or path_display.smart then transformed_path = utils.path_smart(transformed_path) else - if not vim.tbl_contains(path_display, "absolute") or path_display.absolute == false then + if not vim.tbl_contains(path_display, "absolute") and not path_display.absolute then local cwd if opts.cwd then cwd = opts.cwd @@ -306,7 +307,8 @@ utils.transform_path = function(opts, path) local shorten = path_display["shorten"] transformed_path = Path:new(transformed_path):shorten(shorten.len, shorten.exclude) else - transformed_path = Path:new(transformed_path):shorten(path_display["shorten"]) + local length = type(path_display["shorten"]) == "number" and path_display["shorten"] + transformed_path = Path:new(transformed_path):shorten(length) end end if vim.tbl_contains(path_display, "truncate") or path_display.truncate then diff --git a/lua/tests/automated/utils_spec.lua b/lua/tests/automated/utils_spec.lua index 71f772c..48f7689 100644 --- a/lua/tests/automated/utils_spec.lua +++ b/lua/tests/automated/utils_spec.lua @@ -1,27 +1,42 @@ +local Path = require "plenary.path" local utils = require "telescope.utils" +local eq = assert.are.equal + describe("path_expand()", function() - it("removes trailing /", function() - assert.is.equal("/home/user", utils.path_expand "/home/user/") + it("removes trailing os_sep", function() + if utils.iswin then + eq([[C:\Users\a\b]], utils.path_expand [[C:\Users\a\b\]]) + else + eq("/home/user", utils.path_expand "/home/user/") + end end) - it("works with /", function() - assert.is.equal("/", utils.path_expand "/") + it("works with root dir", function() + if utils.iswin then + eq([[C:\]], utils.path_expand [[C:\]]) + else + eq("/", utils.path_expand "/") + end end) it("works with ~", function() - assert.is.equal(vim.loop.os_homedir() .. "/src/foo", utils.path_expand "~/src/foo") + eq(vim.loop.os_homedir() .. "/src/foo", utils.path_expand "~/src/foo") end) - it("handles duplicate /", function() - assert.is.equal("/home/user", utils.path_expand "/home///user") + it("handles duplicate os_sep", function() + if utils.iswin then + eq([[C:\Users\a]], utils.path_expand [[C:\\\Users\\a]]) + else + eq("/home/user", utils.path_expand "/home///user") + end end) it("preserves fake whitespace characters and whitespace", function() local path_space = "/home/user/hello world" - assert.is.equal(path_space, utils.path_expand(path_space)) + eq(path_space, utils.path_expand(path_space)) local path_newline = [[/home/user/hello\nworld]] - assert.is.equal(path_newline, utils.path_expand(path_newline)) + eq(path_newline, utils.path_expand(path_newline)) end) end) @@ -140,9 +155,106 @@ describe("__separates_file_path_location", function() it("separtates file path for " .. suite.input, function() local file, row, col = utils.__separate_file_path_location(suite.input) - assert.are.equal(file, suite.file) - assert.are.equal(row, suite.row) - assert.are.equal(col, suite.col) + eq(file, suite.file) + eq(row, suite.row) + eq(col, suite.col) end) end end) + +describe("transform_path", function() + local cwd = (function() + if utils.iswin then + return [[C:\Users\user\projects\telescope.nvim]] + else + return "/home/user/projects/telescope.nvim" + end + end)() + + local function new_relpath(unix_path) + return Path:new(unpack(vim.split(unix_path, "/"))).filename + end + + local function assert_path(path_display, path, expect) + local opts = { cwd = cwd, __length = 15 } + if type(path_display) == "string" then + opts.path_display = { path_display } + eq(expect, utils.transform_path(opts, path)) + opts.path_display = { [path_display] = true } + eq(expect, utils.transform_path(opts, path)) + elseif type(path_display) == "table" then + opts.path_display = path_display + eq(expect, utils.transform_path(opts, path)) + elseif path_display == nil then + eq(expect, utils.transform_path(opts, path)) + end + end + + it("handles nil path", function() + assert_path(nil, nil, "") + end) + + it("returns back uri", function() + local uri = [[https://www.example.com/index.html]] + assert_path(nil, uri, uri) + end) + + it("handles 'hidden' path_display", function() + eq("", utils.transform_path({ cwd = cwd, path_display = "hidden" }, "foobar")) + assert_path("hidden", "foobar", "") + end) + + it("returns relative path for default opts", function() + local relative = Path:new { "lua", "telescope", "init.lua" } + local absolute = Path:new { cwd, relative } + assert_path(nil, absolute.filename, relative.filename) + assert_path(nil, relative.filename, relative.filename) + end) + + it("handles 'tail' path_display", function() + local path = new_relpath "lua/telescope/init.lua" + assert_path("tail", path, "init.lua") + end) + + it("handles 'smart' path_display", function() + local path1 = new_relpath "lua/telescope/init.lua" + local path2 = new_relpath "lua/telescope/finders.lua" + local path3 = new_relpath "lua/telescope/finders/async_job_finder.lua" + local path4 = new_relpath "plugin/telescope.lua" + + assert_path("smart", path1, path1) + assert_path("smart", path2, new_relpath "../telescope/finders.lua") + assert_path("smart", path3, new_relpath "../telescope/finders/async_job_finder.lua") + assert_path("smart", path4, path4) + end) + + it("handles 'absolute' path_display", function() + local relative = Path:new { "lua", "telescope", "init.lua" } + local absolute = Path:new { cwd, relative } + + -- TODO: feels like 'absolute' should turn relative paths to absolute + -- assert_path("absolute", relative.filename, absolute.filename) + assert_path("absolute", absolute.filename, absolute.filename) + end) + + it("handles default 'shorten' path_display", function() + assert_path("shorten", new_relpath "lua/telescope/init.lua", new_relpath "l/t/init.lua") + end) + + it("handles 'shorten' with number", function() + assert_path({ shorten = 2 }, new_relpath "lua/telescope/init.lua", new_relpath "lu/te/init.lua") + end) + + it("handles 'shorten' with option table", function() + assert_path({ shorten = { len = 2 } }, new_relpath "lua/telescope/init.lua", new_relpath "lu/te/init.lua") + assert_path( + { shorten = { len = 2, exclude = { 1, 3, -1 } } }, + new_relpath "lua/telescope/builtin/init.lua", + new_relpath "lua/te/builtin/init.lua" + ) + end) + + it("handles default 'truncate' path_display", function() + assert_path({ "truncate" }, new_relpath "lua/telescope/init.lua", new_relpath "…scope/init.lua") + end) +end)