mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
feat(lsp): add more LSP defaults (#28500)
- crn for rename - crr for code actions - gr for references - <C-S> (in Insert mode) for signature help
This commit is contained in:
parent
9b028bd64f
commit
6888607415
@ -281,6 +281,10 @@ gr{char} Replace the virtual characters under the cursor with
|
|||||||
that have a special meaning in Insert mode, such as
|
that have a special meaning in Insert mode, such as
|
||||||
most CTRL-keys, cannot be used.
|
most CTRL-keys, cannot be used.
|
||||||
|
|
||||||
|
*gr-default*
|
||||||
|
Mapped to |vim.lsp.buf.references()| by default.
|
||||||
|
|default-mappings|
|
||||||
|
|
||||||
*digraph-arg*
|
*digraph-arg*
|
||||||
The argument for Normal mode commands like |r| and |t| is a single character.
|
The argument for Normal mode commands like |r| and |t| is a single character.
|
||||||
When 'cpo' doesn't contain the 'D' flag, this character can also be entered
|
When 'cpo' doesn't contain the 'D' flag, this character can also be entered
|
||||||
|
@ -61,47 +61,41 @@ options are not restored when the LSP client is stopped or detached.
|
|||||||
- |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or
|
- |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or
|
||||||
a custom keymap for `K` exists.
|
a custom keymap for `K` exists.
|
||||||
|
|
||||||
|
*crr* *v_crr* *crn* *i_CTRL-S*
|
||||||
|
Some keymaps are created unconditionally when Nvim starts:
|
||||||
|
- "crn" is mapped in Normal mode to |vim.lsp.buf.rename()|
|
||||||
|
- "crr" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
|
||||||
|
- "gr" is mapped in Normal mode to |vim.lsp.buf.references()| |gr-default|
|
||||||
|
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
|
||||||
|
|
||||||
|
If not wanted, these keymaps can be removed at any time using
|
||||||
|
|vim.keymap.del()| or |:unmap|.
|
||||||
|
|
||||||
*lsp-defaults-disable*
|
*lsp-defaults-disable*
|
||||||
To override the above defaults, set or unset the options on |LspAttach|: >lua
|
To override the above defaults, set or unset the options on |LspAttach|: >lua
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd('LspAttach', {
|
vim.api.nvim_create_autocmd('LspAttach', {
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
vim.bo[ev.buf].formatexpr = nil
|
vim.bo[ev.buf].formatexpr = nil
|
||||||
vim.bo[ev.buf].omnifunc = nil
|
vim.bo[ev.buf].omnifunc = nil
|
||||||
vim.keymap.del("n", "K", { buffer = ev.buf })
|
vim.keymap.del('n', 'K', { buffer = ev.buf })
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
To use other LSP features like hover, rename, etc. you can set other keymaps
|
To use other LSP features, set keymaps on |LspAttach|. Not all language
|
||||||
on |LspAttach|. Example: >lua
|
servers provide the same capabilities. To ensure you only set keymaps if the
|
||||||
vim.api.nvim_create_autocmd('LspAttach', {
|
language server supports a feature, guard keymaps behind capability checks.
|
||||||
callback = function(args)
|
Example: >lua
|
||||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf })
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
The most common functions are:
|
|
||||||
|
|
||||||
- |vim.lsp.buf.hover()|
|
|
||||||
- |vim.lsp.buf.format()|
|
|
||||||
- |vim.lsp.buf.references()|
|
|
||||||
- |vim.lsp.buf.implementation()|
|
|
||||||
- |vim.lsp.buf.code_action()|
|
|
||||||
|
|
||||||
|
|
||||||
Not all language servers provide the same capabilities. To ensure you only set
|
|
||||||
keymaps if the language server supports a feature, you can guard the keymap
|
|
||||||
calls behind capability checks:
|
|
||||||
>lua
|
|
||||||
vim.api.nvim_create_autocmd('LspAttach', {
|
vim.api.nvim_create_autocmd('LspAttach', {
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||||
if client.server_capabilities.hoverProvider then
|
if client.supports_method('textDocument/implementation') then
|
||||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = args.buf })
|
vim.keymap.set('n', 'g<C-I>', vim.lsp.buf.implementation, { buffer = args.buf })
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
<
|
<
|
||||||
|
|
||||||
To learn what capabilities are available you can run the following command in
|
To learn what capabilities are available you can run the following command in
|
||||||
a buffer with a started LSP client: >vim
|
a buffer with a started LSP client: >vim
|
||||||
|
|
||||||
|
@ -408,6 +408,10 @@ The following changes to existing APIs or features add new behavior.
|
|||||||
• 'comments' includes "fb:•".
|
• 'comments' includes "fb:•".
|
||||||
• 'shortmess' includes the "C" flag.
|
• 'shortmess' includes the "C" flag.
|
||||||
• 'grepprg' defaults to using ripgrep if available.
|
• 'grepprg' defaults to using ripgrep if available.
|
||||||
|
• |crn| in Normal mode maps to |vim.lsp.buf.rename()|.
|
||||||
|
• |crr| in Normal and Visual mode maps to |vim.lsp.buf.code_action()|.
|
||||||
|
• "gr" in Normal mode maps to |vim.lsp.buf.references()| |gr-default|
|
||||||
|
• |i_CTRL-S| in Insert mode maps to |vim.lsp.buf.signature_help()|
|
||||||
• Automatic linting of treesitter query files (see |ft-query-plugin|).
|
• Automatic linting of treesitter query files (see |ft-query-plugin|).
|
||||||
Can be disabled via: >lua
|
Can be disabled via: >lua
|
||||||
vim.g.query_lint_on = {}
|
vim.g.query_lint_on = {}
|
||||||
@ -438,9 +442,10 @@ The following changes to existing APIs or features add new behavior.
|
|||||||
|
|
||||||
:call netrw#BrowseX(expand(exists("g:netrw_gx")? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR>
|
:call netrw#BrowseX(expand(exists("g:netrw_gx")? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR>
|
||||||
|
|
||||||
• |vim.lsp.start()| now maps |K| to use |vim.lsp.buf.hover()| if the server
|
• |vim.lsp.start()| now creates the following default keymaps (assuming the
|
||||||
supports it, unless |'keywordprg'| was customized before calling
|
server supports the feature):
|
||||||
|vim.lsp.start()|.
|
- |K| in Normal mode maps to |vim.lsp.buf.hover()|, unless |'keywordprg'|
|
||||||
|
was customized before calling |vim.lsp.start()|.
|
||||||
|
|
||||||
• Terminal buffers started with no arguments (and use 'shell') close
|
• Terminal buffers started with no arguments (and use 'shell') close
|
||||||
automatically if the job exited without error, eliminating the (often
|
automatically if the job exited without error, eliminating the (often
|
||||||
|
@ -137,6 +137,10 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y".
|
|||||||
- * |v_star-default|
|
- * |v_star-default|
|
||||||
- gc |gc-default| |v_gc-default| |o_gc-default|
|
- gc |gc-default| |v_gc-default| |o_gc-default|
|
||||||
- gcc |gcc-default|
|
- gcc |gcc-default|
|
||||||
|
- |crn|
|
||||||
|
- |crr|
|
||||||
|
- gr |gr-default|
|
||||||
|
- <C-S> |i_CTRL-S|
|
||||||
- Nvim LSP client defaults |lsp-defaults|
|
- Nvim LSP client defaults |lsp-defaults|
|
||||||
- K |K-lsp-default|
|
- K |K-lsp-default|
|
||||||
|
|
||||||
|
@ -144,6 +144,31 @@ do
|
|||||||
end
|
end
|
||||||
vim.keymap.set({ 'o' }, 'gc', textobject_rhs, { desc = 'Comment textobject' })
|
vim.keymap.set({ 'o' }, 'gc', textobject_rhs, { desc = 'Comment textobject' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Default maps for LSP functions.
|
||||||
|
---
|
||||||
|
--- These are mapped unconditionally to avoid confusion. If no server is attached, or if a server
|
||||||
|
--- does not support a capability, an error message is displayed rather than exhibiting different
|
||||||
|
--- behavior.
|
||||||
|
---
|
||||||
|
--- See |gr-default|, |crn|, |crr|, |i_CTRL-S|.
|
||||||
|
do
|
||||||
|
vim.keymap.set('n', 'crn', function()
|
||||||
|
vim.lsp.buf.rename()
|
||||||
|
end, { desc = 'vim.lsp.buf.rename()' })
|
||||||
|
|
||||||
|
vim.keymap.set({ 'n', 'v' }, 'crr', function()
|
||||||
|
vim.lsp.buf.code_action()
|
||||||
|
end, { desc = 'vim.lsp.buf.code_action()' })
|
||||||
|
|
||||||
|
vim.keymap.set('n', 'gr', function()
|
||||||
|
vim.lsp.buf.references()
|
||||||
|
end, { desc = 'vim.lsp.buf.references()' })
|
||||||
|
|
||||||
|
vim.keymap.set('i', '<C-S>', function()
|
||||||
|
vim.lsp.buf.signature_help()
|
||||||
|
end, { desc = 'vim.lsp.buf.signature_help()' })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Default menus
|
--- Default menus
|
||||||
@ -243,230 +268,140 @@ do
|
|||||||
vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid))
|
vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid))
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
|
||||||
|
|
||||||
-- Only do the following when the TUI is attached
|
-- Only do the following when the TUI is attached
|
||||||
local tty = nil
|
local tty = nil
|
||||||
for _, ui in ipairs(vim.api.nvim_list_uis()) do
|
for _, ui in ipairs(vim.api.nvim_list_uis()) do
|
||||||
if ui.chan == 1 and ui.stdout_tty then
|
if ui.chan == 1 and ui.stdout_tty then
|
||||||
tty = ui
|
tty = ui
|
||||||
break
|
break
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if tty then
|
|
||||||
local group = vim.api.nvim_create_augroup('nvim_tty', {})
|
|
||||||
|
|
||||||
--- Set an option after startup (so that OptionSet is fired), but only if not
|
|
||||||
--- already set by the user.
|
|
||||||
---
|
|
||||||
--- @param option string Option name
|
|
||||||
--- @param value any Option value
|
|
||||||
local function setoption(option, value)
|
|
||||||
if vim.api.nvim_get_option_info2(option, {}).was_set then
|
|
||||||
-- Don't do anything if option is already set
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wait until Nvim is finished starting to set the option to ensure the
|
|
||||||
-- OptionSet event fires.
|
|
||||||
if vim.v.vim_did_enter == 1 then
|
|
||||||
--- @diagnostic disable-next-line:no-unknown
|
|
||||||
vim.o[option] = value
|
|
||||||
else
|
|
||||||
vim.api.nvim_create_autocmd('VimEnter', {
|
|
||||||
group = group,
|
|
||||||
once = true,
|
|
||||||
nested = true,
|
|
||||||
callback = function()
|
|
||||||
setoption(option, value)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Guess value of 'background' based on terminal color.
|
if tty then
|
||||||
---
|
local group = vim.api.nvim_create_augroup('nvim_tty', {})
|
||||||
--- We write Operating System Command (OSC) 11 to the terminal to request the
|
|
||||||
--- terminal's background color. We then wait for a response. If the response
|
--- Set an option after startup (so that OptionSet is fired), but only if not
|
||||||
--- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
|
--- already set by the user.
|
||||||
--- compute the luminance[1] of the RGB color and classify it as light/dark
|
|
||||||
--- accordingly. Note that the color components may have anywhere from one to
|
|
||||||
--- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
|
|
||||||
--- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
|
|
||||||
--- ignored in the calculations.
|
|
||||||
---
|
|
||||||
--- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
|
|
||||||
do
|
|
||||||
--- Parse a string of hex characters as a color.
|
|
||||||
---
|
---
|
||||||
--- The string can contain 1 to 4 hex characters. The returned value is
|
--- @param option string Option name
|
||||||
--- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
|
--- @param value any Option value
|
||||||
---
|
local function setoption(option, value)
|
||||||
--- For instance, if only a single hex char "a" is used, then this function
|
if vim.api.nvim_get_option_info2(option, {}).was_set then
|
||||||
--- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
|
-- Don't do anything if option is already set
|
||||||
--- 256).
|
return
|
||||||
---
|
|
||||||
--- @param c string Color as a string of hex chars
|
|
||||||
--- @return number? Intensity of the color
|
|
||||||
local function parsecolor(c)
|
|
||||||
if #c == 0 or #c > 4 then
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local val = tonumber(c, 16)
|
-- Wait until Nvim is finished starting to set the option to ensure the
|
||||||
if not val then
|
-- OptionSet event fires.
|
||||||
return nil
|
if vim.v.vim_did_enter == 1 then
|
||||||
|
--- @diagnostic disable-next-line:no-unknown
|
||||||
|
vim.o[option] = value
|
||||||
|
else
|
||||||
|
vim.api.nvim_create_autocmd('VimEnter', {
|
||||||
|
group = group,
|
||||||
|
once = true,
|
||||||
|
nested = true,
|
||||||
|
callback = function()
|
||||||
|
setoption(option, value)
|
||||||
|
end,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
local max = tonumber(string.rep('f', #c), 16)
|
|
||||||
return val / max
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parse an OSC 11 response
|
--- Guess value of 'background' based on terminal color.
|
||||||
---
|
---
|
||||||
--- Either of the two formats below are accepted:
|
--- We write Operating System Command (OSC) 11 to the terminal to request the
|
||||||
|
--- terminal's background color. We then wait for a response. If the response
|
||||||
|
--- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
|
||||||
|
--- compute the luminance[1] of the RGB color and classify it as light/dark
|
||||||
|
--- accordingly. Note that the color components may have anywhere from one to
|
||||||
|
--- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
|
||||||
|
--- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
|
||||||
|
--- ignored in the calculations.
|
||||||
---
|
---
|
||||||
--- OSC 11 ; rgb:<red>/<green>/<blue>
|
--- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
|
||||||
---
|
do
|
||||||
--- or
|
--- Parse a string of hex characters as a color.
|
||||||
---
|
---
|
||||||
--- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
|
--- The string can contain 1 to 4 hex characters. The returned value is
|
||||||
---
|
--- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
|
||||||
--- where
|
---
|
||||||
---
|
--- For instance, if only a single hex char "a" is used, then this function
|
||||||
--- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
|
--- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
|
||||||
---
|
--- 256).
|
||||||
--- The alpha component is ignored, if present.
|
---
|
||||||
---
|
--- @param c string Color as a string of hex chars
|
||||||
--- @param resp string OSC 11 response
|
--- @return number? Intensity of the color
|
||||||
--- @return string? Red component
|
local function parsecolor(c)
|
||||||
--- @return string? Green component
|
if #c == 0 or #c > 4 then
|
||||||
--- @return string? Blue component
|
return nil
|
||||||
local function parseosc11(resp)
|
|
||||||
local r, g, b
|
|
||||||
r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
|
|
||||||
if not r and not g and not b then
|
|
||||||
local a
|
|
||||||
r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
|
|
||||||
if not a or #a > 4 then
|
|
||||||
return nil, nil, nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local val = tonumber(c, 16)
|
||||||
|
if not val then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local max = tonumber(string.rep('f', #c), 16)
|
||||||
|
return val / max
|
||||||
end
|
end
|
||||||
|
|
||||||
if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
|
--- Parse an OSC 11 response
|
||||||
return r, g, b
|
---
|
||||||
end
|
--- Either of the two formats below are accepted:
|
||||||
|
---
|
||||||
return nil, nil, nil
|
--- OSC 11 ; rgb:<red>/<green>/<blue>
|
||||||
end
|
---
|
||||||
|
--- or
|
||||||
local timer = assert(vim.uv.new_timer())
|
---
|
||||||
|
--- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
|
||||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
---
|
||||||
group = group,
|
--- where
|
||||||
nested = true,
|
---
|
||||||
callback = function(args)
|
--- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
|
||||||
local resp = args.data ---@type string
|
---
|
||||||
local r, g, b = parseosc11(resp)
|
--- The alpha component is ignored, if present.
|
||||||
if r and g and b then
|
---
|
||||||
local rr = parsecolor(r)
|
--- @param resp string OSC 11 response
|
||||||
local gg = parsecolor(g)
|
--- @return string? Red component
|
||||||
local bb = parsecolor(b)
|
--- @return string? Green component
|
||||||
|
--- @return string? Blue component
|
||||||
if rr and gg and bb then
|
local function parseosc11(resp)
|
||||||
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
|
local r, g, b
|
||||||
local bg = luminance < 0.5 and 'dark' or 'light'
|
r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
|
||||||
setoption('background', bg)
|
if not r and not g and not b then
|
||||||
|
local a
|
||||||
|
r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
|
||||||
|
if not a or #a > 4 then
|
||||||
|
return nil, nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
io.stdout:write('\027]11;?\007')
|
if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
|
||||||
|
return r, g, b
|
||||||
|
end
|
||||||
|
|
||||||
timer:start(1000, 0, function()
|
return nil, nil, nil
|
||||||
-- 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)
|
|
||||||
end)
|
|
||||||
|
|
||||||
if not timer:is_closing() then
|
|
||||||
timer:close()
|
|
||||||
end
|
end
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- If the TUI (term_has_truecolor) was able to determine that the host
|
|
||||||
--- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the
|
|
||||||
--- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's
|
|
||||||
--- response indicates that it does support truecolor enable 'termguicolors',
|
|
||||||
--- but only if the user has not already disabled it.
|
|
||||||
do
|
|
||||||
if tty.rgb then
|
|
||||||
-- The TUI was able to determine truecolor support
|
|
||||||
setoption('termguicolors', true)
|
|
||||||
else
|
|
||||||
local caps = {} ---@type table<string, boolean>
|
|
||||||
require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found)
|
|
||||||
if not found then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
caps[cap] = true
|
|
||||||
if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then
|
|
||||||
setoption('termguicolors', true)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local timer = assert(vim.uv.new_timer())
|
local timer = assert(vim.uv.new_timer())
|
||||||
|
|
||||||
-- Arbitrary colors to set in the SGR sequence
|
|
||||||
local r = 1
|
|
||||||
local g = 2
|
|
||||||
local b = 3
|
|
||||||
|
|
||||||
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||||
group = group,
|
group = group,
|
||||||
nested = true,
|
nested = true,
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
local resp = args.data ---@type string
|
local resp = args.data ---@type string
|
||||||
local decrqss = resp:match('^\027P1%$r([%d;:]+)m$')
|
local r, g, b = parseosc11(resp)
|
||||||
|
if r and g and b then
|
||||||
|
local rr = parsecolor(r)
|
||||||
|
local gg = parsecolor(g)
|
||||||
|
local bb = parsecolor(b)
|
||||||
|
|
||||||
if decrqss then
|
if rr and gg and bb then
|
||||||
-- The DECRQSS SGR response first contains attributes separated by
|
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
|
||||||
-- semicolons, followed by the SGR itself with parameters separated
|
local bg = luminance < 0.5 and 'dark' or 'light'
|
||||||
-- by colons. Some terminals include "0" in the attribute list
|
setoption('background', bg)
|
||||||
-- unconditionally; others do not. Our SGR sequence did not set any
|
|
||||||
-- attributes, so there should be no attributes in the list.
|
|
||||||
local attrs = vim.split(decrqss, ';')
|
|
||||||
if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The returned SGR sequence should begin with 48:2
|
|
||||||
local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$')
|
|
||||||
if not sgr then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The remaining elements of the SGR sequence should be the 3 colors
|
|
||||||
-- we set. Some terminals also include an additional parameter
|
|
||||||
-- (which can even be empty!), so handle those cases as well
|
|
||||||
local params = vim.split(sgr, ':')
|
|
||||||
if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if
|
|
||||||
tonumber(params[#params - 2]) == r
|
|
||||||
and tonumber(params[#params - 1]) == g
|
|
||||||
and tonumber(params[#params]) == b
|
|
||||||
then
|
|
||||||
setoption('termguicolors', true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -474,16 +409,7 @@ if tty then
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Write SGR followed by DECRQSS. This sets the background color then
|
io.stdout:write('\027]11;?\007')
|
||||||
-- immediately asks the terminal what the background color is. If the
|
|
||||||
-- terminal responds to the DECRQSS with the same SGR sequence that we
|
|
||||||
-- sent then the terminal supports truecolor.
|
|
||||||
local decrqss = '\027P$qm\027\\'
|
|
||||||
if os.getenv('TMUX') then
|
|
||||||
decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027'))
|
|
||||||
end
|
|
||||||
-- Reset attributes first, as other code may have set attributes.
|
|
||||||
io.stdout:write(string.format('\027[0m\027[48;2;%d;%d;%dm%s', r, g, b, decrqss))
|
|
||||||
|
|
||||||
timer:start(1000, 0, function()
|
timer:start(1000, 0, function()
|
||||||
-- Delete the autocommand if no response was received
|
-- Delete the autocommand if no response was received
|
||||||
@ -497,13 +423,115 @@ if tty then
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- If the TUI (term_has_truecolor) was able to determine that the host
|
||||||
|
--- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the
|
||||||
|
--- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's
|
||||||
|
--- response indicates that it does support truecolor enable 'termguicolors',
|
||||||
|
--- but only if the user has not already disabled it.
|
||||||
|
do
|
||||||
|
if tty.rgb then
|
||||||
|
-- The TUI was able to determine truecolor support
|
||||||
|
setoption('termguicolors', true)
|
||||||
|
else
|
||||||
|
local caps = {} ---@type table<string, boolean>
|
||||||
|
require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found)
|
||||||
|
if not found then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
caps[cap] = true
|
||||||
|
if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then
|
||||||
|
setoption('termguicolors', true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local timer = assert(vim.uv.new_timer())
|
||||||
|
|
||||||
|
-- Arbitrary colors to set in the SGR sequence
|
||||||
|
local r = 1
|
||||||
|
local g = 2
|
||||||
|
local b = 3
|
||||||
|
|
||||||
|
local id = vim.api.nvim_create_autocmd('TermResponse', {
|
||||||
|
group = group,
|
||||||
|
nested = true,
|
||||||
|
callback = function(args)
|
||||||
|
local resp = args.data ---@type string
|
||||||
|
local decrqss = resp:match('^\027P1%$r([%d;:]+)m$')
|
||||||
|
|
||||||
|
if decrqss then
|
||||||
|
-- The DECRQSS SGR response first contains attributes separated by
|
||||||
|
-- semicolons, followed by the SGR itself with parameters separated
|
||||||
|
-- by colons. Some terminals include "0" in the attribute list
|
||||||
|
-- unconditionally; others do not. Our SGR sequence did not set any
|
||||||
|
-- attributes, so there should be no attributes in the list.
|
||||||
|
local attrs = vim.split(decrqss, ';')
|
||||||
|
if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The returned SGR sequence should begin with 48:2
|
||||||
|
local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$')
|
||||||
|
if not sgr then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The remaining elements of the SGR sequence should be the 3 colors
|
||||||
|
-- we set. Some terminals also include an additional parameter
|
||||||
|
-- (which can even be empty!), so handle those cases as well
|
||||||
|
local params = vim.split(sgr, ':')
|
||||||
|
if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if
|
||||||
|
tonumber(params[#params - 2]) == r
|
||||||
|
and tonumber(params[#params - 1]) == g
|
||||||
|
and tonumber(params[#params]) == b
|
||||||
|
then
|
||||||
|
setoption('termguicolors', true)
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Write SGR followed by DECRQSS. This sets the background color then
|
||||||
|
-- immediately asks the terminal what the background color is. If the
|
||||||
|
-- terminal responds to the DECRQSS with the same SGR sequence that we
|
||||||
|
-- sent then the terminal supports truecolor.
|
||||||
|
local decrqss = '\027P$qm\027\\'
|
||||||
|
if os.getenv('TMUX') then
|
||||||
|
decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027'))
|
||||||
|
end
|
||||||
|
-- Reset attributes first, as other code may have set attributes.
|
||||||
|
io.stdout:write(string.format('\027[0m\027[48;2;%d;%d;%dm%s', r, g, b, decrqss))
|
||||||
|
|
||||||
|
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)
|
||||||
|
end)
|
||||||
|
|
||||||
|
if not timer:is_closing() then
|
||||||
|
timer:close()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Default 'grepprg' to ripgrep if available.
|
--- Default options
|
||||||
if vim.fn.executable('rg') == 1 then
|
do
|
||||||
-- Match :grep default, otherwise rg searches cwd by default
|
--- Default 'grepprg' to ripgrep if available.
|
||||||
-- Use -uuu to make ripgrep not do its default filtering
|
if vim.fn.executable('rg') == 1 then
|
||||||
vim.o.grepprg = 'rg --vimgrep -uuu $* ' .. (vim.fn.has('unix') == 1 and '/dev/null' or 'nul')
|
-- Match :grep default, otherwise rg searches cwd by default
|
||||||
vim.o.grepformat = '%f:%l:%c:%m'
|
-- Use -uuu to make ripgrep not do its default filtering
|
||||||
|
vim.o.grepprg = 'rg --vimgrep -uuu $* ' .. (vim.fn.has('unix') == 1 and '/dev/null' or 'nul')
|
||||||
|
vim.o.grepformat = '%f:%l:%c:%m'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -348,7 +348,7 @@ function lsp._set_defaults(client, bufnr)
|
|||||||
and is_empty_or_default(bufnr, 'keywordprg')
|
and is_empty_or_default(bufnr, 'keywordprg')
|
||||||
and vim.fn.maparg('K', 'n', false, false) == ''
|
and vim.fn.maparg('K', 'n', false, false) == ''
|
||||||
then
|
then
|
||||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr })
|
vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr, desc = 'vim.lsp.buf.hover()' })
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
if client.supports_method(ms.textDocument_diagnostic) then
|
if client.supports_method(ms.textDocument_diagnostic) then
|
||||||
|
Loading…
Reference in New Issue
Block a user