Skip to content

Commit d90fc39

Browse files
committed
Verbose changes in 'path.lua' module to be sure that the path will be in windows-style
but due to possible skips of the Path module we can get posix-style path in 'job.lua' module as well. In my case I get stable Windows-style paths in 'harpoon' menu (no mixed slashes). The changes allow me to use git-related functions from Telescope but it also needs to be changed a bit cause it invokes 'vim.loop.spawn()' directly that leads to posix-style paths in the final command which WinAPI rejects. The changes are experimental cause integration with msys2 is fragile.
1 parent 857c5ac commit d90fc39

File tree

3 files changed

+287
-10
lines changed

3 files changed

+287
-10
lines changed

lua/plenary/job.lua

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ local compat = require "plenary.compat"
44

55
local F = require "plenary.functional"
66

7+
--qqq
8+
local U = require "plenary.utils"
9+
--!qqq
10+
711
---@class Job
812
---@field command string Command to run
913
---@field args? string[] List of arguments to pass
@@ -64,8 +68,24 @@ end
6468

6569
local function expand(path)
6670
if vim.in_fast_event() then
71+
--qqq
72+
if U.is_msys2 then
73+
path = U.posix_to_windows(path)
74+
-- Experiments with "{}" escaping.
75+
--path = U.posix_to_windows(vim.fn.expand(vim.fn.escape(path, "{}[]$"), true))
76+
end
6777
return assert(uv.fs_realpath(path), string.format("Path must be valid: %s", path))
78+
--!qqq
79+
--return assert(uv.fs_realpath(path), string.format("Path must be valid: %s", path))
6880
else
81+
--qqq
82+
if U.is_msys2 then
83+
path = U.posix_to_windows(vim.fn.expand(vim.fn.escape(path, "[]$"), true))
84+
--path = U.posix_to_windows(vim.fn.expand(vim.fn.escape(path, "{}[]$"), true))
85+
--path = U.posix_to_windows(vim.fn.expand(path), true)
86+
return path
87+
end
88+
--!qqq
6989
-- TODO: Probably want to check that this is valid here... otherwise that's weird.
7090
return vim.fn.expand(vim.fn.escape(path, "[]$"), true)
7191
end
@@ -112,6 +132,18 @@ function Job:new(o)
112132

113133
obj.command = command
114134
obj.args = args
135+
--qqq
136+
-- This is so annoying that path can be in posix style even here.
137+
--vim.notify("Job:new(): " .. vim.inspect(obj), vim.log.levels.ERROR)
138+
if U.is_msys2 and o.cwd then
139+
-- "git_apply_stash" from Telescope does not work here possibly due to nil "o.cwd".
140+
-- NVM. This was caused by curly braces expansion in stash@{0}.
141+
--if not o.cwd then
142+
-- o.cwd = vim.loop.cwd()
143+
--end
144+
o.cwd = U.posix_to_windows(o.cwd)
145+
end
146+
--!qqq
115147
obj._raw_cwd = o.cwd
116148
if o.env then
117149
if type(o.env) ~= "table" then
@@ -269,6 +301,12 @@ function Job:_create_uv_options()
269301
options.stdio = { self.stdin, self.stdout, self.stderr }
270302

271303
if self._raw_cwd then
304+
--qqq
305+
if U.is_msys2 then
306+
--vim.notify("Job:_create_uv_options(): " .. vim.inspect(self), vim.log.levels.ERROR)
307+
self._raw_cwd = U.posix_to_windows(self._raw_cwd)
308+
end
309+
--!qqq
272310
options.cwd = expand(self._raw_cwd)
273311
end
274312
if self.env then
@@ -400,6 +438,15 @@ function Job:_execute()
400438
self:_user_on_start()
401439
end
402440

441+
--qqq
442+
-- Path can be in posix style even here
443+
-- UPD. Making the path transformation in Job:new() solves "nvim ."->":Telescope git_commits"
444+
--if U.is_msys2 then
445+
-- vim.notify("Job:_execute(): " .. vim.inspect(self) .. ", " .. vim.inspect(options), vim.log.levels.ERROR)
446+
-- self._raw_cwd = U.posix_to_windows(self._raw_cwd)
447+
--end
448+
--!qqq
449+
403450
self.handle, self.pid = uv.spawn(options.command, options, shutdown_factory(self, options))
404451

405452
if not self.handle then

lua/plenary/path.lua

Lines changed: 112 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ local uv = vim.loop
88

99
local F = require "plenary.functional"
1010

