Skip to content

[BUG] Encoding the current working path to a valid session filename will always have some form of issue #273

@josh-nz

Description

@josh-nz

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.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions