-
-
Notifications
You must be signed in to change notification settings - Fork 54
Description
Describe the bug
The current method to encode the current working directory into a filename that is valid (in order to name the session file) will always have some form of issue, regardless of platform. A different approach is required.
A number of Windows issues have been reported that all stem from the same encoding issue: #242 #195 #148
However, MacOS and *nix systems can also have issues with the encoding process.
Let's have a look the functions in question, from auto-session/lib.lua
:
local function win32_unescaped_dir(dir)
dir = dir:gsub("++", ":")
if not vim.o.shellslash then
dir = dir:gsub("-", "\\")
end
return dir
end
local function win32_escaped_dir(dir)
dir = dir:gsub(":", "++")
if not vim.o.shellslash then
dir = dir:gsub("\\", "-")
-- need to escape forward slash as well for windows, see issue #202
dir = dir:gsub("/", "-")
end
return dir
end
local IS_WIN32 = vim.fn.has "win32" == Lib._VIM_TRUE
function Lib.unescape_dir(dir)
return IS_WIN32 and win32_unescaped_dir(dir) or dir:gsub("%%", "/")
end
function Lib.escape_dir(dir)
return IS_WIN32 and win32_escaped_dir(dir) or dir:gsub("/", "\\%%")
end
Let's focus first on Windows. You can see it's a simple substitution for a few characters. However, these substituted characters may exist in the path (since they are valid path/filename characters), and that means it's impossible to know which character/s should be unescaped. It is simply not possible to do simple character substitution to create a valid file name and be able to reliably reverse this process. Let's look at some examples:
C:\foo-bar
will be escaped as C++-foo-bar
and unescaped as C:\foo\bar
C:\foo++bar
will be escaped as C++-foo++bar
and unescaped as C:\foo:bar
Here is a MacOS/ *nix example, which uses a different substitution process but can still have issues:
/Users/Foo/bar%baz
will be escaped as %Users%Foo%bar%baz
and unescaped as /Users/Foo/bar/baz
(I could be wrong on this, I don't quite understand dir:gsub("/", "\\%%")
but I think it's just Lua requiring string escaping to represent the % character. I was looking at the resulting filesystem name for this test. Note also, that in my test I somehow got the buffer filename in the session filename, which broke things. We can go over this if needed, but I think the solutions presented below will resolve this anomaly since I think the source of the issue is the same).
How can this be resolved?
The easiest way is to remove the coupling of the cwd
from the session filename. When a new session is saved, some unique filename friendly identifier is assigned to it (I would suggest a guid
), and this is used as the session filename. This mapping is saved in a file somewhere, similar to how the current session and alternate session is saved. The format is unimportant, it just needs to be a key-value system. If Lua can serialize tables directly to a file, that would be the easiest. So, you'd have something that would look like:
local session_mappings = {
"C:\\foo-bar" = "f666dfb1-5064-4aaa-89e1-e17d71e3e254",
"C:\\foo++bar" = "87ba1a7c-e68a-42df-9c91-ecad51d7d5e2"
...
}
or similar data structure, in the event that the above is not valid Lua syntax.
I think the above mapping system would probably (automatically?) solve issues #242 #195 #148
I am unfamiliar enough with Lua and nvim plugin development to try and implement this, but in theory it shouldn't be hard to do if someone knows the code.
I have seen #116 so I'm unsure if this is a change that would be considered for the current code base, or not acted upon until the rewrite occurs. If it is the latter, then I can't see a solution for the linked Windows issues.