commit 52a4bc45488cb1f626b02be5512cd0301cd48cb8
parent 82b844fefef5f0024d9ae02ebff1153ca3e9127a
Author: Justin M. Keyes <justinkz@gmail.com>
Date: Sun, 27 Apr 2025 13:40:46 -0700
docs: lsp, emoji, startup #33446
Co-authored-by: Maria José Solano <majosolano99@gmail.com>
Diffstat:
17 files changed, 225 insertions(+), 124 deletions(-)
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
@@ -287,38 +287,33 @@ They are also listed below.
- `'callHierarchy/incomingCalls'`
- `'callHierarchy/outgoingCalls'`
-- `'textDocument/codeAction'`
+- `'client/registerCapability'`
+- `'client/unregisterCapability'`
+- `'signature_help'`
+- `'textDocument/codeLens'`
- `'textDocument/completion'`
-- `'textDocument/declaration'`
-- `'textDocument/definition'`
- `'textDocument/diagnostic'`
- `'textDocument/documentHighlight'`
- `'textDocument/documentSymbol'`
-- `'textDocument/foldingRange'`
- `'textDocument/formatting'`
- `'textDocument/hover'`
-- `'textDocument/implementation'`
- `'textDocument/inlayHint'`
-- `'textDocument/prepareTypeHierarchy'`
- `'textDocument/publishDiagnostics'`
- `'textDocument/rangeFormatting'`
-- `'textDocument/rangesFormatting'`
-- `'textDocument/references'`
- `'textDocument/rename'`
-- `'textDocument/semanticTokens/full'`
-- `'textDocument/semanticTokens/full/delta'`
- `'textDocument/signatureHelp'`
-- `'textDocument/typeDefinition*'`
- `'typeHierarchy/subtypes'`
- `'typeHierarchy/supertypes'`
- `'window/logMessage'`
-- `'window/showMessage'`
- `'window/showDocument'`
+- `'window/showMessage'`
- `'window/showMessageRequest'`
+- `'window/workDoneProgress/create'`
- `'workspace/applyEdit'`
- `'workspace/configuration'`
- `'workspace/executeCommand'`
- `'workspace/inlayHint/refresh'`
+- `'workspace/semanticTokens/refresh'`
- `'workspace/symbol'`
- `'workspace/workspaceFolders'`
@@ -553,10 +548,19 @@ LspAttach *LspAttach*
|autocmd-pattern| is the buffer name. The client ID is passed in the
Lua handler |event-data| argument.
+ Example: >lua
+ vim.api.nvim_create_autocmd('LspAttach', {
+ callback = function(ev)
+ local client = vim.lsp.get_client_by_id(ev.data.client_id)
+ -- ...
+ end
+ })
+<
Note: If the LSP server performs dynamic registration, capabilities may be
registered any time _after_ LspAttach. In that case you may want to handle
- the "registerCapability" event. Example: >lua
+ the "registerCapability" event.
+ Example: >lua
vim.lsp.handlers['client/registerCapability'] = (function(overridden)
return function(err, res, ctx)
local result = overridden(err, res, ctx)
@@ -573,8 +577,9 @@ LspAttach *LspAttach*
LspDetach *LspDetach*
Just before an LSP client detaches from a buffer. The |autocmd-pattern| is
the buffer name. The client ID is passed in the Lua handler |event-data|
- argument. Example: >lua
+ argument.
+ Example: >lua
vim.api.nvim_create_autocmd('LspDetach', {
callback = function(args)
-- Get the detaching client
@@ -596,8 +601,9 @@ LspNotify *LspNotify*
LSP server.
The client_id, LSP method, and parameters are sent in the Lua handler
- |event-data| table argument. Example: >lua
+ |event-data| table argument.
+ Example: >lua
vim.api.nvim_create_autocmd('LspNotify', {
callback = function(args)
local bufnr = args.buf
@@ -643,8 +649,9 @@ LspRequest *LspRequest*
The Lua handler |event-data| argument has the client ID, request ID, and
request (described at |vim.lsp.Client|, {requests} field). If the request
type is `complete`, the request will be deleted from the client's pending
- requests table after processing the event handlers. Example: >lua
+ requests table after processing the event handlers.
+ Example: >lua
vim.api.nvim_create_autocmd('LspRequest', {
callback = function(args)
local bufnr = args.buf
@@ -671,8 +678,9 @@ LspTokenUpdate *LspTokenUpdate*
when an existing token becomes visible for the first time. The
|autocmd-pattern| is the buffer name. The Lua handler |event-data|
argument has the client ID and token (see
- |vim.lsp.semantic_tokens.get_at_pos()|). Example: >lua
+ |vim.lsp.semantic_tokens.get_at_pos()|).
+ Example: >lua
vim.api.nvim_create_autocmd('LspTokenUpdate', {
callback = function(args)
local token = args.data.token
@@ -704,14 +712,16 @@ Lua module: vim.lsp *lsp-core*
the LSP server will base its workspaceFolders,
rootUri, and rootPath on initialization. Unused if
`root_dir` is provided.
- • {root_dir}? (`string|fun(bufnr: integer, cb:fun(root_dir?:string))`)
- Directory where the LSP server will base its
- workspaceFolders, rootUri, and rootPath on
- initialization. If a function, it is passed the
- buffer number and a callback argument which must be
- called with the value of root_dir to use. The LSP
- server will not be started until the callback is
- called.
+ • {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 must be called to
+ provide root_dir as a string. LSP will not be
+ activated for the buffer unless `on_dir` is called;
+ thus a `root_dir()` function can dynamically decide
+ whether to activate (or skip) LSP per-buffer. See
+ example at |vim.lsp.enable()|.
• {reuse_client}? (`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`)
Predicate used to decide if a client should be
re-used. Used on all running clients. The default
@@ -907,14 +917,24 @@ config({name}, {cfg}) *vim.lsp.config()*
• {cfg} (`vim.lsp.Config`) See |vim.lsp.Config|.
enable({name}, {enable}) *vim.lsp.enable()*
- Enable an LSP server to automatically start when opening a buffer.
-
- Uses configuration defined with `vim.lsp.config`.
+ Auto-starts LSP when a buffer is opened, based on the |lsp-config|
+ `filetypes`, `root_markers`, and `root_dir` fields.
Examples: >lua
- vim.lsp.enable('clangd')
+ vim.lsp.enable('clangd')
+ vim.lsp.enable({'luals', 'pyright'})
+<
- vim.lsp.enable({'luals', 'pyright'})
+ 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
+ vim.lsp.config('lua_ls', {
+ root_dir = function(bufnr, on_dir)
+ if not vim.fn.bufname(bufnr):match('%.txt$') then
+ on_dir(vim.fn.getcwd())
+ end
+ end
+ })
<
Attributes: ~
@@ -1316,7 +1336,11 @@ Lua module: vim.lsp.client *lsp-client*
in this list. See `workspaceFolders` in the LSP
spec.
• {workspace_required}? (`boolean`) (default false) Server requires a
- workspace (no "single file" support).
+ 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.
• {capabilities}? (`lsp.ClientCapabilities`) Map overriding the
default capabilities defined by
|vim.lsp.protocol.make_client_capabilities()|,
@@ -1592,7 +1616,8 @@ clear_references() *vim.lsp.buf.clear_references()*
Removes document highlights from current buffer.
code_action({opts}) *vim.lsp.buf.code_action()*
- Selects a code action available at the current cursor position.
+ Selects a code action (LSP: "textDocument/codeAction" request) available
+ at cursor position.
Parameters: ~
• {opts} (`table?`) A table with the following fields:
@@ -2575,6 +2600,27 @@ symbols_to_items({symbols}, {bufnr}, {position_encoding})
==============================================================================
Lua module: vim.lsp.log *lsp-log*
+The `vim.lsp.log` module provides logging for the Nvim LSP client.
+
+When debugging language servers, it is helpful to enable extra-verbose logging
+of the LSP client RPC events. Example: >lua
+ vim.lsp.set_log_level 'trace'
+ require('vim.lsp.log').set_format_func(vim.inspect)
+<
+
+Then try to run the language server, and open the log with: >vim
+ :lua vim.cmd('tabnew ' .. vim.lsp.get_log_path())
+<
+
+(Or use `:LspLog` if you have nvim-lspconfig installed.)
+
+Note:
+• Remember to DISABLE verbose logging ("debug" or "trace" level), else you may
+ encounter performance issues.
+• "ERROR" messages containing "stderr" only indicate that the log was sent to
+ stderr. Many servers send harmless messages via stderr.
+
+
get_filename() *vim.lsp.log.get_filename()*
Returns the log filename.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
@@ -2900,7 +2900,7 @@ Use |uv.fs_stat()| to check a file's type, and whether it exists.
Example: >lua
if vim.uv.fs_stat(file) then
- vim.print("file exists")
+ vim.print('file exists')
end
<
@@ -2955,7 +2955,8 @@ vim.fs.dir({path}, {opts}) *vim.fs.dir()*
"fifo", "socket", "char", "block", "unknown".
vim.fs.dirname({file}) *vim.fs.dirname()*
- Return the parent directory of the given path
+ Gets the parent directory of the given path (not expanded/resolved, the
+ caller must do that).
Attributes: ~
Since: 0.8.0
@@ -2980,16 +2981,17 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
narrow the search to find only that type.
Examples: >lua
- -- list all test directories under the runtime directory
- local test_dirs = vim.fs.find(
- {'test', 'tst', 'testdir'},
- {limit = math.huge, type = 'directory', path = './runtime/'}
+ -- List all test directories under the runtime directory.
+ local dirs = vim.fs.find(
+ { 'test', 'tst', 'testdir' },
+ { limit = math.huge, type = 'directory', path = './runtime/' }
)
- -- get all files ending with .cpp or .hpp inside lib/
- local cpp_hpp = vim.fs.find(function(name, path)
+ -- Get all "lib/*.cpp" and "lib/*.hpp" files, using Lua patterns.
+ -- Or use `vim.glob.to_lpeg(…):match(…)` for glob/wildcard matching.
+ local files = vim.fs.find(function(name, path)
return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$')
- end, {limit = math.huge, type = 'file'})
+ end, { limit = math.huge, type = 'file' })
<
Attributes: ~
@@ -3089,19 +3091,20 @@ vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
(`string`) Normalized path
vim.fs.parents({start}) *vim.fs.parents()*
- Iterate over all the parents of the given path.
+ Iterate over all the parents of the given path (not expanded/resolved, the
+ caller must do that).
Example: >lua
local root_dir
for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do
- if vim.fn.isdirectory(dir .. "/.git") == 1 then
+ if vim.fn.isdirectory(dir .. '/.git') == 1 then
root_dir = dir
break
end
end
if root_dir then
- print("Found git repository at", root_dir)
+ print('Found git repository at', root_dir)
end
<
diff --git a/runtime/doc/luaref.txt b/runtime/doc/luaref.txt
@@ -4150,7 +4150,7 @@ string.upper({s}) *string.upper()*
locale.
------------------------------------------------------------------------------
-5.4.1 Patterns *lua-patterns*
+5.4.1 Patterns *lua-pattern* *lua-patterns*
A character class is used to represent a set of characters. The following
combinations are allowed in describing a character class:
@@ -4207,6 +4207,7 @@ A pattern item may be
- a single character class followed by `+`, which matches 1 or more
repetitions of characters in the class. These repetition items will
always match the longest possible sequence;
+ *lua-nongreedy*
- a single character class followed by `-`, which also matches 0 or
more repetitions of characters in the class. Unlike `*`, these
repetition items will always match the shortest possible sequence;
@@ -4221,7 +4222,7 @@ A pattern item may be
`y` where the count reaches 0. For instance, the item `%b()` matches
expressions with balanced parentheses.
-PATTERN *lua-pattern*
+PATTERN
A pattern is a sequence of pattern items. A `^` at the beginning of a pattern
anchors the match at the beginning of the subject string. A `$` at the end of
diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt
@@ -19,12 +19,7 @@ For changing the language of messages and menus see |mlang.txt|.
==============================================================================
Getting started *mbyte-first*
-This is a summary of the multibyte features in Vim. If you are lucky it works
-as described and you can start using Vim without much trouble. If something
-doesn't work you will have to read the rest. Don't be surprised if it takes
-quite a bit of work and experimenting to make Vim use all the multibyte
-features. Unfortunately, every system has its own way to deal with multibyte
-languages and it is quite complicated.
+This is a summary of the multibyte features in Nvim.
LOCALE
@@ -54,14 +49,14 @@ See |mbyte-locale| for details.
ENCODING
-Nvim always uses UTF-8 internally. Thus 'encoding' option is always set
-to "utf-8" and cannot be changed.
+Nvim always uses UTF-8 internally. Thus 'encoding' is always set to "utf-8"
+and cannot be changed.
All the text that is used inside Vim will be in UTF-8. Not only the text in
the buffers, but also in registers, variables, etc.
-You can edit files in different encodings than UTF-8. Nvim
-will convert the file when you read it and convert it back when you write it.
+You can edit files in different encodings than UTF-8. Nvim will convert the
+file when you read it and convert it back when you write it.
See 'fileencoding', 'fileencodings' and |++enc|.
@@ -184,9 +179,9 @@ You could make a small shell script for this.
==============================================================================
Encoding *mbyte-encoding*
-In Nvim UTF-8 is always used internally to encode characters.
- This applies to all the places where text is used, including buffers (files
- loaded into memory), registers and variables.
+UTF-8 is always used internally to encode characters. This applies to all the
+places where text is used, including buffers (files loaded into memory),
+registers and variables.
*charset* *codeset*
Charset is another name for encoding. There are subtle differences, but these
@@ -609,25 +604,25 @@ Combining forms:
Using UTF-8 *mbyte-utf8* *UTF-8* *utf-8* *utf8*
*Unicode* *unicode*
The Unicode character set was designed to include all characters from other
-character sets. Therefore it is possible to write text in any language using
-Unicode (with a few rarely used languages excluded). And it's mostly possible
-to mix these languages in one file, which is impossible with other encodings.
+character sets. Therefore it is possible to write text in (almost) any
+language using Unicode. And it's mostly possible to mix these languages in
+one file, which is impossible with other encodings.
Unicode can be encoded in several ways. The most popular one is UTF-8, which
uses one or more bytes for each character and is backwards compatible with
-ASCII. On MS-Windows UTF-16 is also used (previously UCS-2), which uses
-16-bit words. Vim can support all of these encodings, but always uses UTF-8
+ASCII. On MS-Windows UTF-16 is also used (previously UCS-2), which uses
+16-bit words. Nvim supports all of these encodings, but always uses UTF-8
internally.
-Vim has comprehensive UTF-8 support. It works well in:
-- xterm with UTF-8 support enabled
-- MS-Windows GUI
-- several other platforms
-
-Double-width characters are supported. Works best with 'guifontwide'. When
+Nvim supports double-width characters; works best with 'guifontwide'. When
using only 'guifont' the wide characters are drawn in the normal width and
a space to fill the gap.
+EMOJI *emoji*
+
+You can list emoji characters using this script: >vim
+ :source $VIMRUNTIME/scripts/emoji_list.lua
+<
*bom-bytes*
When reading a file a BOM (Byte Order Mark) can be used to recognize the
Unicode encoding:
@@ -698,7 +693,7 @@ You need to specify a font to be used. For double-wide characters another
font is required, which is exactly twice as wide. There are three ways to do
this:
-1. Set 'guifont' and let Vim find a matching 'guifontwide'
+1. Set 'guifont' and let Nvim find a matching 'guifontwide'
2. Set 'guifont' and 'guifontwide'
See the documentation for each option for details. Example: >
@@ -730,7 +725,7 @@ COMMAND ARGUMENTS *utf-8-char-arg*
Commands like |f|, |F|, |t| and |r| take an argument of one character. For
UTF-8 this argument may include one or two composing characters. These need
-to be produced together with the base character, Vim doesn't wait for the next
+to be produced together with the base character, Nvim doesn't wait for the next
character to be typed to find out if it is a composing character or not.
Using 'keymap' or |:lmap| is a nice way to type these characters.
@@ -741,7 +736,6 @@ searching for a character with a composing character, this will only find
matches with that composing character. It was implemented this way, because
not everybody is able to type a composing character.
-
==============================================================================
Overview of options *mbyte-options*
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -109,7 +109,8 @@ API
DEFAULTS
-• todo
+• 'statusline' default is exposed as a statusline expression (previously it
+ was implemented as an internal C routine).
DIAGNOSTICS
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
@@ -2420,6 +2420,12 @@ A jump table for the options with a short description can be found at |Q_op|.
- 'exrc' can execute any code; editorconfig only specifies settings.
- 'exrc' is Nvim-specific; editorconfig works in other editors.
+ To achieve project-local LSP configuration:
+ 1. Enable 'exrc'.
+ 2. Place LSP configs at ".nvim/lsp/*.lua" in your project root.
+ 3. Create ".nvim.lua" in your project root directory with this line: >lua
+ vim.cmd[[set runtimepath+=.nvim]]
+<
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -6033,8 +6039,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'statusline'* *'stl'* *E540* *E542*
'statusline' 'stl' string (default "%<%f %h%w%m%r %=%{% &showcmdloc == 'statusline' ? '%-10.S ' : '' %}%{% exists('b:keymap_name') ? '<'..b:keymap_name..'> ' : '' %}%{% &ruler ? ( &rulerformat == '' ? '%-14.(%l,%c%V%) %P' : &rulerformat ) : '' %}")
global or local to window |global-local|
- When non-empty, this option determines the content of the status line.
- Also see |status-line|.
+ Sets the |status-line|.
The option consists of printf style '%' items interspersed with
normal text. Each status line item is of the form:
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
@@ -1382,8 +1382,8 @@ The $XDG_CONFIG_HOME, $XDG_DATA_HOME, $XDG_RUNTIME_DIR, $XDG_STATE_HOME,
$XDG_CACHE_HOME, $XDG_CONFIG_DIRS and $XDG_DATA_DIRS environment variables
are used if defined, else default values (listed below) are used.
-Throughout the help pages these defaults are used as placeholders, e.g.
-"~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config".
+Note: In the help these defaults are used as placeholders, e.g. "~/.config" is
+understood as "$XDG_CONFIG_HOME or ~/.config".
CONFIG DIRECTORY (DEFAULT) ~
*$XDG_CONFIG_HOME* Nvim: stdpath("config")
@@ -1437,12 +1437,17 @@ configuration files in `$XDG_CONFIG_HOME/foo` instead of
`$XDG_CONFIG_HOME/nvim`. `$NVIM_APPNAME` must be a name, such as "foo", or a
relative path, such as "foo/bar".
+Note: In the help wherever `$XDG_CONFIG_…/nvim` is mentioned it is understood
+as `$XDG_CONFIG_…/$NVIM_APPNAME`.
+
+ *state-isolation*
One use-case for $NVIM_APPNAME is to "isolate" Nvim applications.
Alternatively, for true isolation, on Linux you can use cgroups namespaces: >
systemd-run --user -qt -p PrivateUsers=yes -p BindPaths=/home/user/profile_xy:/home/user/.config/nvim nvim
-
-Note: Throughout the help pages, wherever `$XDG_CONFIG_…/nvim` is mentioned it
-is understood to mean `$XDG_CONFIG_…/$NVIM_APPNAME`.
+<
+ *stateless*
+To run Nvim without creating any directories or data files: >
+ NVIM_LOG_FILE=/dev/null nvim -n -i NONE
LOG FILE *log* *$NVIM_LOG_FILE* *E5430*
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
@@ -384,6 +384,7 @@ Options:
- 'showcmdloc' cannot be set to empty.
- 'signcolumn' can show multiple signs (dynamic or fixed columns)
- 'statuscolumn' full control of columns using 'statusline' format
+- 'statusline' default is exposed as a statusline expression.
- 'splitkeep' cannot be set to empty.
- 'tabline' middle-click on tabpage label closes tabpage,
and %@Func@foo%X can call any function on mouse-click
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
@@ -2084,6 +2084,15 @@ vim.bo.et = vim.bo.expandtab
--- - 'exrc' can execute any code; editorconfig only specifies settings.
--- - 'exrc' is Nvim-specific; editorconfig works in other editors.
---
+--- To achieve project-local LSP configuration:
+--- 1. Enable 'exrc'.
+--- 2. Place LSP configs at ".nvim/lsp/*.lua" in your project root.
+--- 3. Create ".nvim.lua" in your project root directory with this line:
+---
+--- ```lua
+--- vim.cmd[[set runtimepath+=.nvim]]
+--- ```
+---
--- This option cannot be set from a `modeline` or in the `sandbox`, for
--- security reasons.
---
@@ -6442,8 +6451,7 @@ vim.o.stc = vim.o.statuscolumn
vim.wo.statuscolumn = vim.o.statuscolumn
vim.wo.stc = vim.wo.statuscolumn
---- When non-empty, this option determines the content of the status line.
---- Also see `status-line`.
+--- Sets the `status-line`.
---
--- The option consists of printf style '%' items interspersed with
--- normal text. Each status line item is of the form:
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
@@ -6,7 +6,7 @@
---
--- >lua
--- if vim.uv.fs_stat(file) then
---- vim.print("file exists")
+--- vim.print('file exists')
--- end
--- <
@@ -19,21 +19,21 @@ local sysname = uv.os_uname().sysname:lower()
local iswin = not not (sysname:find('windows') or sysname:find('mingw'))
local os_sep = iswin and '\\' or '/'
---- Iterate over all the parents of the given path.
+--- Iterate over all the parents of the given path (not expanded/resolved, the caller must do that).
---
--- Example:
---
--- ```lua
--- local root_dir
--- for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do
---- if vim.fn.isdirectory(dir .. "/.git") == 1 then
+--- if vim.fn.isdirectory(dir .. '/.git') == 1 then
--- root_dir = dir
--- break
--- end
--- end
---
--- if root_dir then
---- print("Found git repository at", root_dir)
+--- print('Found git repository at', root_dir)
--- end
--- ```
---
@@ -55,7 +55,7 @@ function M.parents(start)
start
end
---- Return the parent directory of the given path
+--- Gets the parent directory of the given path (not expanded/resolved, the caller must do that).
---
---@since 10
---@generic T : string|nil
@@ -234,16 +234,17 @@ end
--- Examples:
---
--- ```lua
---- -- list all test directories under the runtime directory
---- local test_dirs = vim.fs.find(
---- {'test', 'tst', 'testdir'},
---- {limit = math.huge, type = 'directory', path = './runtime/'}
+--- -- List all test directories under the runtime directory.
+--- local dirs = vim.fs.find(
+--- { 'test', 'tst', 'testdir' },
+--- { limit = math.huge, type = 'directory', path = './runtime/' }
--- )
---
---- -- get all files ending with .cpp or .hpp inside lib/
---- local cpp_hpp = vim.fs.find(function(name, path)
+--- -- Get all "lib/*.cpp" and "lib/*.hpp" files, using Lua patterns.
+--- -- Or use `vim.glob.to_lpeg(…):match(…)` for glob/wildcard matching.
+--- local files = vim.fs.find(function(name, path)
--- return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$')
---- end, {limit = math.huge, type = 'file'})
+--- end, { limit = math.huge, type = 'file' })
--- ```
---
---@since 10
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
@@ -282,15 +282,16 @@ end
--- If not provided, then the client will attach to all filetypes.
--- @field filetypes? 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.
+--- Directory markers (.e.g. '.git/') where the LSP server will base its workspaceFolders, rootUri,
+--- and rootPath on initialization. Unused if `root_dir` is provided.
--- @field root_markers? string[]
---
---- Directory where the LSP server will base its workspaceFolders, rootUri, and
---- rootPath on initialization. If a function, it is passed the buffer number
---- and a callback argument which must be called with the value of root_dir to
---- use. The LSP server will not be started until the callback is called.
---- @field root_dir? string|fun(bufnr: integer, cb: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 must be called to provide root_dir as a string. LSP will not be activated for the buffer
+--- unless `on_dir` is called; thus a `root_dir()` function can dynamically decide whether to
+--- activate (or skip) LSP per-buffer. See example at |vim.lsp.enable()|.
+--- @field root_dir? string|fun(bufnr: integer, on_dir:fun(root_dir?:string))
---
--- Predicate used to decide if a client should be re-used. Used on all
--- running clients. The default implementation re-uses a client if name and
@@ -538,16 +539,27 @@ local function lsp_enable_callback(bufnr)
end
end
---- Enable an LSP server to automatically start when opening a buffer.
----
---- Uses configuration defined with `vim.lsp.config`.
+--- Auto-starts LSP when a buffer is opened, based on the |lsp-config| `filetypes`, `root_markers`,
+--- and `root_dir` fields.
---
--- Examples:
---
--- ```lua
---- vim.lsp.enable('clangd')
+--- vim.lsp.enable('clangd')
+--- vim.lsp.enable({'luals', 'pyright'})
+--- ```
+---
+--- 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:
---
---- vim.lsp.enable({'luals', 'pyright'})
+--- ```lua
+--- vim.lsp.config('lua_ls', {
+--- root_dir = function(bufnr, on_dir)
+--- if not vim.fn.bufname(bufnr):match('%.txt$') then
+--- on_dir(vim.fn.getcwd())
+--- end
+--- end
+--- })
--- ```
---
---@since 13
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
@@ -1211,8 +1211,7 @@ local function on_code_action_results(results, opts)
vim.ui.select(actions, select_opts, on_user_choice)
end
---- Selects a code action available at the current
---- cursor position.
+--- Selects a code action (LSP: "textDocument/codeAction" request) available at cursor position.
---
---@param opts? vim.lsp.buf.code_action.Opts
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
@@ -63,7 +63,9 @@ local validate = vim.validate
--- folder in this list. See `workspaceFolders` in the LSP spec.
--- @field workspace_folders? lsp.WorkspaceFolder[]
---
---- (default false) Server requires a workspace (no "single file" support).
+--- (default false) 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.
--- @field workspace_required? boolean
---
--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|,
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
@@ -1,4 +1,25 @@
--- Logger for language client plugin.
+--- @brief
+--- The `vim.lsp.log` module provides logging for the Nvim LSP client.
+---
+--- When debugging language servers, it is helpful to enable extra-verbose logging of the LSP client
+--- RPC events. Example:
+--- ```lua
+--- vim.lsp.set_log_level 'trace'
+--- require('vim.lsp.log').set_format_func(vim.inspect)
+--- ```
+---
+--- Then try to run the language server, and open the log with:
+--- ```vim
+--- :lua vim.cmd('tabnew ' .. vim.lsp.get_log_path())
+--- ```
+---
+--- (Or use `:LspLog` if you have nvim-lspconfig installed.)
+---
+--- Note:
+--- - Remember to DISABLE verbose logging ("debug" or "trace" level), else you may encounter
+--- performance issues.
+--- - "ERROR" messages containing "stderr" only indicate that the log was sent to stderr. Many
+--- servers send harmless messages via stderr.
local log = {}
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
@@ -2753,6 +2753,12 @@ local options = {
- 'exrc' can execute any code; editorconfig only specifies settings.
- 'exrc' is Nvim-specific; editorconfig works in other editors.
+ To achieve project-local LSP configuration:
+ 1. Enable 'exrc'.
+ 2. Place LSP configs at ".nvim/lsp/*.lua" in your project root.
+ 3. Create ".nvim.lua" in your project root directory with this line: >lua
+ vim.cmd[[set runtimepath+=.nvim]]
+ <
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
]=],
@@ -8550,8 +8556,7 @@ local options = {
"%{% &ruler ? ( &rulerformat == '' ? '%-14.(%l,%c%V%) %P' : &rulerformat ) : '' %}",
}),
desc = [=[
- When non-empty, this option determines the content of the status line.
- Also see |status-line|.
+ Sets the |status-line|.
The option consists of printf style '%' items interspersed with
normal text. Each status line item is of the form:
diff --git a/test/functional/core/env_spec.lua b/test/functional/core/env_spec.lua
@@ -3,25 +3,22 @@ local n = require('test.functional.testnvim')()
local eq = t.eq
local clear = n.clear
-local exec_capture = n.exec_capture
local command = n.command
-describe('vim.uv', function()
+describe('env', function()
before_each(function()
clear()
end)
- -- Subsequential env var assignment consistency
- -- see: issue 32550
- it('vim.uv.os_setenv(), vim.uv.os_unsetenv() consistency', function()
- eq('', exec_capture('echo $FOO'))
+ it('vim.uv.os_setenv(), vim.uv.os_unsetenv() consistency #32550', function()
+ eq('', n.eval('$FOO'))
command('lua vim.uv.os_setenv("FOO", "bar")')
- eq('bar', exec_capture('echo $FOO'))
+ eq('bar', n.eval('$FOO'))
command('lua vim.uv.os_setenv("FOO", "fizz")')
- eq('fizz', exec_capture('echo $FOO'))
+ eq('fizz', n.eval('$FOO'))
command('lua vim.uv.os_unsetenv("FOO")')
- eq('', exec_capture('echo $FOO'))
+ eq('', n.eval('$FOO'))
command('lua vim.uv.os_setenv("FOO", "buzz")')
- eq('buzz', exec_capture('echo $FOO'))
+ eq('buzz', n.eval('$FOO'))
end)
end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
@@ -8021,7 +8021,7 @@ describe('float window', function()
]])
end
- -- Test for \u2800 (braille blank unicode character)
+ -- Treat for \u2800 (braille blank) as whitespace.
local braille_blank = "\226\160\128"
api.nvim_buf_set_lines(buf, 0, -1, true, {"test" .. braille_blank, "", "popup"..braille_blank.." text"})
if multigrid then