@@ -664,7 +664,7 @@ M.open_file = function(state, path, open_cmd, bufnr)
664
664
end
665
665
666
666
if M .truthy (path ) then
667
- local escaped_path = M .escape_path (path )
667
+ local escaped_path = M .escape_path_for_cmd (path )
668
668
local bufnr_or_path = bufnr or escaped_path
669
669
local events = require (" neo-tree.events" )
670
670
local result = true
@@ -1000,10 +1000,29 @@ M.windowize_path = function(path)
1000
1000
return path :gsub (" /" , " \\ " )
1001
1001
end
1002
1002
1003
- M .escape_path = function (path )
1003
+ --- Escapes a path primarily relying on `vim.fn.fnameescape`. This function should
1004
+ --- only be used when preparing a path to be used in a vim command, such as `:e`.
1005
+ ---
1006
+ --- For Windows systems, this function handles punctuation characters that will
1007
+ --- be escaped, but may appear at the beginning of a path segment. For example,
1008
+ --- the path `C:\foo\(bar)\baz.txt` (where foo, (bar), and baz.txt are segments)
1009
+ --- will remain unchanged when escaped by `fnaemescape` on a Windows system.
1010
+ --- However, if that string is used to edit a file with `:e`, `:b`, etc., the open
1011
+ --- parenthesis will be treated as an escaped character and the path separator will
1012
+ --- be lost.
1013
+ ---
1014
+ --- For more details, see issue #889 when this function was introduced, and further
1015
+ --- discussions in #1264 and #1352.
1016
+ --- @param path string
1017
+ --- @return string
1018
+ M .escape_path_for_cmd = function (path )
1004
1019
local escaped_path = vim .fn .fnameescape (path )
1005
1020
if M .is_windows then
1006
- escaped_path = escaped_path :gsub (" \\ " , " /" ):gsub (" / " , " " )
1021
+ -- on windows, any punctuation preceeded by a `\` needs to have a second `\`
1022
+ -- added to preserve the path separator. this is a naive replacement and
1023
+ -- definitely not bullet proof. if we start finding issues with opening files
1024
+ -- or changing directories, look here first.
1025
+ escaped_path = escaped_path :gsub (" \\ %p" , " \\ %1" )
1007
1026
end
1008
1027
return escaped_path
1009
1028
end
@@ -1201,4 +1220,34 @@ M.brace_expand = function(s)
1201
1220
return result
1202
1221
end
1203
1222
1223
+ --- Indexes a table that uses paths as keys. Case-insensitive logic is used when
1224
+ --- running on Windows.
1225
+ ---
1226
+ --- Consideration should be taken before using this function, because it is a
1227
+ --- bit expensive on Windows. However, this function helps when trying to index
1228
+ --- with absolute path keys, which can have inconsistent casing on Windows (such
1229
+ --- as with drive letters).
1230
+ --- @param tbl table
1231
+ --- @param key string
1232
+ --- @return unknown
1233
+ M .index_by_path = function (tbl , key )
1234
+ local value = tbl [key ]
1235
+ if value ~= nil then
1236
+ return value
1237
+ end
1238
+
1239
+ -- on windows, paths that differ only by case are considered equal
1240
+ -- TODO: we should optimize this, see discussion in #1353
1241
+ if M .is_windows then
1242
+ local key_lower = key :lower ()
1243
+ for k , v in pairs (tbl ) do
1244
+ if key_lower == k :lower () then
1245
+ return v
1246
+ end
1247
+ end
1248
+ end
1249
+
1250
+ return value
1251
+ end
1252
+
1204
1253
return M
0 commit comments