diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 1b922ee67b..4dfd7d0e7c 100644 --- 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 index 2dcf915428..f869181d1e 100644 --- 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 index ffcd537d7b..5c617f7b0d 100644 --- 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 index 47fd4f3343..3f7c53ee9c 100644 --- 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 index 9c88e3885e..a69520b8e2 100644 --- 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 index 6779c867ce..584382d9f1 100644 --- 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 index 2e4781f0e6..d5104efa86 100644 --- 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 index 7ffb505528..5ddcc7008b 100644 --- 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 index 1e0e40a3a3..b06334ba31 100644 --- 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 index 8862afc760..1a99627347 100644 --- 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 index a117217f17..55a5ab6cf4 100644 --- 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'}) +--- ``` --- ---- 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 +--- }) --- ``` --- ---@since 13 diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index e6ffc8360e..aac9965f42 100644 --- 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 index a362287570..cd78bab3e8 100644 --- 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 index e28a856215..2dccd86ecd 100644 --- 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 index 624e4166a9..d76327ffcd 100644 --- 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 index 4d5409248b..6aa0e6fb6a 100644 --- 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 index bd4f868032..d372148f35 100644 --- 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