@@ -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