diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 52f88bb621..f4f6ff8fdc 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -363,6 +363,8 @@ PLUGINS unrelated Python virtual environments are activated. |provider-python| +• |:checkhealth| now checks for an available |vim.ui.open()| handler. + STARTUP • todo diff --git a/runtime/lua/vim/health/health.lua b/runtime/lua/vim/health/health.lua index 9fab85582f..855ba075a6 100644 --- a/runtime/lua/vim/health/health.lua +++ b/runtime/lua/vim/health/health.lua @@ -418,6 +418,14 @@ local function check_external_tools() health.warn('ripgrep not available') end + local open_cmd, err = vim.ui._get_open_cmd() + if open_cmd then + health.ok(('vim.ui.open: handler found (%s)'):format(open_cmd[1])) + else + --- @cast err string + health.warn(err) + end + -- `vim.pack` prefers git 2.36 but tries to work with 2.x. if vim.fn.executable('git') == 1 then local git = vim.fn.exepath('git') diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index abcf7f8ba0..5a2cb662ef 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -166,27 +166,44 @@ function M.open(path, opt) if opt.cmd then cmd = vim.list_extend(opt.cmd --[[@as string[] ]], { path }) - elseif vim.fn.has('mac') == 1 then - cmd = { 'open', path } - elseif vim.fn.has('win32') == 1 then - cmd = { 'cmd.exe', '/c', 'start', '', path } - elseif vim.fn.executable('xdg-open') == 1 then - cmd = { 'xdg-open', path } - job_opt.stdout = false - job_opt.stderr = false - elseif vim.fn.executable('wslview') == 1 then - cmd = { 'wslview', path } - elseif vim.fn.executable('explorer.exe') == 1 then - cmd = { 'explorer.exe', path } - elseif vim.fn.executable('lemonade') == 1 then - cmd = { 'lemonade', 'open', path } else - return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open, lemonade)' + local open_cmd, err = M._get_open_cmd() + if err then + return nil, err + end + ---@cast open_cmd string[] + if open_cmd[1] == 'xdg-open' then + job_opt.stdout = false + job_opt.stderr = false + end + cmd = vim.list_extend(open_cmd, { path }) end return vim.system(cmd, job_opt), nil end +--- Get an available command used to open the path or URL. +--- +--- @return string[]|nil # Command, or nil if not found. +--- @return nil|string # Error message on failure, or nil on success. +function M._get_open_cmd() + if vim.fn.has('mac') == 1 then + return { 'open' }, nil + elseif vim.fn.has('win32') == 1 then + return { 'cmd.exe', '/c', 'start', '' }, nil + elseif vim.fn.executable('xdg-open') == 1 then + return { 'xdg-open' }, nil + elseif vim.fn.executable('wslview') == 1 then + return { 'wslview' }, nil + elseif vim.fn.executable('explorer.exe') == 1 then + return { 'explorer.exe' }, nil + elseif vim.fn.executable('lemonade') == 1 then + return { 'lemonade', 'open' }, nil + else + return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open, lemonade)' + end +end + --- Returns all URLs at cursor, if any. --- @return string[] function M._get_urls()