neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit b02c83941493db79e4ab7ba23adb665d4528f791
parent 862338255da6dc08ae4f4f78db0034c81e3cdf38
Author: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date:   Wed, 24 Jul 2024 09:04:09 -0500

fix(tui): set id parameter in OSC 8 sequences (#29840)

The id parameter is used to communicate to the terminal that two URLs
are the same. Without an id, the terminal must rely on heuristics to
determine which cells belong together to make a single hyperlink.

See the relevant section in the spec [1] for more details.

[1]: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#hover-underlining-and-the-id-parameter
Diffstat:
Msrc/nvim/tui/tui.c | 7++++++-
Mtest/functional/terminal/tui_spec.lua | 8++++----
2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c @@ -793,7 +793,12 @@ static void update_attrs(TUIData *tui, int attr_id) if (attrs.url >= 0) { const char *url = urls.keys[attrs.url]; kv_size(tui->urlbuf) = 0; - kv_printf(tui->urlbuf, "\x1b]8;;%s\x1b\\", url); + + // Add some fixed offset to the URL ID to deconflict with other + // applications which may set their own IDs + const uint64_t id = 0xE1EA0000U + (uint32_t)attrs.url; + + kv_printf(tui->urlbuf, "\x1b]8;id=%" PRIu64 ";%s\x1b\\", id, url); out(tui, tui->urlbuf.items, kv_size(tui->urlbuf)); } else { out(tui, S_LEN("\x1b]8;;\x1b\\")); diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua @@ -1968,9 +1968,9 @@ describe('TUI', function() if not req then return end - local url = req:match('\027]8;;(.*)$') - if url ~= nil then - table.insert(_G.urls, url) + local id, url = req:match('\027]8;id=(%d+);(.*)$') + if id ~= nil and url ~= nil then + table.insert(_G.urls, { id = tonumber(id), url = url }) end end, }) @@ -1984,7 +1984,7 @@ describe('TUI', function() }) ]]) retry(nil, 1000, function() - eq({ 'https://example.com', '' }, exec_lua([[return _G.urls]])) + eq({ { id = 0xE1EA0000, url = 'https://example.com' } }, exec_lua([[return _G.urls]])) end) end) end)