From 2613ba5000d4c0d9b15e2eec2d2b97615575925e Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Tue, 5 Dec 2023 10:01:32 -0800 Subject: feat(defaults): enable 'termguicolors' by default when supported by terminal Enable 'termguicolors' automatically when Nvim can detect that truecolor is supported by the host terminal. If $COLORTERM is set to "truecolor" or "24bit", or the terminal's terminfo entry contains capabilities for Tc, RGB, or setrgbf and setrgbb, then we assume that the terminal supports truecolor. Otherwise, the terminal is queried (using both XTGETTCAP and SGR + DECRQSS). If the terminal's response to these queries (if any) indicates that it supports truecolor, then 'termguicolors' is enabled. --- runtime/lua/vim/termcap.lua | 52 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'runtime/lua/vim/termcap.lua') diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index 862cc52149..b88d9ac9ba 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -12,7 +12,10 @@ local M = {} --- emulator supports the XTGETTCAP sequence. --- --- @param caps string|table A terminal capability or list of capabilities to query ---- @param cb function(cap:string, seq:string) Function to call when a response is received +--- @param cb function(cap:string, found:bool, seq:string?) Callback function which is called for +--- each capability in {caps}. {found} is set to true if the capability was found or false +--- otherwise. {seq} is the control sequence for the capability if found, or nil for +--- boolean capabilities. function M.query(caps, cb) vim.validate({ caps = { caps, { 'string', 'table' } }, @@ -23,21 +26,33 @@ function M.query(caps, cb) caps = { caps } end - local count = #caps + local pending = {} ---@type table + for _, v in ipairs(caps) do + pending[v] = true + end + + local timer = assert(vim.uv.new_timer()) - vim.api.nvim_create_autocmd('TermResponse', { + local id = vim.api.nvim_create_autocmd('TermResponse', { callback = function(args) local resp = args.data ---@type string - local k, v = resp:match('^\027P1%+r(%x+)=(%x+)$') - if k and v then + local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') + if k and rest then local cap = vim.text.hexdecode(k) - local seq = - vim.text.hexdecode(v):gsub('\\E', '\027'):gsub('%%p%d', ''):gsub('\\(%d+)', string.char) + local seq ---@type string? + if rest:match('^=%x+$') then + seq = vim.text + .hexdecode(rest:sub(2)) + :gsub('\\E', '\027') + :gsub('%%p%d', '') + :gsub('\\(%d+)', string.char) + end + + cb(cap, true, seq) - cb(cap, seq) + pending[cap] = nil - count = count - 1 - if count == 0 then + if next(pending) == nil then return true end end @@ -57,6 +72,23 @@ function M.query(caps, cb) end io.stdout:write(query) + + timer:start(1000, 0, function() + -- Delete the autocommand if no response was received + vim.schedule(function() + -- Suppress error if autocommand has already been deleted + pcall(vim.api.nvim_del_autocmd, id) + + -- Call the callback for all capabilities that were not found + for k in pairs(pending) do + cb(k, false, nil) + end + end) + + if not timer:is_closing() then + timer:close() + end + end) end return M -- cgit From e527842211188a5c069ef4f4759aa291353b707f Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 13 Dec 2023 08:14:30 -0600 Subject: fix(termcap): only call callback for requested capabilities (#26546) If multiple XTGETTCAP requests are active at once (for example, for requesting the Ms capability and truecolor capabilities), then the TermResponse autocommand may fire for capabilities that were not requested. Instead, make sure that the provided callback is only called for capabilities that were actually requested. --- runtime/lua/vim/termcap.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim/termcap.lua') diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index b88d9ac9ba..e48657b3c2 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -39,6 +39,12 @@ function M.query(caps, cb) local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') if k and rest then local cap = vim.text.hexdecode(k) + if not pending[cap] then + -- Received a response for a capability we didn't request. This can happen if there are + -- multiple concurrent XTGETTCAP requests + return + end + local seq ---@type string? if rest:match('^=%x+$') then seq = vim.text -- cgit From ffeb31c2f962b895bbc7111dd095e4b5ba27e88d Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Thu, 14 Dec 2023 11:37:45 -0600 Subject: fix(termcap): set 'nested' on TermResponse autocommand --- runtime/lua/vim/termcap.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim/termcap.lua') diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua index e48657b3c2..ec29acca48 100644 --- a/runtime/lua/vim/termcap.lua +++ b/runtime/lua/vim/termcap.lua @@ -34,6 +34,7 @@ function M.query(caps, cb) local timer = assert(vim.uv.new_timer()) local id = vim.api.nvim_create_autocmd('TermResponse', { + nested = true, callback = function(args) local resp = args.data ---@type string local k, rest = resp:match('^\027P1%+r(%x+)(.*)$') -- cgit