Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(utils): path_expand always use backslash for windows #3018

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions doc/telescope.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2545,9 +2545,8 @@ utils.path_expand({path}) *telescope.utils.path_expand()*
non-existent paths when dealing with valid absolute paths.

Other paths will have '~' and environment variables expanded. Unlike
`vim.fs.normalize()`, backslashes are preserved. This has better
compatibility with `plenary.path` and also avoids mangling valid Unix paths
with literal backslashes.
`vim.fs.normalize()`, Windows paths are converted to use backslashes for
compatibility with `plenary.path`.

Trailing slashes are trimmed. With the exception of root paths. eg. `/` on
Unix or `C:\` on Windows
Expand Down
22 changes: 13 additions & 9 deletions lua/telescope/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ utils.iswin = vim.loop.os_uname().sysname == "Windows_NT"
--- non-existent paths when dealing with valid absolute paths.
---
--- Other paths will have '~' and environment variables expanded.
--- Unlike `vim.fs.normalize()`, backslashes are preserved. This has better
--- compatibility with `plenary.path` and also avoids mangling valid Unix paths
--- with literal backslashes.
--- Unlike `vim.fs.normalize()`, Windows paths are converted to use backslashes
--- for compatibility with `plenary.path`.
---
--- Trailing slashes are trimmed. With the exception of root paths.
--- eg. `/` on Unix or `C:\` on Windows
Expand All @@ -39,26 +38,31 @@ utils.path_expand = function(path)
path = { path, { "string" } },
}

if path:match "^[%%#<]" then
path = vim.fn.expand(path)
end

local os_sep = utils.get_separator()
if utils.iswin then
path = path:gsub("/", os_sep)
end

if utils.is_uri(path) then
return path
end

if path:match "^[%%#<]" then
path = vim.fn.expand(path)
end
path = path:gsub(os_sep .. "+", os_sep)

if path:sub(1, 1) == "~" then
local home = vim.loop.os_homedir() or "~"
if home:sub(-1) == "\\" or home:sub(-1) == "/" then
if home:sub(-1) == os_sep then
home = home:sub(1, -2)
end
path = home .. path:sub(2)
end

path = path:gsub("%$([%w_]+)", vim.loop.os_getenv)
path = path:gsub("/+", "/")
if utils.iswin then
path = path:gsub("\\+", "\\")
if path:match "^%w:\\$" then
return path
else
Expand Down
45 changes: 32 additions & 13 deletions lua/tests/automated/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,35 @@ local utils = require "telescope.utils"

local eq = assert.are.equal

local os_sep = utils.get_separator()

local function new_relpath(unix_path)
return Path:new(unpack(vim.split(unix_path, "/"))).filename
end

local function new_abspath(unix_path)
unix_path = unix_path:gsub("^[/]+", "")
return new_relpath(vim.loop.os_homedir() .. os_sep .. unix_path)
end

describe("path_expand()", function()
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
local path = new_abspath "a/b"
eq(path, utils.path_expand(path .. os_sep))
end)

it("works with root dir", function()
if utils.iswin then
eq([[C:\]], utils.path_expand [[C:\]])
eq([[C:\]], utils.path_expand [[C:/]])
else
eq("/", utils.path_expand "/")
end
end)

it("works with ~", function()
eq(vim.loop.os_homedir() .. "/src/foo", utils.path_expand "~/src/foo")
local path = new_abspath "src/foo"
eq(path, utils.path_expand "~/src/foo")
end)

it("handles duplicate os_sep", function()
Expand All @@ -33,11 +43,16 @@ describe("path_expand()", function()
end)

it("preserves fake whitespace characters and whitespace", function()
local path_space = "/home/user/hello world"
local path_space = new_relpath "foo/hello world"
eq(path_space, utils.path_expand(path_space))
local path_newline = [[/home/user/hello\nworld]]
eq(path_newline, utils.path_expand(path_newline))

-- backslash is always path sep in windows
if not utils.iswin then
local path_newline = [[/home/user/hello\nworld]]
eq(path_newline, utils.path_expand(path_newline))
end
end)

describe("early return for uri", function()
local uris = {
[[https://www.example.com/index.html]],
Expand All @@ -58,6 +73,14 @@ describe("path_expand()", function()
end)
end
end)

it("handles % expand", function()
eq(vim.fn.expand "%", utils.path_expand "%")
end)

it("handles < expand", function()
eq(vim.fn.expand "<cfile>", utils.path_expand "<cfile>")
end)
end)

describe("is_uri", function()
Expand Down Expand Up @@ -191,10 +214,6 @@ describe("transform_path", function()
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
Expand Down