@@ -664,7 +664,7 @@ M.open_file = function(state, path, open_cmd, bufnr)
664664 end
665665
666666 if M .truthy (path ) then
667- local escaped_path = M .escape_path (path )
667+ local escaped_path = M .escape_path_for_cmd (path )
668668 local bufnr_or_path = bufnr or escaped_path
669669 local events = require (" neo-tree.events" )
670670 local result = true
@@ -1000,10 +1000,29 @@ M.windowize_path = function(path)
10001000 return path :gsub (" /" , " \\ " )
10011001end
10021002
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 )
10041019 local escaped_path = vim .fn .fnameescape (path )
10051020 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" )
10071026 end
10081027 return escaped_path
10091028end
@@ -1201,4 +1220,34 @@ M.brace_expand = function(s)
12011220 return result
12021221end
12031222
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+
12041253return M
0 commit comments