This is a Neovim plugin/library for generating statusline components from the built-in LSP client.
- 2021年03月13日: Some users report success using the Google "Noto Emoji" font for
status_symbol
andindicator_hint
. - 2020年11月19日: Please note that the default diagnostics symbols require Font Awesome or a Nerd Font. You may also change the diagnostics symbols as shown in the configuration section.
- 2020年11月13日: Due to this PR, you must update to
the latest Neovim
master
to avoid errors with the old diagnostics API. See issue #19 for more information. - 2020年05月25日: There has been a minor breaking change to the API:
extension_callbacks
is now namedextensions
. There have also been a number of additions and improvements; see the below (specifically Configuration and Example Use) for details.
Show the current containing function (like b:coc_current_function
):
Statusline showing current function and no errors
Easily access diagnostic counts: Statusline showing some error indicators
Show progress messages from servers: Statusline showing progress messages from a server
You will need a version of Neovim that includes the built-in LSP client (right now, that means
nightly). Use your preferred package/plugin manager. With
vim-packager
, this looks like:
call packager#add('nvim-lua/lsp-status.nvim')
The plugin provides several utilities:
update_current_function() -- Set/reset the b:lsp_current_function variable -- Shows the current function, method, class, struct, interface, enum, module, or namespace diagnostics() -- Return a table with all diagnostic counts for the current buffer messages() -- Return a table listing progress and other status messages for display register_progress() -- Register the provided handler for progress messages register_client() -- Register a client for messages -- Integrate misc. LS protocol extensions into the messages framework -- Each extension table contains a set of handlers and a setup() function -- returning said handlers extensions = { clangd, pyls_ms } -- Set up a client for use with lsp-status. Calls register_client() and sets up -- buffer autocommands on_attach(client) config(config_vals) -- Configure lsp-status -- Table of client capabilities extended to signal support for progress messages capabilities status() -- One example out-of-the-box statusline component (as shown in the images above)
lsp-status.nvim
supports messaging-related protocol extensions offered by
clangd
and Microsoft's Python language
server (python/setStatusBarMessage
,
python/beginProgress
, python/reportProgress
, and python/endProgress
). To use these extensions,
register the handlers provided in the extensions
table (the keys for the handlers are
the relevant LSP method name).
Note: For clangd
, you must also set init_options = { clangdFileStatus = true }
.
New: You can also call lsp_status.extensions.<server name>.setup()
to return the full set of
handlers, as shown below.
You can configure lsp-status.nvim
using the config
function, which takes a table of
configuration values. The following configuration options are supported:
kind_labels
: An optional map from LSP symbol kinds to label symbols. Used to decorate the current function name. Default:{}
select_symbol
: An optional handler of the formfunction(cursor_pos, document_symbol)
that should returntrue
ifdocument_symbol
(aDocumentSymbol
) should be accepted as the symbol currently containing the cursor.
For example, the sumneko lua server sends
valueRange
(which is not specified in the protocol) to give the range for a function's start and
end. To respect valueRange
, you can use the following configuration:
lsp_status.config { select_symbol = function(cursor_pos, symbol) if symbol.valueRange then local value_range = { ["start"] = { character = 0, line = vim.fn.byte2line(symbol.valueRange[1]) }, ["end"] = { character = 0, line = vim.fn.byte2line(symbol.valueRange[2]) } } return require("lsp-status.util").in_range(cursor_pos, value_range) end end }
current_function
: Boolean,true
if the current function should be updated and displayed in the default statusline component.show_filename
: Boolean,true
if the filename should be displayed in the progress text.indicator_*
-group: strings to show as diagnostic warnings. If you don't have Nerd/Awesome Fonts you can replace defaults with ASCII chars like this:
-- Put this somewhere near lsp_status.register_progress()
lsp_status.config({
indicator_errors = 'E',
indicator_warnings = 'W',
indicator_info = 'i',
indicator_hint = '?',
indicator_ok = 'Ok',
})
indicator_separator
: a string which goes between each diagnostic group symbol and its count. Defaults to whitespace.component_separator
: a string which goes between each "chunk" of the statusline component (i.e. different diagnostic groups, messages). Defaults to whitespace.diagnostics
: Boolean,true
by default. Iffalse
, the default statusline component does not display LSP diagnostics.
Here is an example configuration (also using nvim-lsp
)
showing how lsp-status
can be integrated into one's statusline and other LSP configuration.
In any Lua file you load:
local lsp_status = require('lsp-status') -- completion_customize_lsp_label as used in completion-nvim -- Optional: customize the kind labels used in identifying the current function. -- g:completion_customize_lsp_label is a dict mapping from LSP symbol kind -- to the string you want to display as a label -- lsp_status.config { kind_labels = vim.g.completion_customize_lsp_label } -- Register the progress handler lsp_status.register_progress()
Before calling setup
for each relevant LSP client:
-- Set default client capabilities plus window/workDoneProgress config.capabilities = vim.tbl_extend('keep', config.capabilities or {}, lsp_status.capabilities)
In an on_attach
function for each relevant LSP client:
-- Register client for messages and set up buffer autocommands to update -- the statusline and the current function. -- NOTE: on_attach is called with the client object, which is the "client" parameter below lsp_status.on_attach(client)
Specific client configuration (following nvim-lsp
conventions):
clangd = { handlers = lsp_status.extensions.clangd.setup() }, pyls_ms = { handlers = lsp_status.extensions.pyls_ms.setup() },
An example statusline segment is provided in
lua/lsp-status/statusline. You are encouraged to read the source
and develop your own statusline segment, but if you'd like something reasonable out-of-the-box, you
can call lsp_status.status()
somewhere in your statusline definition (make sure you have
require
'd the lsp-status
module too!)
Here's a complete example:
lua << END local lsp_status = require('lsp-status') lsp_status.register_progress() local lspconfig = require('lspconfig') -- Some arbitrary servers lspconfig.clangd.setup({ handlers = lsp_status.extensions.clangd.setup(), init_options = { clangdFileStatus = true }, on_attach = lsp_status.on_attach, capabilities = lsp_status.capabilities }) lspconfig.pyls_ms.setup({ handlers = lsp_status.extensions.pyls_ms.setup(), settings = { python = { workspaceSymbols = { enabled = true }}}, on_attach = lsp_status.on_attach, capabilities = lsp_status.capabilities }) lspconfig.ghcide.setup({ on_attach = lsp_status.on_attach, capabilities = lsp_status.capabilities }) lspconfig.rust_analyzer.setup({ on_attach = lsp_status.on_attach, capabilities = lsp_status.capabilities }) END " Statusline function! LspStatus() abort if luaeval('#vim.lsp.buf_get_clients() > 0') return luaeval("require('lsp-status').status()") endif return '' endfunction
This plugin is "complete" - it works in all the ways it was originally intended to, and it doesn't seem to break. That said, it hasn't been tested much, and I'm open to adding new features if others want them.
One thing that probably should be added is proper documentation of some sort. The code could also stand to be cleaned up.
Bug reports and feature requests are welcome! PRs are doubly welcome!