Skip to content

Commit

Permalink
feat(path): expand ~\ prefix on MS-Windows
Browse files Browse the repository at this point in the history
In fix_fname() for MS-Windows, expand "~\" or "~/" prefixed paths to the
USERPROFILE environment variable for the user's profile directory
instead of a relative path to a literal "~" directory.

Fix #23901

Signed-off-by: Rafael Kitover <[email protected]>
  • Loading branch information
rkitover committed May 20, 2024
1 parent 91892f5 commit ac8a4d6
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
3 changes: 3 additions & 0 deletions runtime/doc/news.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ TUI

• TODO

* On MS-Windows, paths prefixed with "~/" or "~\" are now expanded to the
user's profile directory, not a relative path to a literal "~" directory.

==============================================================================
NEW FEATURES *news-features*

Expand Down
23 changes: 15 additions & 8 deletions src/nvim/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -1884,7 +1884,8 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
/// the root may have relative paths (like dir/../subdir) or symlinks
/// embedded, or even extra separators (//). This function addresses
/// those possibilities, returning a resolved absolute path.
/// For MS-Windows, this also expands names like "longna~1".
/// For MS-Windows, this also expands names like "longna~1" and
/// replaces "~/" or "~\" prefixes with the user profile directory.
///
/// @param fname is the filename to expand
/// @return [allocated] Full path (NULL for failure).
Expand All @@ -1893,18 +1894,24 @@ char *fix_fname(const char *fname)
#ifdef UNIX
return FullName_save(fname, true);
#else
if (!vim_isAbsName(fname)
|| strstr(fname, "..") != NULL
|| strstr(fname, "//") != NULL
if (*fname == '~' && (fname[1] == '/' || fname[1] == '\\')) {
const char *profile_dir = os_getenv("USERPROFILE");
size_t len = strlen(profile_dir) + strlen(fname);
char *new_fname = xmalloc(len);
snprintf(new_fname, len, "%s%s", profile_dir, fname + 1);
fname = new_fname;
} else if (!vim_isAbsName(fname)
|| strstr(fname, "..") != NULL
|| strstr(fname, "//") != NULL
# ifdef BACKSLASH_IN_FILENAME
|| strstr(fname, "\\\\") != NULL
|| strstr(fname, "\\\\") != NULL
# endif
) {
) {
return FullName_save(fname, false);
} else {
fname = xstrdup(fname);
}

fname = xstrdup(fname);

# ifdef USE_FNAME_CASE
path_fix_case((char *)fname); // set correct case for file name
# endif
Expand Down

0 comments on commit ac8a4d6

Please sign in to comment.