mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Merge 9b096873af
into 4ffc20c951
This commit is contained in:
commit
697e979562
@ -9,6 +9,12 @@ local schar = string.char
|
||||
local tohex = require('bit').tohex
|
||||
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*'
|
||||
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
|
||||
-- https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/naming-conventions-for-computer-domain-site-ou
|
||||
-- added also "." to the regex to handle \\wsl.localhost
|
||||
local WINDOWS_UNC_PATTERN = '^\\\\([a-zA-Z.-]+)(\\.*)'
|
||||
local WINDOWS_VOLUME_PATTERN = '^([a-zA-Z]:)(.*)'
|
||||
local IS_WINDOWS = vim.uv.os_uname().version:match('Windows')
|
||||
|
||||
local PATTERNS = {
|
||||
---RFC 2396
|
||||
---https://tools.ietf.org/html/rfc2396#section-2.2
|
||||
@ -36,7 +42,7 @@ end
|
||||
|
||||
---@param uri string
|
||||
---@return boolean
|
||||
local function is_windows_file_uri(uri)
|
||||
local function is_windows_volume_uri(uri)
|
||||
return uri:match('^file:/+[a-zA-Z]:') ~= nil
|
||||
end
|
||||
|
||||
@ -60,15 +66,18 @@ end
|
||||
---@param path string Path to file
|
||||
---@return string URI
|
||||
function M.uri_from_fname(path)
|
||||
local volume_path, fname = path:match('^([a-zA-Z]:)(.*)') ---@type string?
|
||||
local is_windows = volume_path ~= nil
|
||||
local volume_path, vfname = path:match(WINDOWS_VOLUME_PATTERN) ---@type string?,string?
|
||||
local unc_path, ufname = path:match(WINDOWS_UNC_PATTERN) ---@type string?,string?
|
||||
local win_pre_fname = volume_path or unc_path
|
||||
local is_windows = win_pre_fname ~= nil
|
||||
if is_windows then
|
||||
path = volume_path .. M.uri_encode(fname:gsub('\\', '/'))
|
||||
local fname = unc_path and ufname or vfname
|
||||
path = win_pre_fname .. M.uri_encode(fname:gsub('\\', '/'))
|
||||
else
|
||||
path = M.uri_encode(path)
|
||||
end
|
||||
local uri_parts = { 'file://' }
|
||||
if is_windows then
|
||||
if is_windows and not unc_path then
|
||||
table.insert(uri_parts, '/')
|
||||
end
|
||||
table.insert(uri_parts, path)
|
||||
@ -80,10 +89,14 @@ end
|
||||
---@return string URI
|
||||
function M.uri_from_bufnr(bufnr)
|
||||
local fname = vim.api.nvim_buf_get_name(bufnr)
|
||||
local volume_path = fname:match('^([a-zA-Z]:).*')
|
||||
local is_windows = volume_path ~= nil
|
||||
local volume_path, vfname = fname:match(WINDOWS_VOLUME_PATTERN) ---@type string?,string?
|
||||
local unc_path, ufname = fname:match(WINDOWS_UNC_PATTERN) ---@type string?,string?
|
||||
local win_pre_fname = volume_path or unc_path
|
||||
local is_windows = win_pre_fname ~= nil
|
||||
local scheme ---@type string?
|
||||
if is_windows then
|
||||
fname = unc_path and ufname or vfname
|
||||
fname = win_pre_fname .. fname
|
||||
fname = fname:gsub('\\', '/')
|
||||
scheme = fname:match(WINDOWS_URI_SCHEME_PATTERN)
|
||||
else
|
||||
@ -106,10 +119,14 @@ function M.uri_to_fname(uri)
|
||||
end
|
||||
uri = M.uri_decode(uri)
|
||||
--TODO improve this.
|
||||
if is_windows_file_uri(uri) then
|
||||
if is_windows_volume_uri(uri) then
|
||||
uri = uri:gsub('^file:/+', ''):gsub('/', '\\')
|
||||
else
|
||||
uri = uri:gsub('^file:/+', '/') ---@type string
|
||||
if IS_WINDOWS and uri:match('^file://[a-zA-Z.-]') ~= nil then -- handle UNC file uri in windows
|
||||
uri = uri:gsub('^file:/+', '//'):gsub('/', '\\')
|
||||
else
|
||||
uri = uri:gsub('^file:/+', '/')
|
||||
end
|
||||
end
|
||||
return uri
|
||||
end
|
||||
|
@ -49,6 +49,21 @@ describe('URI methods', function()
|
||||
eq('file:///C:/Foo%20/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
|
||||
end)
|
||||
|
||||
it('UNC path includes only ascii characters', function()
|
||||
exec_lua([[filepath = '\\\\wsl.local-host\\Foo\\Bar\\Baz.txt']])
|
||||
|
||||
eq('file://wsl.local-host/Foo/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
|
||||
end)
|
||||
|
||||
it('UNC path including white space', function()
|
||||
exec_lua([[filepath = '\\\\wsl.local-host\\Foo \\Bar\\Baz.txt']])
|
||||
|
||||
eq(
|
||||
'file://wsl.local-host/Foo%20/Bar/Baz.txt',
|
||||
exec_lua('return vim.uri_from_fname(filepath)')
|
||||
)
|
||||
end)
|
||||
|
||||
it('file path including Unicode characters', function()
|
||||
exec_lua([[filepath = 'C:\\xy\\åäö\\ɧ\\汉语\\↥\\🤦\\🦄\\å\\بِيَّ.txt']])
|
||||
|
||||
@ -127,6 +142,26 @@ describe('URI methods', function()
|
||||
eq('C:\\Foo \\Bar\\Baz.txt', exec_lua(test_case))
|
||||
end)
|
||||
|
||||
it('UNC path includes only ascii characters', function()
|
||||
skip(not is_os('win'), 'Not applicable on non-Windows')
|
||||
local test_case = [[
|
||||
local uri = 'file://wsl.local-host/Foo/Bar/Baz.txt'
|
||||
return vim.uri_to_fname(uri)
|
||||
]]
|
||||
|
||||
eq('\\\\wsl.local-host\\Foo\\Bar\\Baz.txt', exec_lua(test_case))
|
||||
end)
|
||||
|
||||
it('UNC path including white space', function()
|
||||
skip(not is_os('win'), 'Not applicable on non-Windows')
|
||||
local test_case = [[
|
||||
local uri = 'file://wsl.local-host/Foo%20/Bar/Baz.txt'
|
||||
return vim.uri_to_fname(uri)
|
||||
]]
|
||||
|
||||
eq('\\\\wsl.local-host\\Foo \\Bar\\Baz.txt', exec_lua(test_case))
|
||||
end)
|
||||
|
||||
it('file path including Unicode characters', function()
|
||||
local test_case = [[
|
||||
local uri = 'file:///C:/xy/%C3%A5%C3%A4%C3%B6/%C9%A7/%E6%B1%89%E8%AF%AD/%E2%86%A5/%F0%9F%A4%A6/%F0%9F%A6%84/a%CC%8A/%D8%A8%D9%90%D9%8A%D9%8E%D9%91.txt'
|
||||
|
Loading…
Reference in New Issue
Block a user