Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lsp: vim.lsp.diagnostics and lsp-handlers #12655

Merged
merged 1 commit into from
Nov 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 42 additions & 11 deletions runtime/doc/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,9 @@ created for extmark changes.
==============================================================================
Global Functions *api-global*

nvim__get_hl_defs({ns_id}) *nvim__get_hl_defs()*
TODO: Documentation

nvim__get_lib_dir() *nvim__get_lib_dir()*
TODO: Documentation

Expand Down Expand Up @@ -952,6 +955,9 @@ nvim_get_runtime_file({name}, {all}) *nvim_get_runtime_file()*
It is not an error to not find any files. An empty array is
returned then.

Attributes: ~
{fast}

Parameters: ~
{name} pattern of files to search for
{all} whether to return all matches or only the first
Expand Down Expand Up @@ -987,6 +993,7 @@ nvim_input({keys}) *nvim_input()*
Note:
|keycodes| like <CR> are translated, so "<" is special. To
input a literal "<", send <LT>.

Note:
For mouse events use |nvim_input_mouse()|. The pseudokey
form "<LeftMouse><col,row>" is deprecated since
Expand Down Expand Up @@ -1378,8 +1385,7 @@ nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts})
{opts} Optional parameters. Reserved for future use.

*nvim_set_client_info()*
nvim_set_client_info({name}, {version}, {type}, {methods},
{attributes})
nvim_set_client_info({name}, {version}, {type}, {methods}, {attributes})
Self-identifies the client.

The client/plugin/application should call this after
Expand Down Expand Up @@ -1491,7 +1497,7 @@ nvim_set_decoration_provider({ns_id}, {opts})
disable the provider until the next redraw. Similarily, return
`false` in `on_win` will skip the `on_lines` calls for that
window (but any extmarks set in `on_win` will still be used).
A plugin managing multiple sources of decorations should
A plugin managing multiple sources of decoration should
ideally only set one provider, and merge the sources
internally. You can use multiple `ns_id` for the extmarks
set/modified inside the callback anyway.
Expand Down Expand Up @@ -1519,6 +1525,33 @@ nvim_set_decoration_provider({ns_id}, {opts})
• on_end: called at the end of a redraw cycle
["end", tick]

nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
Set a highlight group.

TODO: ns_id = 0, should modify :highlight namespace TODO val
should take update vs reset flag

Parameters: ~
{ns_id} number of namespace for this highlight
{name} highlight group name, like ErrorMsg
{val} highlight definiton map, like
|nvim_get_hl_by_name|.

nvim_set_hl_ns({ns_id}) *nvim_set_hl_ns()*
Set active namespace for highlights.

NB: this function can be called from async contexts, but the
semantics are not yet well-defined. To start with
|nvim_set_decoration_provider| on_win and on_line callbacks
are explicitly allowed to change the namespace during a redraw
cycle.

Attributes: ~
{fast}

Parameters: ~
{ns_id} the namespace to activate

nvim_set_keymap({mode}, {lhs}, {rhs}, {opts}) *nvim_set_keymap()*
Sets a global |mapping| for the given mode.

Expand Down Expand Up @@ -1618,8 +1651,8 @@ nvim__buf_stats({buffer}) *nvim__buf_stats()*
TODO: Documentation

*nvim_buf_add_highlight()*
nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line},
{col_start}, {col_end})
nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line}, {col_start},
{col_end})
Adds a highlight to buffer.

Useful for plugins that dynamically generate highlights to a
Expand Down Expand Up @@ -2067,8 +2100,7 @@ nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {opts})
|nvim_set_keymap()|

*nvim_buf_set_lines()*
nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing},
{replacement})
nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
Sets (replaces) a line-range in the buffer.

Indexing is zero-based, end-exclusive. Negative indices are
Expand Down Expand Up @@ -2116,8 +2148,7 @@ nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
{value} Variable value

*nvim_buf_set_virtual_text()*
nvim_buf_set_virtual_text({buffer}, {src_id}, {line}, {chunks},
{opts})
nvim_buf_set_virtual_text({buffer}, {src_id}, {line}, {chunks}, {opts})
Set the virtual text (annotation) for a buffer line.

By default (and currently the only option) the text will be
Expand Down Expand Up @@ -2449,8 +2480,8 @@ nvim_ui_pum_set_bounds({width}, {height}, {row}, {col})
Note that this method is not to be confused with
|nvim_ui_pum_set_height()|, which sets the number of visible
items in the popup menu, while this function sets the bounding
box of the popup menu, including visual decorations such as
boarders and sliders. Floats need not use the same font size,
box of the popup menu, including visual elements such as
borders and sliders. Floats need not use the same font size,
nor be anchored to exact grid corners, so one can set
floating-point numbers to the popup menu geometry.

