From bce2364f60112901ef8d1cf5cbeeeb4caabed668 Mon Sep 17 00:00:00 2001 From: "neovim-backports[bot]" <175700243+neovim-backports[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:18:47 -0500 Subject: [PATCH] fix(tui): set id parameter in OSC 8 sequences (#29847) 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 (cherry picked from commit b02c83941493db79e4ab7ba23adb665d4528f791) --- src/nvim/tui/tui.c | 7 ++++++- test/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 index c74f5a5260..b6fc4a496d 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -781,7 +781,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 index b532da58c8..66c038fbd6 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -1941,9 +1941,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, }) @@ -1957,7 +1957,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)