11+
--qqq
12+
local U = require "plenary.utils"
13+
--!qqq
14+
1115
local S_IF = {
1216
-- S_IFDIR = 0o040000 # directory
1317
DIR = 0x4000,
@@ -16,14 +20,29 @@ local S_IF = {
1620
}
1721

1822
local path = {}
19-
path.home = vim.loop.os_homedir()
23+
--qqq
24+
-- vim.loop.os_homedir() ignores HOME env var in msys2
25+
if U.is_msys2 then
26+
path.home = U.posix_to_windows(vim.fn.expand("~"))
27+
else
28+
path.home = vim.loop.os_homedir()
29+
end
30+
--!qqq
31+
--path.home = vim.loop.os_homedir()
2032

2133
path.sep = (function()
2234
if jit then
2335
local os = string.lower(jit.os)
24-
if os ~= "windows" then
36+
if os ~= "windows" and not U.is_msys2 then
2537
return "/"
2638
else
39+
--qqq
40+
--vim.notify("os: " .. vim.inspect(os) .. ", U.is_msys: " .. vim.inspect(U.is_msys2), vim.log.levels.ERROR)
41+
-- msys2 works fine with backslashes as well as cmd.exe/powershell.exe
42+
-- but not UNC paths if the paths will ever be supported.
43+
-- Maybe returning "/" as path separator can break something in existing logic.
44+
--return "/"
45+
--!qqq
2746
return "\\"
2847
end
2948
else
@@ -39,7 +58,17 @@ path.root = (function()
3958
else
4059
return function(base)
4160
base = base or vim.loop.cwd()
42-
return base:sub(1, 1) .. ":\\"
61+
--qqq
62+
if U.is_msys2 then
63+
base = U.posix_to_windows(base)
64+
--if not base:find("^[A-Za-z]:" .. path.sep) then
65+
-- vim.notify("path.root IIFE: base has incorrect path style for msys2!", vim.log.levels.ERROR)
66+
--end
67+
end
68+
return base:sub(1, 1) .. ":" .. path.sep
69+
--return base:sub(1, 3)
70+
--!qqq
71+
--return base:sub(1, 1) .. ":\\"
4372
end
4473
end
4574
end)()
@@ -55,8 +84,14 @@ local concat_paths = function(...)
5584
end
5685

5786
local function is_root(pathname)
58-
if path.sep == "\\" then
59-
return string.match(pathname, "^[A-Z]:\\?$")
87+
if path.sep == "\\" or U.is_msys2 then
88+
--qqq
89+
if U.is_msys2 then
90+
pathname = U.posix_to_windows(pathname)
91+
end
92+
return string.match(pathname, "^[A-Za-z]:[\\/]?$")
93+
--!qqq
94+
--return string.match(pathname, "^[A-Z]:\\?$")
6095
end
6196
return pathname == "/"
6297
end
@@ -77,7 +112,12 @@ local is_uri = function(filename)
77112
end
78113

79114
local is_absolute = function(filename, sep)
80-
if sep == "\\" then
115+
if sep == "\\" or U.is_msys2 then
116+
--qqq
117+
if U.is_msys2 then
118+
filename = U.posix_to_windows(filename)
119+
end
120+
--!qqq
81121
return string.match(filename, "^[%a]:[\\/].*$") ~= nil
82122
end
83123
return string.sub(filename, 1, 1) == sep
@@ -103,8 +143,10 @@ local function _normalize_path(filename, cwd)
103143
local split_without_disk_name = function(filename_local)
104144
local parts = _split_by_separator(filename_local)
105145
-- Remove disk name part on Windows
106-
if path.sep == "\\" and is_abs then
146+
if is_abs and (path.sep == "\\" or U.is_msys2) then
107147
table.remove(parts, 1)
148+
table.remove(parts, 1)
149+
--table.remove(parts, 1)
108150
end
109151
return parts
110152
end
@@ -137,6 +179,12 @@ local function _normalize_path(filename, cwd)
137179
out_file = prefix .. table.concat(parts, path.sep)
138180
end
139181

182+
--qqq
183+
if U.is_msys2 then
184+
out_file = U.posix_to_windows(out_file)
185+
end
186+
--!qqq
187+
140188
return out_file
141189
end
142190

@@ -182,12 +230,22 @@ Path.__index = function(t, k)
182230

183231
if k == "_cwd" then
184232
local cwd = uv.fs_realpath "."
233+
--qqq
234+
if U.is_msys2 then
235+
cwd = U.posix_to_windows(cwd)
236+
end
237+
--!qqq
185238
t._cwd = cwd
186239
return cwd
187240
end
188241

189242
if k == "_absolute" then
190243
local absolute = uv.fs_realpath(t.filename)
244+
--qqq
245+
if U.is_msys2 then
246+
absolute = U.posix_to_windows(absolute)
247+
end
248+
--!qqq
191249
t._absolute = absolute
192250
return absolute
193251
end
@@ -234,6 +292,13 @@ function Path:new(...)
234292
-- If we already have a Path, it's fine.
235293
-- Just return it
236294
if Path.is_path(path_input) then
295+
--qqq
296+
-- Maybe we should fix fields with paths here as well
297+
--if U.is_msys2 then
298+
-- vim.notify("Path:new(...): returning already defined Path object " .. vim.inspect(path_input), vim.log.levels.ERROR)
299+
-- path_input.filename = U.posix_to_windows(path_input.filename)
300+
--end
301+
--!qqq
237302
return path_input
238303
end
239304

@@ -259,8 +324,18 @@ function Path:new(...)
259324
end
260325

261326
path_string = table.concat(path_objs, sep)
327+
--qqq
328+
if U.is_msys2 then
329+
path_string = U.posix_to_windows(path_string)
330+
end
331+
--!qqq
262332
else
263333
assert(type(path_input) == "string", vim.inspect(path_input))
334+
--qqq
335+
if U.is_msys2 then
336+
path_input = U.posix_to_windows(path_input)
337+
end
338+
--!qqq
264339
path_string = path_input
265340
end
266341

@@ -319,7 +394,15 @@ function Path:expand()
319394
-- TODO support windows
320395
local expanded
321396
if string.find(self.filename, "~") then
322-
expanded = string.gsub(self.filename, "^~", vim.loop.os_homedir())
397+
--qqq
398+
-- vim.loop.os_homedir() ignores HOME env variable in msys2
399+
if U.is_msys2 then
400+
expanded = string.gsub(self.filename, "^~", vim.fn.expand("~"))
401+
else
402+
expanded = string.gsub(self.filename, "^~", vim.loop.os_homedir())
403+
end
404+
--!qqq
405+
--expanded = string.gsub(self.filename, "^~", vim.loop.os_homedir())
323406
elseif string.find(self.filename, "^%.") then
324407
expanded = vim.loop.fs_realpath(self.filename)
325408
if expanded == nil then
@@ -336,9 +419,22 @@ function Path:expand()
336419
else
337420
expanded = self.filename
338421
end
422+
--qqq
423+
if expanded and U.is_msys2 then
424+
--vim.notify("Path:expand(): " .. "vim.inspect(expanded), vim.log.levels.ERROR")
425+
expanded = U.posix_to_windows(expanded)
426+
end
427+
--!qqq
339428
return expanded and expanded or error "Path not valid"
340429
end
341430

431+
--qqq
432+
-- Can be tough to achieve in msys2 for posix-style paths.
433+
-- Like from C:\\msys64\\home\\User\\personal\\project\\src\\file.lua (rel. src\\file.lua)
434+
-- to /home/User/personal/project/src/file.lua (rel. src/file.lua).
435+
-- This will probably require back-and-forth path conversions.
436+
-- But do we actually need to bother about that instead of leaving Windows-style rel. path?
437+
--!qqq
342438
function Path:make_relative(cwd)
343439
if is_uri(self.filename) then
344440
return self.filename
@@ -358,6 +454,12 @@ function Path:make_relative(cwd)
358454
end
359455
end
360456

457+
--qqq
458+
if U.is_msys2 then
459+
self.filename = U.posix_to_windows(self.filename)
460+
end
461+
--!qqq
462+
361463
return self.filename
362464
end
363465

@@ -435,7 +537,7 @@ local shorten = (function()
435537
return shorten_len(filename, 1)
436538
end
437539

438-
if jit and path.sep ~= "\\" then
540+
if jit and path.sep ~= "\\" then --and not U.is_msys2 then
439541
local ffi = require "ffi"
440542
ffi.cdef [[
441543
typedef unsigned char char_u;
@@ -489,7 +591,7 @@ function Path:mkdir(opts)
489591
for _, dir in ipairs(dirs) do
490592
if dir ~= "" then
491593
local joined = concat_paths(processed, dir)
492-
if processed == "" and self._sep == "\\" then
594+
if processed == "" and (self._sep == "\\") then -- or U.is_msys2) then
493595
joined = dir
494596
end
495597
local stat = uv.fs_stat(joined) or {}

0 commit comments

Comments
 (0)