diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /runtime/lua/vim/ui.lua | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'runtime/lua/vim/ui.lua')
-rw-r--r-- | runtime/lua/vim/ui.lua | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index 99b9b78e2a..532decf5e9 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -117,6 +117,8 @@ end --- -- Asynchronous. --- vim.ui.open("https://neovim.io/") --- vim.ui.open("~/path/to/file") +--- -- Use the "osurl" command to handle the path or URL. +--- vim.ui.open("gh#neovim/neovim!29490", { cmd = { 'osurl' } }) --- -- Synchronous (wait until the process exits). --- local cmd, err = vim.ui.open("$VIMRUNTIME") --- if cmd then @@ -125,23 +127,29 @@ end --- ``` --- ---@param path string Path or URL to open +---@param opt? { cmd?: string[] } Options +--- - cmd string[]|nil Command used to open the path or URL. --- ---@return vim.SystemObj|nil # Command object, or nil if not found. ---@return nil|string # Error message on failure, or nil on success. --- ---@see |vim.system()| -function M.open(path) +function M.open(path, opt) vim.validate({ path = { path, 'string' }, }) local is_uri = path:match('%w+:') if not is_uri then - path = vim.fn.expand(path) + path = vim.fs.normalize(path) end - local cmd --- @type string[] + opt = opt or {} + local cmd ---@type string[] + local job_opt = { text = true, detach = true } --- @type vim.SystemOpts - if vim.fn.has('mac') == 1 then + 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 if vim.fn.executable('rundll32') == 1 then @@ -149,37 +157,79 @@ function M.open(path) else return nil, 'vim.ui.open: rundll32 not found' end + 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('xdg-open') == 1 then - cmd = { 'xdg-open', path } else return nil, 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)' end - return vim.system(cmd, { text = true, detach = true }), nil + return vim.system(cmd, job_opt), nil end ---- Gets the URL at cursor, if any. -function M._get_url() - if vim.bo.filetype == 'markdown' then - local range = vim.api.nvim_win_get_cursor(0) - vim.treesitter.get_parser():parse(range) - -- marking the node as `markdown_inline` is required. Setting it to `markdown` does not - -- work. - local current_node = vim.treesitter.get_node { lang = 'markdown_inline' } - while current_node do - local type = current_node:type() - if type == 'inline_link' or type == 'image' then - local child = assert(current_node:named_child(1)) - return vim.treesitter.get_node_text(child, 0) +--- Returns all URLs at cursor, if any. +--- @return string[] +function M._get_urls() + local urls = {} ---@type string[] + + local bufnr = vim.api.nvim_get_current_buf() + local cursor = vim.api.nvim_win_get_cursor(0) + local row = cursor[1] - 1 + local col = cursor[2] + local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, { row, col }, { row, col }, { + details = true, + type = 'highlight', + overlap = true, + }) + for _, v in ipairs(extmarks) do + local details = v[4] + if details and details.url then + urls[#urls + 1] = details.url + end + end + + local highlighter = vim.treesitter.highlighter.active[bufnr] + if highlighter then + local range = { row, col, row, col } + local ltree = highlighter.tree:language_for_range(range) + local lang = ltree:lang() + local query = vim.treesitter.query.get(lang, 'highlights') + if query then + local tree = assert(ltree:tree_for_range(range)) + for _, match, metadata in query:iter_matches(tree:root(), bufnr, row, row + 1) do + for id, nodes in pairs(match) do + for _, node in ipairs(nodes) do + if vim.treesitter.node_contains(node, range) then + local url = metadata[id] and metadata[id].url + if url and match[url] then + for _, n in ipairs(match[url]) do + urls[#urls + 1] = + vim.treesitter.get_node_text(n, bufnr, { metadata = metadata[url] }) + end + end + end + end + end end - current_node = current_node:parent() end end - return vim.fn.expand('<cfile>') + + if #urls == 0 then + -- If all else fails, use the filename under the cursor + table.insert( + urls, + vim._with({ go = { isfname = vim.o.isfname .. ',@-@' } }, function() + return vim.fn.expand('<cfile>') + end) + ) + end + + return urls end return M |