@@ -59,6 +59,17 @@ function M.path_basename(path)
59
59
return path :sub (i + 1 , # path )
60
60
end
61
61
62
+ --- Check if there are parentheses before brackets, it causes problems for windows.
63
+ --- Refer to issue #2862 and #2961 for more details.
64
+ local function has_parentheses_and_brackets (path )
65
+ local _ , i_parentheses = path :find (" (" , 1 , true )
66
+ local _ , i_brackets = path :find (" [" , 1 , true )
67
+ if i_parentheses and i_brackets then
68
+ return true
69
+ end
70
+ return false
71
+ end
72
+
62
73
--- Get a path relative to another path.
63
74
--- @param path string
64
75
--- @param relative_to string | nil
@@ -68,13 +79,18 @@ function M.path_relative(path, relative_to)
68
79
return path
69
80
end
70
81
71
- local _ , r = path :find (M .path_add_trailing (relative_to ), 1 , true )
72
- local p = path
82
+ local norm_path = path
83
+ if has_parentheses_and_brackets (path ) then
84
+ norm_path = path :gsub (" /" , " \\ " )
85
+ end
86
+
87
+ local _ , r = norm_path :find (M .path_add_trailing (relative_to ), 1 , true )
88
+ local p = norm_path
73
89
if r then
74
90
-- take the relative path starting after '/'
75
91
-- if somehow given a completely matching path,
76
92
-- returns ""
77
- p = path :sub (r + 1 )
93
+ p = norm_path :sub (r + 1 )
78
94
end
79
95
return p
80
96
end
@@ -272,14 +288,23 @@ function M.canonical_path(path)
272
288
return path
273
289
end
274
290
291
+ --- Escapes special characters in string for windows, refer to issue #2862 and #2961 for more details.
292
+ local function escape_special_char_for_windows (path )
293
+ if has_parentheses_and_brackets (path ) then
294
+ return path :gsub (" \\ " , " /" ):gsub (" / " , " \\ " )
295
+ end
296
+ return path :gsub (" %(" , " \\ (" ):gsub (" %)" , " \\ )" )
297
+ end
298
+
275
299
--- Escapes special characters in string if windows else returns unmodified string.
276
300
--- @param path string
277
301
--- @return string | nil
278
302
function M .escape_special_chars (path )
279
303
if path == nil then
280
304
return path
281
305
end
282
- return M .is_windows and path :gsub (" %(" , " \\ (" ):gsub (" %)" , " \\ )" ) or path
306
+ -- return M.is_windows and path:gsub("%(", "\\("):gsub("%)", "\\)") or path
307
+ return M .is_windows and escape_special_char_for_windows (path ) or path
283
308
end
284
309
285
310
--- Create empty sub-tables if not present
0 commit comments