-
Notifications
You must be signed in to change notification settings - Fork 2.1k
UI Customization
Note: these instruction assume Neovim 0.6.0 or later!
Floating windows with borders are built-into the neovim core handler. The borders can be styled by passing in a character and highlight group. Highlight groups must be set with an autocmd to avoid being overwritten by your colorscheme.
vim.cmd [[autocmd! ColorScheme * highlight NormalFloat guibg=#1f2335]]
vim.cmd [[autocmd! ColorScheme * highlight FloatBorder guifg=white guibg=#1f2335]]
local border = {
{"🭽", "FloatBorder"},
{"▔", "FloatBorder"},
{"🭾", "FloatBorder"},
{"▕", "FloatBorder"},
{"🭿", "FloatBorder"},
{"▁", "FloatBorder"},
{"🭼", "FloatBorder"},
{"▏", "FloatBorder"},
}
-- LSP settings (for overriding per client)
local handlers = {
["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, {border = border}),
["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, {border = border }),
}
-- Do not forget to use the on_attach function
require 'lspconfig'.myserver.setup { handlers=handlers }
-- To instead override globally
local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview
function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...)
opts = opts or {}
opts.border = opts.border or border
return orig_util_open_floating_preview(contents, syntax, opts, ...)
end
require 'lspconfig'.myservertwo.setup {}
local M = {}
M.icons = {
Class = " ",
Color = " ",
Constant = " ",
Constructor = " ",
Enum = " ",
EnumMember = " ",
Field = " ",
File = " ",
Folder = " ",
Function = " ",
Interface = "",
Keyword = " ",
Method = "ƒ ",
Module = " ",
Property = " ",
Snippet = " ",
Struct = " ",
Text = " ",
Unit = " ",
Value = " ",
Variable = " ",
}
function M.setup()
local kinds = vim.lsp.protocol.CompletionItemKind
for i, kind in ipairs(kinds) do
kinds[i] = M.icons[kind] or kind
end
end
return M
You can configure diagnostic options globally. See :help vim.diagnostic.config
for more advanced customization options.
vim.diagnostic.config({
virtual_text = true,
signs = true,
underline = true,
update_in_insert = false,
severity_sort = false,
})
Note: With the default settings, you will not see updated diagnostics until you leave insert mode. Set update_in_insert = true
if you want diagnostics to update while in insert mode.
local signs = { Error = " ", Warn = " ", Hint = " ", Info = " " }
for type, icon in pairs(signs) do
local hl = "DiagnosticSign" .. type
vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
end
function PrintDiagnostics(opts, bufnr, line_nr, client_id)
bufnr = bufnr or 0
line_nr = line_nr or (vim.api.nvim_win_get_cursor(0)[1] - 1)
opts = opts or {['lnum'] = line_nr}
local line_diagnostics = vim.diagnostic.get(bufnr, opts)
if vim.tbl_isempty(line_diagnostics) then return end
local diagnostic_message = ""
for i, diagnostic in ipairs(line_diagnostics) do
diagnostic_message = diagnostic_message .. string.format("%d: %s", i, diagnostic.message or "")
print(diagnostic_message)
if i ~= #line_diagnostics then
diagnostic_message = diagnostic_message .. "\n"
end
end
vim.api.nvim_echo({{diagnostic_message, "Normal"}}, false, {})
end
vim.api.nvim_create_autocmd("CursorHold", {
group = vim.api.nvim_create_augroup("print_diagnostics", { clear = true }),
callback = PrintDiagnostics
})
-- You will likely want to reduce updatetime which affects CursorHold
-- note: this setting is global and should be set only once
vim.o.updatetime = 250
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
group = vim.api.nvim_create_augroup("float_diagnostic", { clear = true }),
callback = function ()
vim.diagnostic.open_float(nil, {focus=false})
end
})
For diagnostics for specific cursor position
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
group = vim.api.nvim_create_augroup("float_diagnostic_cursor", { clear = true }),
callback = function ()
vim.diagnostic.open_float(nil, {focus=false, scope="cursor"})
end
})
After neovim 0.7, put the code below into on_attach()
vim.api.nvim_create_autocmd("CursorHold", {
buffer = bufnr,
callback = function()
local opts = {
focusable = false,
close_events = { "BufLeave", "CursorMoved", "InsertEnter", "FocusLost" },
border = 'rounded',
source = 'always',
prefix = ' ',
scope = 'cursor',
}
vim.diagnostic.open_float(nil, opts)
end
})
See https://www.reddit.com/r/neovim/comments/mvhfw7/can_built_in_lsp_diagnostics_be_limited_to_show_a/
local function goto_definition(split_cmd)
local util = vim.lsp.util
local log = require("vim.lsp.log")
local api = vim.api
-- note, this handler style is for neovim 0.5.1/0.6, if on 0.5, call with function(_, method, result)
local handler = function(_, result, ctx)
if result == nil or vim.tbl_isempty(result) then
local _ = log.info() and log.info(ctx.method, "No location found")
return nil
end
if split_cmd then
vim.cmd(split_cmd)
end
if vim.tbl_islist(result) then
util.jump_to_location(result[1])
if #result > 1 then
-- util.set_qflist(util.locations_to_items(result))
vim.fn.setqflist(util.locations_to_items(result))
api.nvim_command("copen")
api.nvim_command("wincmd p")
end
else
util.jump_to_location(result)
end
end
return handler
end
vim.lsp.handlers["textDocument/definition"] = goto_definition('split')
vim.diagnostic.config({
virtual_text = {
source = "always", -- Or "if_many"
},
float = {
source = "always", -- Or "if_many"
},
})
By default, this character is a square icon (■).
vim.diagnostic.config({
virtual_text = {
prefix = '■', -- Could be '●', '▎', 'x'
}
})
See the properties of the signs with sign list
.
for _, diag in ipairs({ "Error", "Warn", "Info", "Hint" }) do
vim.fn.sign_define("DiagnosticSign" .. diag, {
text = "",
texthl = "DiagnosticSign" .. diag,
linehl = "",
numhl = "DiagnosticSign" .. diag,
})
end
Depending on how your theme is styled, you may wish to replace the prefix for numhl
with "DiagnosticVirtualText"
or "DiagnosticFloating"
to better fit the intended look.
Add the following to your on_attach (this allows checking server capabilities to avoid calling invalid commands).
if client.resolved_capabilities.document_highlight then
vim.cmd [[
hi! LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
hi! LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
hi! LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
]]
vim.api.nvim_create_augroup('lsp_document_highlight', {
clear = false
})
vim.api.nvim_clear_autocmds({
buffer = bufnr,
group = 'lsp_document_highlight',
})
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
group = 'lsp_document_highlight',
buffer = bufnr,
callback = vim.lsp.buf.document_highlight,
})
vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
group = 'lsp_document_highlight',
buffer = bufnr,
callback = vim.lsp.buf.clear_references,
})
end
Note this requires Neovim v0.7 which introduces vim.api.nvim_create_augroup
and vim.api.nvim_create_autocmd
. If you are using Neovim with version prior to v0.7 then use the following:
Click to expand
if client.resolved_capabilities.document_highlight then
vim.cmd [[
hi! LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
hi! LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
hi! LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
augroup lsp_document_highlight
autocmd! * <buffer>
autocmd! CursorHold <buffer> lua vim.lsp.buf.document_highlight()
autocmd! CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()
autocmd! CursorMoved <buffer> lua vim.lsp.buf.clear_references()
autocmd! CursorMovedI <buffer> lua vim.lsp.buf.clear_references()
augroup END
]]
end
If you are on Neovim v0.8, client.resolved_capabilities.document_highlight
is deprecated. In its place, use client.server_capabilities.documentHighlightProvider
.