Expand Down
129 changes: 129 additions & 0 deletions runtime/doc/lsp-extension.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
*lsp-extension.txt* LSP Extension

NVIM REFERENCE MANUAL


The `vim.lsp` Lua module is a framework for building LSP plugins.

1. Start with |vim.lsp.start_client()| and |vim.lsp.buf_attach_client()|.
2. Peek at the API: >
:lua print(vim.inspect(vim.lsp))
< 3. See |lsp-extension-example| for a full example.

================================================================================
LSP EXAMPLE *lsp-extension-example*

This example is for plugin authors or users who want a lot of control. If you
are just getting started see |lsp-quickstart|.

For more advanced configurations where just filtering by filetype isn't
sufficient, you can use the `vim.lsp.start_client()` and
`vim.lsp.buf_attach_client()` commands to easily customize the configuration
however you please. For example, if you want to do your own filtering, or
start a new LSP client based on the root directory for working with multiple
projects in a single session. To illustrate, the following is a fully working
Lua example.

The example will:
1. Check for each new buffer whether or not we want to start an LSP client.
2. Try to find a root directory by ascending from the buffer's path.
3. Create a new LSP for that root directory if one doesn't exist.
4. Attach the buffer to the client for that root directory.

>
-- Some path manipulation utilities
local function is_dir(filename)
local stat = vim.loop.fs_stat(filename)
return stat and stat.type == 'directory' or false
end

local path_sep = vim.loop.os_uname().sysname == "Windows" and "\\" or "/"
-- Assumes filepath is a file.
local function dirname(filepath)
local is_changed = false
local result = filepath:gsub(path_sep.."([^"..path_sep.."]+)$", function()
is_changed = true
return ""
end)
return result, is_changed
end

local function path_join(...)
return table.concat(vim.tbl_flatten {...}, path_sep)
end

-- Ascend the buffer's path until we find the rootdir.
-- is_root_path is a function which returns bool
local function buffer_find_root_dir(bufnr, is_root_path)
local bufname = vim.api.nvim_buf_get_name(bufnr)
if vim.fn.filereadable(bufname) == 0 then
return nil
end
local dir = bufname
-- Just in case our algo is buggy, don't infinite loop.
for _ = 1, 100 do
local did_change
dir, did_change = dirname(dir)
if is_root_path(dir, bufname) then
return dir, bufname
end
-- If we can't ascend further, then stop looking.
if not did_change then
return nil
end
end
end

-- A table to store our root_dir to client_id lookup. We want one LSP per
-- root directory, and this is how we assert that.
local javascript_lsps = {}
-- Which filetypes we want to consider.
local javascript_filetypes = {
["javascript.jsx"] = true;
["javascript"] = true;
["typescript"] = true;
["typescript.jsx"] = true;
}

-- Create a template configuration for a server to start, minus the root_dir
-- which we will specify later.
local javascript_lsp_config = {
name = "javascript";
cmd = { path_join(os.getenv("JAVASCRIPT_LANGUAGE_SERVER_DIRECTORY"), "lib", "language-server-stdio.js") };
}

-- This needs to be global so that we can call it from the autocmd.
function check_start_javascript_lsp()
local bufnr = vim.api.nvim_get_current_buf()
-- Filter which files we are considering.
if not javascript_filetypes[vim.api.nvim_buf_get_option(bufnr, 'filetype')] then
return
end
-- Try to find our root directory. We will define this as a directory which contains
-- node_modules. Another choice would be to check for `package.json`, or for `.git`.
local root_dir = buffer_find_root_dir(bufnr, function(dir)
return is_dir(path_join(dir, 'node_modules'))
-- return vim.fn.filereadable(path_join(dir, 'package.json')) == 1
-- return is_dir(path_join(dir, '.git'))
end)
-- We couldn't find a root directory, so ignore this file.
if not root_dir then return end

-- Check if we have a client already or start and store it.
local client_id = javascript_lsps[root_dir]
if not client_id then
local new_config = vim.tbl_extend("error", javascript_lsp_config, {
root_dir = root_dir;
})
client_id = vim.lsp.start_client(new_config)
javascript_lsps[root_dir] = client_id
end
-- Finally, attach to the buffer to track changes. This will do nothing if we
-- are already attached.
vim.lsp.buf_attach_client(bufnr, client_id)
end

vim.api.nvim_command [[autocmd BufReadPost * lua check_start_javascript_lsp()]]
<

vim:tw=78:ts=8:ft=help:norl: