docs: news, intro, lsp, api #33687

This commit is contained in:
Justin M. Keyes
2025-06-01 14:13:50 -07:00
committed by GitHub
parent ff95d7ff9a
commit 80753332d1
10 changed files with 171 additions and 150 deletions

View File

@@ -1185,10 +1185,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
ANSI termcodes, so you can use Nvim as a "scrollback pager" (for terminals
like kitty): *ansi-colorize* *terminal-scrollback-pager* >lua
vim.api.nvim_create_user_command('TermHl', function()
local b = vim.api.nvim_create_buf(false, true)
local chan = vim.api.nvim_open_term(b, {})
vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
vim.api.nvim_win_set_buf(0, b)
vim.api.nvim_open_term(0, {})
end, { desc = 'Highlights ANSI termcodes in curbuf' })
<

View File

@@ -28,7 +28,8 @@ Follow these steps to get LSP features:
upstream installation instructions. You can find language servers here:
https://microsoft.github.io/language-server-protocol/implementors/servers/
2. Use |vim.lsp.config()| to define a configuration for an LSP client.
2. Use |vim.lsp.config()| to define a configuration for an LSP client
(see https://github.com/neovim/nvim-lspconfig for examples).
Example: >lua
vim.lsp.config['luals'] = {
-- Command and arguments to start the server.
@@ -55,12 +56,14 @@ Follow these steps to get LSP features:
}
}
}
<
3. Use |vim.lsp.enable()| to enable a configuration.
Example: >lua
vim.lsp.enable('luals')
<
4. Restart Nvim, or use ":edit" to reload the buffer.
4. Open a code file matching one of the `filetypes` specified in the config.
Note: Depending on the LSP server, you may need to ensure your project has
a |lsp-root_markers| file so the workspace can be recognized.
5. Check that LSP is active ("attached") for the buffer: >vim
:checkhealth vim.lsp
@@ -77,6 +80,16 @@ listed below, if (1) the language server supports the functionality and (2)
the options are empty or were set by the builtin runtime (ftplugin) files. The
options are not restored when the LSP client is stopped or detached.
GLOBAL DEFAULTS
*grr* *gra* *grn* *gri* *i_CTRL-S*
These GLOBAL keymaps are created unconditionally when Nvim starts:
- "grn" is mapped in Normal mode to |vim.lsp.buf.rename()|
- "gra" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
- "grr" is mapped in Normal mode to |vim.lsp.buf.references()|
- "gri" is mapped in Normal mode to |vim.lsp.buf.implementation()|
- "gO" is mapped in Normal mode to |vim.lsp.buf.document_symbol()|
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
BUFFER-LOCAL DEFAULTS
- 'omnifunc' is set to |vim.lsp.omnifunc()|, use |i_CTRL-X_CTRL-O| to trigger
completion.
@@ -89,20 +102,10 @@ BUFFER-LOCAL DEFAULTS
- |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or
a custom keymap for `K` exists.
GLOBAL DEFAULTS
*grr* *gra* *grn* *gri* *i_CTRL-S*
These GLOBAL keymaps are created unconditionally when Nvim starts:
- "grn" is mapped in Normal mode to |vim.lsp.buf.rename()|
- "gra" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
- "grr" is mapped in Normal mode to |vim.lsp.buf.references()|
- "gri" is mapped in Normal mode to |vim.lsp.buf.implementation()|
- "gO" is mapped in Normal mode to |vim.lsp.buf.document_symbol()|
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
DISABLING DEFAULTS *lsp-defaults-disable*
You can remove GLOBAL keymaps at any time using |vim.keymap.del()| or
|:unmap|. See also |gr-default|.
*lsp-defaults-disable*
To remove or override BUFFER-LOCAL defaults, define a |LspAttach| handler: >lua
vim.api.nvim_create_autocmd('LspAttach', {
@@ -253,7 +256,7 @@ FAQ *lsp-faq*
autocmd BufWritePre *.rs lua vim.lsp.buf.format({ async = false })
<
*lsp-vs-treesitter*
- Q: How do LSP and Treesitter compare?
- Q: How do LSP, Treesitter and Ctags compare?
- A: LSP requires a client and language server. The language server uses
semantic analysis to understand code at a project level. This provides
language servers with the ability to rename across files, find
@@ -265,6 +268,11 @@ FAQ *lsp-faq*
like syntax highlighting, simple goto-definitions, scope analysis and
more.
A |ctags|-like program can generate a |tags| file that allows Nvim to
jump to definitions, provide simple completions via |i_CTRL-X_CTRL-]|
command. It is not as featureful and doesn't have semantic understanding,
but it is fast, lightweight and useful for navigating polyglot projects.
================================================================================
LSP API *lsp-api*
@@ -717,46 +725,40 @@ Lua module: vim.lsp *lsp-core*
implementation re-uses a client if name and root_dir
matches.
• {root_dir}? (`string|fun(bufnr: integer, on_dir:fun(root_dir?:string))`)
*lsp-root_dir()* Directory where the LSP server will
base its workspaceFolders, rootUri, and rootPath on
initialization. The function form receives a buffer
number and `on_dir` callback which it must call to
provide root_dir, or LSP will not be activated for
the buffer. Thus a `root_dir()` function can
dynamically decide per-buffer whether to activate (or
skip) LSP. See example at |vim.lsp.enable()|.
• {root_markers}? (`(string|string[])[]`) Directory markers (.e.g.
'.git/') where the LSP server will base its
*lsp-root_dir()* Decides the workspace root: the
directory where the LSP server will base its
workspaceFolders, rootUri, and rootPath on
initialization. Unused if `root_dir` is provided.
The list order decides the priority. To indicate
initialization. The function form must call the
`on_dir` callback to provide the root dir, or LSP
will not be activated for the buffer. Thus a
`root_dir()` function can dynamically decide
per-buffer whether to activate (or skip) LSP. See
example at |vim.lsp.enable()|.
• {root_markers}? (`(string|string[])[]`) *lsp-root_markers*
Filename(s) (".git/", "package.json", …) used to
decide the workspace root. Unused if `root_dir` is
defined. The list order decides priority. To indicate
"equal priority", specify names in a nested list
(`{ { 'a', 'b' }, ... }`) Each entry in this list is
a set of one or more markers. For each set, Nvim will
search upwards for each marker contained in the set.
If a marker is found, the directory which contains
that marker is used as the root directory. If no
markers from the set are found, the process is
repeated with the next set in the list.
`{ { 'a.txt', 'b.lua' }, ... }`.
Example: >lua
For each item, Nvim will search upwards (from the
buffer file) for that marker, or list of markers;
search stops at the first directory containing that
marker, and the directory is used as the root dir
(workspace folder).
Example: Find the first ancestor directory containing
file or directory "stylua.toml"; if not found, find
the first ancestor containing ".git": >lua
root_markers = { 'stylua.toml', '.git' }
<
Find the first parent directory containing the file
`stylua.toml`. If not found, find the first parent
directory containing the file or directory `.git`.
Example: >lua
Example: Find the first ancestor directory containing
EITHER "stylua.toml" or ".luarc.json"; if not found,
find the first ancestor containing ".git": >lua
root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' }
<
Find the first parent directory containing EITHER
`stylua.toml` or `.luarc.json`. If not found, find
the first parent directory containing the file or
directory `.git`.
buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
Implements the `textDocument/did…` notifications required to track a
@@ -954,6 +956,12 @@ enable({name}, {enable}) *vim.lsp.enable()*
vim.lsp.enable({'luals', 'pyright'})
<
Example: *lsp-restart* Passing `false` stops and detaches the client(s).
Thus you can "restart" LSP by disabling and re-enabling a given config: >lua
vim.lsp.enable('clangd', false)
vim.lsp.enable('clangd', true)
<
Example: To dynamically decide whether LSP is activated, define a
|lsp-root_dir()| function which calls `on_dir()` only when you want that
config to activate: >lua
@@ -971,7 +979,8 @@ enable({name}, {enable}) *vim.lsp.enable()*
Parameters: ~
• {name} (`string|string[]`) Name(s) of client(s) to enable.
• {enable} (`boolean?`) `true|nil` to enable, `false` to disable.
• {enable} (`boolean?`) `true|nil` to enable, `false` to disable
(actively stops and detaches clients as needed)
foldclose({kind}, {winid}) *vim.lsp.foldclose()*
Close all {kind} of folds in the the window with {winid}.
@@ -1090,6 +1099,9 @@ get_log_path() *vim.lsp.get_log_path()*
is_enabled({name}) *vim.lsp.is_enabled()*
Checks if the given LSP config is enabled (globally, not per-buffer).
Unlike `vim.lsp.config['…']`, this does not have the side-effect of
resolving the config.
Parameters: ~
• {name} (`string`) Config name
@@ -1370,11 +1382,12 @@ Lua module: vim.lsp.client *lsp-client*
command name, and the value is a function which
is called if any LSP action (code action, code
lenses, …) triggers the command.
• {detached}? (`boolean`, default: true) Daemonize the server
process so that it runs in a separate process
group from Nvim. Nvim will shutdown the process
on exit, but if Nvim fails to exit cleanly this
could leave behind orphaned server processes.
• {detached}? (`boolean`, default: `true`) Daemonize the
server process so that it runs in a separate
process group from Nvim. Nvim will shutdown the
process on exit, but if Nvim fails to exit
cleanly this could leave behind orphaned server
processes.
• {flags}? (`table`) A table with flags for the client.
The current (experimental) flags are:
• {allow_incremental_sync}? (`boolean`,
@@ -1399,8 +1412,8 @@ Lua module: vim.lsp.client *lsp-client*
initialization request as
`initializationOptions`. See `initialize` in
the LSP spec.
• {name}? (`string`) (default: client-id) Name in logs
and user messages.
• {name}? (`string`, default: client-id) Name in logs and
user messages.
• {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) Called "position
encoding" in LSP spec. The encoding that the
LSP server expects, used for communication. Not
@@ -1450,7 +1463,7 @@ Lua module: vim.lsp.client *lsp-client*
this list. Can be `null` if the client supports
workspace folders but none are configured. See
`workspaceFolders` in LSP spec.
• {workspace_required}? (`boolean`) (default false) Server requires a
• {workspace_required}? (`boolean`, default: `false`) Server requires a
workspace (no "single file" support). Note:
Without a workspace, cross-file features
(navigation, hover) may or may not work

View File

@@ -140,6 +140,8 @@ EDITOR
• |:iput| works like |:put| but adjusts indent.
• |omnicompletion| in `help` buffer. |ft-help-omni|
• Setting "'0" in 'shada' prevents storing the jumplist in the shada file.
• 'shada' now correctly respects "/0" and "f0".
EVENTS
@@ -149,14 +151,20 @@ EVENTS
HIGHLIGHTS
• |hl-DiffTextAdd| highlights added text within a changed line.
• |hl-StderrMsg| |hl-StdoutMsg|
LSP
• |vim.lsp.ClientConfig| gained `workspace_required`.
• You can control priority of |vim.lsp.Config| `root_markers`.
• Support for `textDocument/documentColor`: |lsp-document_color|
https://microsoft.github.io/language-server-protocol/specification/#textDocument_documentColor
• The `textDocument/diagnostic` request now includes the previous id in its
parameters.
• |vim.lsp.enable()| start/stops clients as necessary. And detaches
non-applicable LSP clients.
• |vim.lsp.is_enabled()| checks if a LSP config is enabled (without
"resolving" it).
LUA

View File

@@ -11,15 +11,43 @@ not a clone: compatibility with Vim (especially editor and Vimscript features,
except |Vim9script|) is maintained where possible. See |vim-differences| for
the complete reference.
If you already use Vim, see |nvim-from-vim| for a quickstart. If you just
installed Nvim and have never used it before, watch this 10-minute
video: https://youtu.be/TQn2hJeHQbM .
- If you already use Vim, see |nvim-from-vim| for a quickstart.
- If you have never used Vim or Nvim before, see below.
Type |gO| to see the table of contents.
==============================================================================
What now? *nvim-quickstart*
To learn how to use Vim in 30 minutes, try the tutorial: >vim
:Tutor<Enter>
<
Type |gO| to see the table of contents.
Or watch this 10-minute video: https://youtu.be/TQn2hJeHQbM .
To customize Nvim, you will need a config file. Create your |init.lua| by
copying the "example_init.lua" file: >vim
:exe 'edit' stdpath('config') .. '/init.lua'
:read $VIMRUNTIME/example_init.lua
<
See |lua-guide| for practical notes on using Lua to configure Nvim.
"IDE" features in Nvim are provided by |LSP|.
If you are just trying out Nvim for a few minutes, and want to see the
extremes of what it can do, try one of these popular "extension packs" or
"distributions" (Note: Nvim is not affiliated with these projects, and does
not support them):
- *lazyvim* https://www.lazyvim.org/
- *nvchad* https://nvchad.com/
- *kickstart* https://github.com/nvim-lua/kickstart.nvim
- Not recommended; use `$VIMRUNTIME/example_init.lua` instead.
However, we recommend (eventually) taking time to learn Nvim from its stock
configuration, and incrementally setting options and adding plugins to your
|config| as you discover a need.
==============================================================================
Transitioning from Vim *nvim-from-vim*
@@ -73,29 +101,4 @@ the same Nvim configuration on all of your machines, by creating
source ~/.config/nvim/init.vim
==============================================================================
What next? *nvim-quickstart*
If you want to use Lua to configure Nvim, you can copy an example
configuration to your |init.lua|
>vim
:exe 'edit' stdpath('config') .. '/init.lua'
:read $VIMRUNTIME/example_init.lua
<
See |lua-guide| for practical notes on using Lua to configure Nvim.
"IDE" features in Nvim are provided by Language Server Protocol. See |lsp|
If you are just trying out Nvim for a few minutes, and want to see the
extremes of what it can do, try one of these popular "extension packs" or
"distributions" (Note: Nvim is not affiliated with these projects, and does
not support them):
- *kickstart* https://github.com/nvim-lua/kickstart.nvim
- *lazyvim* https://www.lazyvim.org/
- *nvchad* https://nvchad.com/
However, in general, we recommend (eventually) taking time to learn Nvim from
its stock configuration, and incrementally setting options and adding plugins
to your |config| as you find an explicit need to do so.
vim:tw=78:ts=8:et:ft=help:norl:

View File

@@ -135,7 +135,8 @@ To remove only the "How-to disable mouse" menu item (and its separator): >vim
DEFAULT MAPPINGS
*default-mappings*
Nvim creates the following default mappings at |startup|. You can disable any
of these in your config by simply removing the mapping, e.g. ":unmap Y".
of these in your config by simply removing the mapping, e.g. ":unmap Y". If
you never want any default mappings, call |:mapclear| early in your config.
- Y |Y-default|
- <C-U> |i_CTRL-U-default|

View File

@@ -1669,10 +1669,7 @@ function vim.api.nvim_notify(msg, log_level, opts) end
---
--- ```lua
--- vim.api.nvim_create_user_command('TermHl', function()
--- local b = vim.api.nvim_create_buf(false, true)
--- local chan = vim.api.nvim_open_term(b, {})
--- vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
--- vim.api.nvim_win_set_buf(0, b)
--- vim.api.nvim_open_term(0, {})
--- end, { desc = 'Highlights ANSI termcodes in curbuf' })
--- ```
---

View File

@@ -286,43 +286,35 @@ end
--- implementation re-uses a client if name and root_dir matches.
--- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean
---
--- [lsp-root_dir()]() Directory where the LSP server will base its workspaceFolders, rootUri, and
--- rootPath on initialization. The function form receives a buffer number and `on_dir` callback
--- which it must call to provide root_dir, or LSP will not be activated for the buffer. Thus
--- a `root_dir()` function can dynamically decide per-buffer whether to activate (or skip) LSP. See
--- example at |vim.lsp.enable()|.
--- [lsp-root_dir()]()
--- Decides the workspace root: the directory where the LSP server will base its workspaceFolders,
--- rootUri, and rootPath on initialization. The function form must call the `on_dir` callback to
--- provide the root dir, or LSP will not be activated for the buffer. Thus a `root_dir()` function
--- can dynamically decide per-buffer whether to activate (or skip) LSP.
--- See example at |vim.lsp.enable()|.
--- @field root_dir? string|fun(bufnr: integer, on_dir:fun(root_dir?:string))
---
--- Directory markers (.e.g. '.git/') where the LSP server will base its workspaceFolders,
--- rootUri, and rootPath on initialization. Unused if `root_dir` is provided.
--- [lsp-root_markers]()
--- Filename(s) (".git/", "package.json", …) used to decide the workspace root. Unused if `root_dir`
--- is defined. The list order decides priority. To indicate "equal priority", specify names in
--- a nested list `{ { 'a.txt', 'b.lua' }, ... }`.
---
--- The list order decides the priority. To indicate "equal priority", specify names in a nested list (`{ { 'a', 'b' }, ... }`)
--- Each entry in this list is a set of one or more markers. For each set, Nvim
--- will search upwards for each marker contained in the set. If a marker is
--- found, the directory which contains that marker is used as the root
--- directory. If no markers from the set are found, the process is repeated
--- with the next set in the list.
---
--- Example:
--- For each item, Nvim will search upwards (from the buffer file) for that marker, or list of
--- markers; search stops at the first directory containing that marker, and the directory is used
--- as the root dir (workspace folder).
---
--- Example: Find the first ancestor directory containing file or directory "stylua.toml"; if not
--- found, find the first ancestor containing ".git":
--- ```lua
--- root_markers = { 'stylua.toml', '.git' }
--- ```
---
--- Find the first parent directory containing the file `stylua.toml`. If not
--- found, find the first parent directory containing the file or directory
--- `.git`.
---
--- Example:
---
--- Example: Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
--- not found, find the first ancestor containing ".git":
--- ```lua
--- root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' }
--- ```
---
--- Find the first parent directory containing EITHER `stylua.toml` or
--- `.luarc.json`. If not found, find the first parent directory containing the
--- file or directory `.git`.
---
--- @field root_markers? (string|string[])[]
--- Sets the default configuration for an LSP client (or _all_ clients if the special name "*" is
@@ -587,6 +579,14 @@ end
--- vim.lsp.enable({'luals', 'pyright'})
--- ```
---
--- Example: [lsp-restart]() Passing `false` stops and detaches the client(s). Thus you can
--- "restart" LSP by disabling and re-enabling a given config:
---
--- ```lua
--- vim.lsp.enable('clangd', false)
--- vim.lsp.enable('clangd', true)
--- ```
---
--- Example: To _dynamically_ decide whether LSP is activated, define a |lsp-root_dir()| function
--- which calls `on_dir()` only when you want that config to activate:
---
@@ -603,7 +603,8 @@ end
---@since 13
---
--- @param name string|string[] Name(s) of client(s) to enable.
--- @param enable? boolean `true|nil` to enable, `false` to disable.
--- @param enable? boolean `true|nil` to enable, `false` to disable (actively stops and detaches
--- clients as needed)
function lsp.enable(name, enable)
validate('name', name, { 'string', 'table' })
@@ -648,6 +649,8 @@ end
--- Checks if the given LSP config is enabled (globally, not per-buffer).
---
--- Unlike `vim.lsp.config['…']`, this does not have the side-effect of resolving the config.
---
--- @param name string Config name
--- @return boolean
function lsp.is_enabled(name)

View File

@@ -73,7 +73,7 @@ local validate = vim.validate
--- Daemonize the server process so that it runs in a separate process group from Nvim.
--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave
--- behind orphaned server processes.
--- (default: true)
--- (default: `true`)
--- @field detached? boolean
---
--- A table with flags for the client. The current (experimental) flags are:
@@ -89,7 +89,8 @@ local validate = vim.validate
--- the LSP spec.
--- @field init_options? lsp.LSPObject
---
--- (default: client-id) Name in logs and user messages.
--- Name in logs and user messages.
--- (default: client-id)
--- @field name? string
---
--- Called "position encoding" in LSP spec. The encoding that the LSP server expects, used for
@@ -132,9 +133,10 @@ local validate = vim.validate
--- supports workspace folders but none are configured. See `workspaceFolders` in LSP spec.
--- @field workspace_folders? lsp.WorkspaceFolder[]
---
--- (default false) Server requires a workspace (no "single file" support). Note: Without
--- Server requires a workspace (no "single file" support). Note: Without
--- a workspace, cross-file features (navigation, hover) may or may not work depending on the
--- language server, even if the server doesn't require a workspace.
--- (default: `false`)
--- @field workspace_required? boolean
--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}>

View File

@@ -991,10 +991,7 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
///
/// ```lua
/// vim.api.nvim_create_user_command('TermHl', function()
/// local b = vim.api.nvim_create_buf(false, true)
/// local chan = vim.api.nvim_open_term(b, {})
/// vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
/// vim.api.nvim_win_set_buf(0, b)
/// vim.api.nvim_open_term(0, {})
/// end, { desc = 'Highlights ANSI termcodes in curbuf' })
/// ```
///

View File

@@ -6677,7 +6677,7 @@ describe('LSP', function()
end)
end)
it('correctly handles root_markers', function()
it('root_markers priority', function()
--- Setup directories for testing
-- root/
-- ├── dir_a/