mirror of
https://github.com/neovim/neovim.git
synced 2026-07-17 06:31:16 +00:00
fix(path): normalize separators (slashes) #39155
Problem: Continue separators normalization, and try to keep it at the nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx` Solution: some key changes - normalize `$HOME-windows` - normalize entry points of changing directory - `nvim_set_current_dir()`, `chdir()` - normalize the named pipe - `--listen` arg, `--server` arg, `:restart` - `serverstart()`, `sockconnect()`, `serverstop()` - make `expand()` respect 'shellslash' again - clean up `did_set_shellslash` - replace `forward_slash` with `TO_SLASH` - remove obsolete `TMP_PATHSEPSTR` - remove `slash_adjust` in `do_autocmd_dirchanged`? - make `fnamemodify()` always return `/` (except when substituting separators via `:s`, `:gs` ?) Note: - these funcs still apply `slash_adjust` on return, as before: `:pwd`, `chdir()`, `exepath()`, `getcwd()` - these funcs alwarys return `/`, unlike before the normalization PRs - `getcompletion()`, `finddir()`, `findfile()` Also - clean up code, comments, formatting and tests - move `TO_SLASH` from `f_chdir` to `changedir_func` - move `TO_SLASH` from `f_bufadd` to `buflist_new` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
@@ -322,7 +322,7 @@ describe('context functions', function()
|
||||
filter(map(add(
|
||||
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
|
||||
'filter(
|
||||
{ "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
|
||||
{ "f": expand("#".v:val.bufnr.":p:gs?\\?/?"), "l": v:val.lnum },
|
||||
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
|
||||
]]):gsub('\n', ''))),
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ local t = require('test.testutil')
|
||||
local n = require('test.functional.testnvim')()
|
||||
|
||||
local eq, clear, call, write_file, command = t.eq, n.clear, n.call, t.write_file, n.command
|
||||
local eval = n.eval
|
||||
local eval, fn = n.eval, n.fn
|
||||
local is_os = t.is_os
|
||||
local pcall_err = t.pcall_err
|
||||
|
||||
@@ -18,38 +18,26 @@ describe('executable()', function()
|
||||
eq(1, call('executable', 'false'))
|
||||
end)
|
||||
|
||||
if is_os('win') then
|
||||
it('exepath returns consistent slashes #13787', function()
|
||||
-- test/ cannot be a symlink in this test.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
it('exepath respects shellslash #13787', function()
|
||||
t.skip(not is_os('win'), 'N/A for non-Windows')
|
||||
-- test/ cannot be a symlink in this test.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
|
||||
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||
eq(
|
||||
[[test/functional/fixtures/bin/null.CMD]],
|
||||
call('fnamemodify', call('exepath', 'null'), ':.')
|
||||
)
|
||||
command('set shellslash')
|
||||
eq(
|
||||
'test/functional/fixtures/bin/null.CMD',
|
||||
call('fnamemodify', call('exepath', 'null'), ':.')
|
||||
)
|
||||
end)
|
||||
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||
eq(([[%s\test\functional\fixtures\bin\null.CMD]]):format(fn.getcwd()), fn.exepath('null'))
|
||||
command('set shellslash')
|
||||
eq(('%s/test/functional/fixtures/bin/null.CMD'):format(fn.getcwd()), fn.exepath('null'))
|
||||
end)
|
||||
|
||||
it('stdpath returns consistent slashes #13787', function()
|
||||
-- Needs to check paths relative to repo root dir.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
it('stdpath returns consistent slashes #13787', function()
|
||||
t.skip(not is_os('win'), 'N/A for non-Windows')
|
||||
-- Needs to check paths relative to repo root dir.
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
|
||||
t.matches(
|
||||
[[build/Xtest_xdg[%w_]*/share/nvim%-data]],
|
||||
call('fnamemodify', call('stdpath', 'data'), ':.')
|
||||
)
|
||||
command('set shellslash')
|
||||
t.matches(
|
||||
'build/Xtest_xdg[%w_]*/share/nvim%-data',
|
||||
call('fnamemodify', call('stdpath', 'data'), ':.')
|
||||
)
|
||||
end)
|
||||
end
|
||||
t.matches('build/Xtest_xdg[%w_]*/share/nvim%-data', fn.stdpath('data'))
|
||||
command('set shellslash')
|
||||
t.matches('build/Xtest_xdg[%w_]*/share/nvim%-data', fn.stdpath('data'))
|
||||
end)
|
||||
|
||||
it('fails for invalid values', function()
|
||||
for _, input in ipairs({ 'v:null', 'v:true', 'v:false', '{}', '[]' }) do
|
||||
|
||||
@@ -10,10 +10,6 @@ local write_file = t.write_file
|
||||
local is_os = t.is_os
|
||||
local chdir = n.fn.chdir
|
||||
|
||||
local function eq_slashconvert(expected, got)
|
||||
eq(t.fix_slashes(expected), t.fix_slashes(got))
|
||||
end
|
||||
|
||||
describe('fnamemodify()', function()
|
||||
setup(function()
|
||||
write_file('Xtest-fnamemodify.txt', [[foobar]])
|
||||
@@ -42,7 +38,7 @@ describe('fnamemodify()', function()
|
||||
eq(root, fnamemodify([[/]], ':p'))
|
||||
|
||||
local letter_colon = root:sub(1, 2)
|
||||
local old_dir = t.fix_slashes(getcwd()) .. '/'
|
||||
local old_dir = ('%s/'):format(getcwd())
|
||||
local foo_dir = old_dir .. 'foo/'
|
||||
eq(old_dir, fnamemodify(letter_colon, ':p'))
|
||||
eq(old_dir, fnamemodify(letter_colon .. '.', ':p'))
|
||||
@@ -65,28 +61,28 @@ describe('fnamemodify()', function()
|
||||
n.api.nvim_set_current_dir(t.paths.test_source_path)
|
||||
|
||||
local filename = 'src/version.c'
|
||||
local cwd = getcwd()
|
||||
local cwd = vim.fs.normalize(getcwd())
|
||||
|
||||
eq_slashconvert(cwd .. '/src/version.c', fnamemodify(filename, ':p'))
|
||||
eq(('%s/src/version.c'):format(cwd), fnamemodify(filename, ':p'))
|
||||
|
||||
eq_slashconvert('src/version.c', fnamemodify(filename, ':p:.'))
|
||||
eq_slashconvert(cwd .. '/src', fnamemodify(filename, ':p:h'))
|
||||
eq_slashconvert(cwd .. '', fnamemodify(filename, ':p:h:h'))
|
||||
eq('src/version.c', fnamemodify(filename, ':p:.'))
|
||||
eq(('%s/src'):format(cwd), fnamemodify(filename, ':p:h'))
|
||||
eq(cwd, fnamemodify(filename, ':p:h:h'))
|
||||
eq('version.c', fnamemodify(filename, ':p:t'))
|
||||
eq_slashconvert(cwd .. '/src/version', fnamemodify(filename, ':p:r'))
|
||||
eq(('%s/src/version'):format(cwd), fnamemodify(filename, ':p:r'))
|
||||
|
||||
eq_slashconvert(cwd .. '/src/main.c', fnamemodify(filename, ':s?version?main?:p'))
|
||||
eq(('%s/src/main.c'):format(cwd), fnamemodify(filename, ':s?version?main?:p'))
|
||||
|
||||
local converted_cwd = cwd:gsub('/', '\\')
|
||||
eq(converted_cwd .. '\\src\\version.c', fnamemodify(filename, ':p:gs?/?\\\\?'))
|
||||
|
||||
eq('src', fnamemodify(filename, ':h'))
|
||||
eq('version.c', fnamemodify(filename, ':t'))
|
||||
eq_slashconvert('src/version', fnamemodify(filename, ':r'))
|
||||
eq('src/version', fnamemodify(filename, ':r'))
|
||||
eq('version', fnamemodify(filename, ':t:r'))
|
||||
eq('c', fnamemodify(filename, ':e'))
|
||||
|
||||
eq_slashconvert('src/main.c', fnamemodify(filename, ':s?version?main?'))
|
||||
eq('src/main.c', fnamemodify(filename, ':s?version?main?'))
|
||||
end)
|
||||
|
||||
it('handles advanced examples from ":help filename-modifiers"', function()
|
||||
@@ -98,11 +94,11 @@ describe('fnamemodify()', function()
|
||||
|
||||
eq('c', fnamemodify(filename, ':e:e:r'))
|
||||
|
||||
eq_slashconvert('src/version.c', fnamemodify(filename, ':r'))
|
||||
eq('src/version.c', fnamemodify(filename, ':r'))
|
||||
eq('c', fnamemodify(filename, ':r:e'))
|
||||
|
||||
eq_slashconvert('src/version', fnamemodify(filename, ':r:r'))
|
||||
eq_slashconvert('src/version', fnamemodify(filename, ':r:r:r'))
|
||||
eq('src/version', fnamemodify(filename, ':r:r'))
|
||||
eq('src/version', fnamemodify(filename, ':r:r:r'))
|
||||
end)
|
||||
|
||||
it('handles :h', function()
|
||||
@@ -136,11 +132,11 @@ describe('fnamemodify()', function()
|
||||
eq('//server///share', fnamemodify('//server///share', ':h'))
|
||||
eq('//server/share/', fnamemodify('//server/share/foo', ':h'))
|
||||
|
||||
eq([[\\foo\C$]], fnamemodify([[\\foo\C$]], ':h'))
|
||||
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\]], ':h'))
|
||||
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\bar]], ':h'))
|
||||
eq([[\\foo\C$\]], fnamemodify([[\\foo\C$\bar]], ':h:h'))
|
||||
eq([[//foo\C$/]], fnamemodify([[//foo\C$/bar]], ':h'))
|
||||
eq([[//foo/C$]], fnamemodify([[\\foo\C$]], ':h'))
|
||||
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\]], ':h'))
|
||||
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\bar]], ':h'))
|
||||
eq([[//foo/C$/]], fnamemodify([[\\foo\C$\bar]], ':h:h'))
|
||||
eq([[//foo/C$/]], fnamemodify([[//foo\C$/bar]], ':h'))
|
||||
-- `C$` is a share name, not a file name
|
||||
eq('', fnamemodify('//foo/C$/bar', ':h:t'))
|
||||
|
||||
@@ -165,17 +161,17 @@ describe('fnamemodify()', function()
|
||||
|
||||
it('handles :t', function()
|
||||
eq('hello.txt', fnamemodify('hello.txt', ':t'))
|
||||
eq_slashconvert('hello.txt', fnamemodify('path/to/hello.txt', ':t'))
|
||||
eq('hello.txt', fnamemodify('path/to/hello.txt', ':t'))
|
||||
end)
|
||||
|
||||
it('handles :r', function()
|
||||
eq('hello', fnamemodify('hello.txt', ':r'))
|
||||
eq_slashconvert('path/to/hello', fnamemodify('path/to/hello.txt', ':r'))
|
||||
eq('path/to/hello', fnamemodify('path/to/hello.txt', ':r'))
|
||||
end)
|
||||
|
||||
it('handles :e', function()
|
||||
eq('txt', fnamemodify('hello.txt', ':e'))
|
||||
eq_slashconvert('txt', fnamemodify('path/to/hello.txt', ':e'))
|
||||
eq('txt', fnamemodify('path/to/hello.txt', ':e'))
|
||||
end)
|
||||
|
||||
it('handles regex replacements', function()
|
||||
|
||||
Reference in New Issue
Block a user