mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	feat(main): expand file ~\ or ~/ prefix on Windows
In command_line_scan() for MSWIN, expand "~\" or "~/" prefixed paths to the USERPROFILE environment variable for the user's profile directory. Rename the static os_homedir() to os_uv_homedir() to emphasize that it is a wrapper around a libuv function. Add the function os_get_homedir() to os/env.c to return the cached homedir value as a const. Must be called after homedir is initialized or it fails. The difference between this function and the static os_uv_homedir() is that the latter gets the homedir from libuv and is used to initialize homedir in init_homedir(), while os_get_homedir() just returns homedir as a const if it's initialized and is public. Use the os_get_homedir() accessor for ~/ expansion on Windows to make the code more concise. Add a Windows section to main_spec.lua with tests for expanding ~/ and ~\ prefixes for files passed in on the command-line. Fix #23901 Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
		@@ -1442,6 +1442,17 @@ scripterror:
 | 
			
		||||
      ga_grow(&global_alist.al_ga, 1);
 | 
			
		||||
      char *p = xstrdup(argv[0]);
 | 
			
		||||
 | 
			
		||||
      // On Windows expand "~\" or "~/" prefix in file names to profile directory.
 | 
			
		||||
#ifdef MSWIN
 | 
			
		||||
      if (*p == '~' && (p[1] == '\\' || p[1] == '/')) {
 | 
			
		||||
        size_t size = strlen(os_get_homedir()) + strlen(p);
 | 
			
		||||
        char *tilde_expanded = xmalloc(size);
 | 
			
		||||
        snprintf(tilde_expanded, size, "%s%s", os_get_homedir(), p + 1);
 | 
			
		||||
        xfree(p);
 | 
			
		||||
        p = tilde_expanded;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
 | 
			
		||||
          && !os_isdir(alist_name(&GARGLIST[0]))) {
 | 
			
		||||
        char *r = concat_fnames(p, path_tail(alist_name(&GARGLIST[0])), true);
 | 
			
		||||
 
 | 
			
		||||
@@ -400,17 +400,28 @@ void os_get_hostname(char *hostname, size_t size)
 | 
			
		||||
///   2. if $HOME is not set, try the following
 | 
			
		||||
/// For Windows:
 | 
			
		||||
///   1. assemble homedir using HOMEDRIVE and HOMEPATH
 | 
			
		||||
///   2. try os_homedir()
 | 
			
		||||
///   2. try os_uv_homedir()
 | 
			
		||||
///   3. resolve a direct reference to another system variable
 | 
			
		||||
///   4. guess C drive
 | 
			
		||||
/// For Unix:
 | 
			
		||||
///   1. try os_homedir()
 | 
			
		||||
///   1. try os_uv_homedir()
 | 
			
		||||
///   2. go to that directory
 | 
			
		||||
///     This also works with mounts and links.
 | 
			
		||||
///     Don't do this for Windows, it will change the "current dir" for a drive.
 | 
			
		||||
///   3. fall back to current working directory as a last resort
 | 
			
		||||
static char *homedir = NULL;
 | 
			
		||||
static char *os_homedir(void);
 | 
			
		||||
static char *os_uv_homedir(void);
 | 
			
		||||
 | 
			
		||||
/// Public accessor for the cached "real", resolved user home directory. See
 | 
			
		||||
/// comment on `homedir`.
 | 
			
		||||
const char *os_get_homedir(void)
 | 
			
		||||
{
 | 
			
		||||
  if (!homedir) {
 | 
			
		||||
    emsg("os_get_homedir failed: homedir not initialized");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  return homedir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_homedir(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -440,7 +451,7 @@ void init_homedir(void)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (var == NULL) {
 | 
			
		||||
    var = os_homedir();
 | 
			
		||||
    var = os_uv_homedir();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Weird but true: $HOME may contain an indirect reference to another
 | 
			
		||||
@@ -471,7 +482,7 @@ void init_homedir(void)
 | 
			
		||||
 | 
			
		||||
#ifdef UNIX
 | 
			
		||||
  if (var == NULL) {
 | 
			
		||||
    var = os_homedir();
 | 
			
		||||
    var = os_uv_homedir();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Get the actual path.  This resolves links.
 | 
			
		||||
@@ -492,7 +503,7 @@ void init_homedir(void)
 | 
			
		||||
 | 
			
		||||
static char homedir_buf[MAXPATHL];
 | 
			
		||||
 | 
			
		||||
static char *os_homedir(void)
 | 
			
		||||
static char *os_uv_homedir(void)
 | 
			
		||||
{
 | 
			
		||||
  homedir_buf[0] = NUL;
 | 
			
		||||
  size_t homedir_size = MAXPATHL;
 | 
			
		||||
 
 | 
			
		||||
@@ -193,4 +193,26 @@ describe('command-line option', function()
 | 
			
		||||
    matches('Run "nvim %-V1 %-v"', fn.system({ nvim_prog_abs(), '-v' }))
 | 
			
		||||
    matches('Compilation: .*Run :checkhealth', fn.system({ nvim_prog_abs(), '-V1', '-v' }))
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  if is_os('win') then
 | 
			
		||||
    for _, prefix in ipairs({ '~/', '~\\' }) do
 | 
			
		||||
      it('expands ' .. prefix .. ' on Windows', function()
 | 
			
		||||
        local fname = os.getenv('USERPROFILE') .. '\\nvim_test.txt'
 | 
			
		||||
        finally(function()
 | 
			
		||||
          os.remove(fname)
 | 
			
		||||
        end)
 | 
			
		||||
        write_file(fname, 'some text')
 | 
			
		||||
        eq(
 | 
			
		||||
          'some text',
 | 
			
		||||
          fn.system({
 | 
			
		||||
            nvim_prog_abs(),
 | 
			
		||||
            '-es',
 | 
			
		||||
            '+%print',
 | 
			
		||||
            '+q',
 | 
			
		||||
            prefix .. 'nvim_test.txt',
 | 
			
		||||
          }):gsub('\n', '')
 | 
			
		||||
        )
 | 
			
		||||
      end)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user