diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/autoload/provider/clipboard.vim | 2 | ||||
-rw-r--r-- | runtime/doc/api.txt | 13 | ||||
-rw-r--r-- | runtime/doc/builtin.txt | 9 | ||||
-rw-r--r-- | runtime/doc/deprecated.txt | 1 | ||||
-rw-r--r-- | runtime/doc/dev_arch.txt | 10 | ||||
-rw-r--r-- | runtime/doc/develop.txt | 8 | ||||
-rw-r--r-- | runtime/doc/gui.txt | 3 | ||||
-rw-r--r-- | runtime/doc/intro.txt | 24 | ||||
-rw-r--r-- | runtime/doc/lsp.txt | 36 | ||||
-rw-r--r-- | runtime/doc/lua.txt | 6 | ||||
-rw-r--r-- | runtime/doc/map.txt | 2 | ||||
-rw-r--r-- | runtime/doc/nvim.txt | 36 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 2 | ||||
-rw-r--r-- | runtime/doc/various.txt | 3 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 5 | ||||
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 3 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api.lua | 14 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 13 | ||||
-rw-r--r-- | runtime/lua/vim/_system.lua | 126 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 208 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 2 |
23 files changed, 307 insertions, 229 deletions
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 58d3d4550f..848fa401f1 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -158,7 +158,7 @@ function! provider#clipboard#Executable() abort let s:copy['*'] = s:copy['+'] let s:paste['*'] = s:paste['+'] return 'termux-clipboard' - elseif !empty($TMUX) && executable('tmux') + elseif executable('tmux') && (!empty($TMUX) || 0 == jobwait([jobstart(['tmux', 'list-buffers'])], 2000)[0]) let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V'])) if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0]) let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-'] diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index c5dabeb551..9cb8f72348 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -1114,7 +1114,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()* Open a terminal instance in a buffer By default (and currently the only option) the terminal will not be - connected to an external process. Instead, input send on the channel will + connected to an external process. Instead, input sent on the channel will be echoed directly by the terminal. This is useful to display ANSI terminal sequences returned as part of a rpc message, or similar. @@ -1125,6 +1125,17 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()* |nvim_chan_send()| can be called immediately to process sequences in a virtual terminal having the intended size. + Example: this `TermHl` command can be used to display and highlight raw + ANSI termcodes, so you can use Nvim as a "scrollback pager" (for terminals + like kitty): *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) + end, { desc = 'Highlights ANSI termcodes in curbuf' }) +< + Attributes: ~ not allowed when |textlock| is active diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 585db21a0b..304e63fd95 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -5443,7 +5443,7 @@ jobwait({jobs} [, {timeout}]) *jobwait()* • {timeout} (`integer?`) Return: ~ - (`any`) + (`integer[]`) join({list} [, {sep}]) *join()* Join the items in {list} together into one String. @@ -7986,7 +7986,7 @@ rpcnotify({channel}, {event} [, {args}...]) *rpcnotify()* Parameters: ~ • {channel} (`integer`) • {event} (`string`) - • {args} (`any?`) + • {...} (`any`) Return: ~ (`any`) @@ -8001,7 +8001,7 @@ rpcrequest({channel}, {method} [, {args}...]) *rpcrequest()* Parameters: ~ • {channel} (`integer`) • {method} (`string`) - • {args} (`any?`) + • {...} (`any`) Return: ~ (`any`) @@ -10234,6 +10234,7 @@ str2list({string} [, {utf8}]) *str2list()* and exists only for backwards-compatibility. With UTF-8 composing characters are handled properly: >vim echo str2list("á") " returns [97, 769] +< Parameters: ~ • {string} (`string`) @@ -11991,7 +11992,7 @@ winlayout([{tabnr}]) *winlayout()* • {tabnr} (`integer?`) Return: ~ - (`any`) + (`any[]`) winline() *winline()* The result is a Number, which is the screen line of the cursor diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index c6ca5e5ce9..ab9c0b2ce8 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -64,6 +64,7 @@ LSP • `client.is_stopped()` Use |Client:is_stopped()| instead. • `client.supports_method()` Use |Client:supports_method()| instead. • `client.on_attach()` Use |Client:on_attach()| instead. +• `vim.lsp.start_client()` Use |vim.lsp.start()| instead. ------------------------------------------------------------------------------ DEPRECATED IN 0.10 *deprecated-0.10* diff --git a/runtime/doc/dev_arch.txt b/runtime/doc/dev_arch.txt index 1cb3b9ad67..2be6221117 100644 --- a/runtime/doc/dev_arch.txt +++ b/runtime/doc/dev_arch.txt @@ -46,11 +46,11 @@ Remember to bump NVIM_API_LEVEL if it wasn't already during this development cycle. Other references: -* |msgpack-rpc| -* |ui| -* https://github.com/neovim/neovim/pull/3246 -* https://github.com/neovim/neovim/pull/18375 -* https://github.com/neovim/neovim/pull/21605 +- |msgpack-rpc| +- |ui| +- https://github.com/neovim/neovim/pull/3246 +- https://github.com/neovim/neovim/pull/18375 +- https://github.com/neovim/neovim/pull/21605 diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index a61c569a67..da64475465 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -300,7 +300,7 @@ vim.paste in runtime/lua/vim/_editor.lua like this: > --- @returns false if client should cancel the paste. -LUA STDLIB DESIGN GUIDELINES *dev-lua* +STDLIB DESIGN GUIDELINES *dev-lua* See also |dev-naming|. @@ -337,7 +337,7 @@ preference): way. Advantage is that propagation happens for free and it's harder to accidentally swallow errors. (E.g. using `uv_handle/pipe:write()` without checking return values is common.) -4. `on_error` parameter +4. `on_error` callback - For async and "visitors" traversing a graph, where many errors may be collected while work continues. 5. `vim.notify` (sometimes with optional `opts.silent` (async, visitors ^)) @@ -434,7 +434,9 @@ Use existing common {verb} names (actions) if possible: - eval: Evaluates an expression - exec: Executes code, may return a result - fmt: Formats - - get: Gets things (often by a query) + - get: Gets things. Two variants (overloads): + 1. `get<T>(id: int): T` returns one item. + 2. `get<T>(filter: dict): T[]` returns a list. - inspect: Presents a high-level, often interactive, view - is_enabled: Checks if functionality is enabled. - open: Opens something (a buffer, window, …) diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 21f1ba8241..85a0df03f9 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -20,8 +20,9 @@ features, whereas help tags with the "ui-" prefix refer to the |ui-protocol|. Nvim provides a default, builtin UI (the |TUI|), but there are many other (third-party) GUIs that you can use instead: -- Firenvim (Nvim in your web browser!) https://github.com/glacambre/firenvim + *vscode* - vscode-neovim (Nvim in VSCode!) https://github.com/vscode-neovim/vscode-neovim +- Firenvim (Nvim in your web browser!) https://github.com/glacambre/firenvim - Neovide https://neovide.dev/ - Goneovim https://github.com/akiyosi/goneovim - Nvy https://github.com/RMichelsen/Nvy diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index d099c29bdb..85169fcc17 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -49,17 +49,19 @@ For more information try one of these: ============================================================================== Nvim on the interwebs *internet* - *www* *distribution* *download* - - Nvim home page: https://neovim.io/ - Downloads: https://github.com/neovim/neovim/releases - Vim FAQ: https://vimhelp.org/vim_faq.txt.html - - - *bugs* *bug-report* -Report bugs and request features here: -https://github.com/neovim/neovim/issues - + *www* *distribution* +- Nvim home page: https://neovim.io/ +- Vim FAQ: https://vimhelp.org/vim_faq.txt.html + + *download* *upgrade* *ubuntu* +To install or upgrade Nvim, you can... +- Download a pre-built archive: + https://github.com/neovim/neovim/releases +- Use your system package manager: + https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package + + *bugs* *bug-report* *feature-request* +Report bugs and request features here: https://github.com/neovim/neovim/issues Be brief, yet complete. Always give a reproducible example and try to find out which settings or other things trigger the bug. diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index e311831bd3..2654d7f14f 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -841,12 +841,11 @@ start({config}, {opts}) *vim.lsp.start()* }) < - See |vim.lsp.start_client()| for all available options. The most important + See |vim.lsp.ClientConfig| for all available options. The most important are: • `name` arbitrary name for the LSP client. Should be unique per language server. - • `cmd` command string[] or function, described at - |vim.lsp.start_client()|. + • `cmd` command string[] or function. • `root_dir` path to the project root. By default this is used to decide if an existing client should be re-used. The example above uses |vim.fs.root()| to detect the root by traversing the file system upwards @@ -868,7 +867,7 @@ start({config}, {opts}) *vim.lsp.start()* Parameters: ~ • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See |vim.lsp.ClientConfig|. - • {opts} (`table?`) Optional keyword arguments + • {opts} (`table?`) Optional keyword arguments. • {reuse_client}? (`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`) Predicate used to decide if a client should be re-used. @@ -876,25 +875,15 @@ start({config}, {opts}) *vim.lsp.start()* re-uses a client if name and root_dir matches. • {bufnr}? (`integer`) Buffer handle to attach to if starting or re-using a client (0 for current). + • {attach}? (`boolean`) Whether to attach the client to a + buffer (default true). If set to `false`, `reuse_client` + and `bufnr` will be ignored. • {silent}? (`boolean`) Suppress error reporting if the LSP server fails to start (default false). Return: ~ (`integer?`) client_id -start_client({config}) *vim.lsp.start_client()* - Starts and initializes a client with the given configuration. - - Parameters: ~ - • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See - |vim.lsp.ClientConfig|. - - Return (multiple): ~ - (`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may - not be fully initialized. Use `on_init` to do any actions once the - client has been initialized. - (`string?`) Error message, if any - status() *vim.lsp.status()* Consumes the latest progress messages from all clients and formats them as a string. Empty if there are no clients or if no new messages @@ -968,8 +957,7 @@ Lua module: vim.lsp.client *lsp-client* server. • {config} (`vim.lsp.ClientConfig`) copy of the table that was passed by the user to - |vim.lsp.start_client()|. See - |vim.lsp.ClientConfig|. + |vim.lsp.start()|. See |vim.lsp.ClientConfig|. • {server_capabilities} (`lsp.ServerCapabilities?`) Response from the server sent on `initialize` describing the server's capabilities. @@ -1093,7 +1081,7 @@ Lua module: vim.lsp.client *lsp-client* • {commands}? (`table<string,fun(command: lsp.Command, ctx: table)>`) Table that maps string of clientside commands to user-defined functions. Commands passed to - start_client take precedence over the global + `start()` take precedence over the global command registry. Each key must be a unique command name, and the value is a function which is called if any LSP action (code action, code @@ -1122,9 +1110,9 @@ Lua module: vim.lsp.client *lsp-client* Callback invoked before the LSP "initialize" phase, where `params` contains the parameters being sent to the server and `config` is the - config that was passed to - |vim.lsp.start_client()|. You can use this to - modify parameters before they are sent. + config that was passed to |vim.lsp.start()|. You + can use this to modify parameters before they + are sent. • {on_init}? (`elem_or_list<fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)>`) Callback invoked after LSP "initialize", where `result` is a table of `capabilities` and @@ -2296,7 +2284,7 @@ connect({host_or_path}, {port}) *vim.lsp.rpc.connect()* • a host and port via TCP Return a function that can be passed to the `cmd` field for - |vim.lsp.start_client()| or |vim.lsp.start()|. + |vim.lsp.start()|. Parameters: ~ • {host_or_path} (`string`) host to connect to or path to a pipe/domain diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 047e263768..48fa595a53 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -17,9 +17,9 @@ get an idea of what lurks beneath: >vim :lua vim.print(package.loaded) Nvim includes a "standard library" |lua-stdlib| for Lua. It complements the -"editor stdlib" (|builtin-functions| and |Ex-commands|) and the |API|, all of -which can be used from Lua code (|lua-vimscript| |vim.api|). Together these -"namespaces" form the Nvim programming interface. +"editor stdlib" (|vimscript-functions| + |Ex-commands|) and the |API|, all of +which can be used from Lua code (|lua-vimscript| |vim.api|). These three +namespaces form the Nvim programming interface. Lua plugins and user config are automatically discovered and loaded, just like Vimscript. See |lua-guide| for practical guidance. diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 11048aee30..34cf309576 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -12,7 +12,7 @@ manual. Type |gO| to see the table of contents. ============================================================================== -1. Key mapping *key-mapping* *mapping* *macro* +1. Key mapping *keybind* *key-mapping* *mapping* *macro* Key mapping is used to change the meaning of typed keys. The most common use is to define a sequence of commands for a function key. Example: > diff --git a/runtime/doc/nvim.txt b/runtime/doc/nvim.txt index 86e344c654..8593511dbc 100644 --- a/runtime/doc/nvim.txt +++ b/runtime/doc/nvim.txt @@ -6,21 +6,23 @@ Nvim *nvim* *neovim* *nvim-intro* -Nvim is based on Vim by Bram Moolenaar. +Nvim is based on Vim by Bram Moolenaar. Nvim is emphatically a fork of Vim, +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 are new to Vim, try the 30-minute tutorial: >vim +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 . - :Tutor<Enter> - -Nvim is emphatically a fork of Vim, not a clone: compatibility with Vim -(especially editor and Vimscript features) is maintained where possible. See -|vim-differences| for the complete reference of differences from Vim. +To learn how to use Vim in 30 minutes, try the tutorial: >vim + :Tutor<Enter> +< Type |gO| to see the table of contents. ============================================================================== -Transitioning from Vim *nvim-from-vim* +Transitioning from Vim *nvim-from-vim* 1. To start the transition, create your |init.vim| (user config) file: >vim @@ -71,4 +73,20 @@ the same Nvim configuration on all of your machines, by creating source ~/.config/nvim/init.vim ============================================================================== +What next? *nvim-quickstart* + +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: diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index 55eba484bc..77eddfd8e1 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -788,7 +788,7 @@ must handle. kind Name indicating the message kind: - "" (empty) Unknown (consider a feature-request: |bugs|) + "" (empty) Unknown (consider a |feature-request|) "confirm" |confirm()| or |:confirm| dialog "confirm_sub" |:substitute| confirm dialog |:s_c| "emsg" Error (|errors|, internal error, |:throw|, …) diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index d967e7c75b..5049439337 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -534,7 +534,8 @@ gO Show a filetype-specific, navigable "outline" of the current buffer. For example, in a |help| buffer this shows the table of contents. - Currently works in |help| and |:Man| buffers. + Works in |help| and |:Man| buffers, or any buffer with + an active |LSP| client (|lsp-defaults|). [N]gs *gs* *:sl* *:sleep* :[N]sl[eep] [N][m] Do nothing for [N] seconds, or [N] milliseconds if [m] diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 6e1a9adb83..8d2d672ce1 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -186,6 +186,9 @@ nvim_terminal: - 'textwidth' set to 0 - 'nowrap' - 'nolist' + - 'nonumber' + - 'norelativenumber' + - 'signcolumn' set to "no" - 'winhighlight' uses |hl-StatusLineTerm| and |hl-StatusLineTermNC| in place of |hl-StatusLine| and |hl-StatusLineNC| @@ -686,7 +689,7 @@ Cscope: https://github.com/dhananjaylatkar/cscope_maps.nvim Eval: -- Vim9script +- *Vim9script* (the Vim 9+ flavor of Vimscript) is not supported. - *cscope_connection()* - *err_teapot()* - *js_encode()* diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 6583cf48b3..ef83a3ccc3 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -492,6 +492,9 @@ do vim.bo.textwidth = 0 vim.wo[0][0].wrap = false vim.wo[0][0].list = false + vim.wo[0][0].number = false + vim.wo[0][0].relativenumber = false + vim.wo[0][0].signcolumn = 'no' -- This is gross. Proper list options support when? local winhl = vim.o.winhighlight diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index acd12b353d..d74ee11b46 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1654,7 +1654,7 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- Open a terminal instance in a buffer --- --- By default (and currently the only option) the terminal will not be ---- connected to an external process. Instead, input send on the channel +--- connected to an external process. Instead, input sent on the channel --- will be echoed directly by the terminal. This is useful to display --- ANSI terminal sequences returned as part of a rpc message, or similar. --- @@ -1665,6 +1665,18 @@ function vim.api.nvim_notify(msg, log_level, opts) end --- Then `nvim_chan_send()` can be called immediately to process sequences --- in a virtual terminal having the intended size. --- +--- Example: this `TermHl` command can be used to display and highlight raw ANSI termcodes, so you +--- can use Nvim as a "scrollback pager" (for terminals like kitty): [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) +--- end, { desc = 'Highlights ANSI termcodes in curbuf' }) +--- ``` +--- --- @param buffer integer the buffer to use (expected to be empty) --- @param opts vim.api.keyset.open_term Optional parameters. --- - on_input: Lua callback for input sent, i e keypresses in terminal diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index f9b5d93a4b..e207f641de 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -4928,7 +4928,7 @@ function vim.fn.jobstop(id) end --- --- @param jobs integer[] --- @param timeout? integer ---- @return any +--- @return integer[] function vim.fn.jobwait(jobs, timeout) end --- Join the items in {list} together into one String. @@ -7244,9 +7244,9 @@ function vim.fn.round(expr) end --- --- @param channel integer --- @param event string ---- @param args? any +--- @param ... any --- @return any -function vim.fn.rpcnotify(channel, event, args) end +function vim.fn.rpcnotify(channel, event, ...) end --- Sends a request to {channel} to invoke {method} via --- |RPC| and blocks until a response is received. @@ -7256,9 +7256,9 @@ function vim.fn.rpcnotify(channel, event, args) end --- --- @param channel integer --- @param method string ---- @param args? any +--- @param ... any --- @return any -function vim.fn.rpcrequest(channel, method, args) end +function vim.fn.rpcrequest(channel, method, ...) end --- @deprecated --- Deprecated. Replace >vim @@ -9328,6 +9328,7 @@ function vim.fn.str2float(string, quoted) end --- and exists only for backwards-compatibility. --- With UTF-8 composing characters are handled properly: >vim --- echo str2list("á") " returns [97, 769] +--- < --- --- @param string string --- @param utf8? boolean @@ -10870,7 +10871,7 @@ function vim.fn.winheight(nr) end --- < --- --- @param tabnr? integer ---- @return any +--- @return any[] function vim.fn.winlayout(tabnr) end --- The result is a Number, which is the screen line of the cursor diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua index ce5dbffeaa..c0a0570e13 100644 --- a/runtime/lua/vim/_system.lua +++ b/runtime/lua/vim/_system.lua @@ -47,15 +47,6 @@ local function close_handle(handle) end end ----@param state vim.SystemState -local function close_handles(state) - close_handle(state.handle) - close_handle(state.stdin) - close_handle(state.stdout) - close_handle(state.stderr) - close_handle(state.timer) -end - --- @class vim.SystemObj --- @field cmd string[] --- @field pid integer @@ -132,9 +123,7 @@ function SystemObj:write(data) -- (https://github.com/neovim/neovim/pull/17620#discussion_r820775616) stdin:write('', function() stdin:shutdown(function() - if stdin then - stdin:close() - end + close_handle(stdin) end) end) end @@ -146,25 +135,52 @@ function SystemObj:is_closing() return handle == nil or handle:is_closing() or false end ----@param output fun(err:string?, data: string?)|false ----@return uv.uv_stream_t? ----@return fun(err:string?, data: string?)? Handler -local function setup_output(output) - if output == nil then - return assert(uv.new_pipe(false)), nil +--- @param output? uv.read_start.callback|false +--- @param text? boolean +--- @return uv.uv_stream_t? pipe +--- @return uv.read_start.callback? handler +--- @return string[]? data +local function setup_output(output, text) + if output == false then + return end + local bucket --- @type string[]? + local handler --- @type uv.read_start.callback + if type(output) == 'function' then - return assert(uv.new_pipe(false)), output + handler = output + else + bucket = {} + handler = function(err, data) + if err then + error(err) + end + if text and data then + bucket[#bucket + 1] = data:gsub('\r\n', '\n') + else + bucket[#bucket + 1] = data + end + end end - assert(output == false) - return nil, nil + local pipe = assert(uv.new_pipe(false)) + + --- @type uv.read_start.callback + local function handler_with_close(err, data) + handler(err, data) + if data == nil then + pipe:read_stop() + pipe:close() + end + end + + return pipe, handler_with_close, bucket end ----@param input string|string[]|true|nil ----@return uv.uv_stream_t? ----@return string|string[]? +--- @param input? string|string[]|boolean +--- @return uv.uv_stream_t? +--- @return string|string[]? local function setup_input(input) if not input then return @@ -208,28 +224,6 @@ local function setup_env(env, clear_env) return renv end ---- @param stream uv.uv_stream_t ---- @param text? boolean ---- @param bucket string[] ---- @return fun(err: string?, data: string?) -local function default_handler(stream, text, bucket) - return function(err, data) - if err then - error(err) - end - if data ~= nil then - if text then - bucket[#bucket + 1] = data:gsub('\r\n', '\n') - else - bucket[#bucket + 1] = data - end - else - stream:read_stop() - stream:close() - end - end -end - local is_win = vim.fn.has('win32') == 1 local M = {} @@ -255,9 +249,9 @@ local function spawn(cmd, opts, on_exit, on_error) return handle, pid_or_err --[[@as integer]] end ----@param timeout integer ----@param cb fun() ----@return uv.uv_timer_t +--- @param timeout integer +--- @param cb fun() +--- @return uv.uv_timer_t local function timer_oneshot(timeout, cb) local timer = assert(uv.new_timer()) timer:start(timeout, 0, function() @@ -273,7 +267,12 @@ end --- @param signal integer --- @param on_exit fun(result: vim.SystemCompleted)? local function _on_exit(state, code, signal, on_exit) - close_handles(state) + close_handle(state.handle) + close_handle(state.stdin) + close_handle(state.timer) + + -- #30846: Do not close stdout/stderr here, as they may still have data to + -- read. They will be closed in uv.read_start on EOF. local check = assert(uv.new_check()) check:start(function() @@ -311,6 +310,15 @@ local function _on_exit(state, code, signal, on_exit) end) end +--- @param state vim.SystemState +local function _on_error(state) + close_handle(state.handle) + close_handle(state.stdin) + close_handle(state.stdout) + close_handle(state.stderr) + close_handle(state.timer) +end + --- Run a system command --- --- @param cmd string[] @@ -324,8 +332,8 @@ function M.run(cmd, opts, on_exit) opts = opts or {} - local stdout, stdout_handler = setup_output(opts.stdout) - local stderr, stderr_handler = setup_output(opts.stderr) + local stdout, stdout_handler, stdout_data = setup_output(opts.stdout, opts.text) + local stderr, stderr_handler, stderr_data = setup_output(opts.stderr, opts.text) local stdin, towrite = setup_input(opts.stdin) --- @type vim.SystemState @@ -335,7 +343,9 @@ function M.run(cmd, opts, on_exit) timeout = opts.timeout, stdin = stdin, stdout = stdout, + stdout_data = stdout_data, stderr = stderr, + stderr_data = stderr_data, } --- @diagnostic disable-next-line:missing-fields @@ -350,17 +360,15 @@ function M.run(cmd, opts, on_exit) }, function(code, signal) _on_exit(state, code, signal, on_exit) end, function() - close_handles(state) + _on_error(state) end) - if stdout then - state.stdout_data = {} - stdout:read_start(stdout_handler or default_handler(stdout, opts.text, state.stdout_data)) + if stdout and stdout_handler then + stdout:read_start(stdout_handler) end - if stderr then - state.stderr_data = {} - stderr:read_start(stderr_handler or default_handler(stderr, opts.text, state.stderr_data)) + if stderr and stderr_handler then + stderr:read_start(stderr_handler) end local obj = new_systemobj(state) diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 5d771c30e9..b4c37dd160 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1873,6 +1873,8 @@ local filename = { ['.clang-tidy'] = 'yaml', ['yarn.lock'] = 'yaml', matplotlibrc = 'yaml', + ['.condarc'] = 'yaml', + condarc = 'yaml', zathurarc = 'zathurarc', ['/etc/zprofile'] = 'zsh', ['.zlogin'] = 'zsh', diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index b1a3316e3e..4717d7995a 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -211,17 +211,117 @@ local function reuse_client_default(client, config) return false end +--- Reset defaults set by `set_defaults`. +--- Must only be called if the last client attached to a buffer exits. +local function reset_defaults(bufnr) + if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then + vim.bo[bufnr].tagfunc = nil + end + if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then + vim.bo[bufnr].omnifunc = nil + end + if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then + vim.bo[bufnr].formatexpr = nil + end + vim._with({ buf = bufnr }, function() + local keymap = vim.fn.maparg('K', 'n', false, true) + if keymap and keymap.callback == vim.lsp.buf.hover and keymap.buffer == 1 then + vim.keymap.del('n', 'K', { buffer = bufnr }) + end + end) +end + +--- @param code integer +--- @param signal integer +--- @param client_id integer +local function on_client_exit(code, signal, client_id) + local client = all_clients[client_id] + + vim.schedule(function() + for bufnr in pairs(client.attached_buffers) do + if client and client.attached_buffers[bufnr] and api.nvim_buf_is_valid(bufnr) then + api.nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + end + + client.attached_buffers[bufnr] = nil + + if #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 then + reset_defaults(bufnr) + end + end + + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace) + end) + + local name = client.name or 'unknown' + + -- Schedule the deletion of the client object so that it exists in the execution of LspDetach + -- autocommands + vim.schedule(function() + all_clients[client_id] = nil + + -- Client can be absent if executable starts, but initialize fails + -- init/attach won't have happened + if client then + changetracking.reset(client) + end + if code ~= 0 or (signal ~= 0 and signal ~= 15) then + local msg = string.format( + 'Client %s quit with exit code %s and signal %s. Check log for errors: %s', + name, + code, + signal, + lsp.get_log_path() + ) + vim.notify(msg, vim.log.levels.WARN) + end + end) +end + +--- Creates and initializes a client with the given configuration. +--- @param config vim.lsp.ClientConfig Configuration for the server. +--- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be +--- fully initialized. Use `on_init` to do any actions once +--- the client has been initialized. +--- @return string? # Error message, if any +local function create_and_initialize_client(config) + local ok, res = pcall(require('vim.lsp.client').create, config) + if not ok then + return nil, res --[[@as string]] + end + + local client = assert(res) + + --- @diagnostic disable-next-line: invisible + table.insert(client._on_exit_cbs, on_client_exit) + + all_clients[client.id] = client + + client:initialize() + + return client.id, nil +end + --- @class vim.lsp.start.Opts --- @inlinedoc --- --- 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 --- root_dir matches. ---- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean +--- @field reuse_client? (fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean) --- --- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr? integer --- +--- Whether to attach the client to a buffer (default true). +--- If set to `false`, `reuse_client` and `bufnr` will be ignored. +--- @field attach? boolean +--- --- Suppress error reporting if the LSP server fails to start (default false). --- @field silent? boolean @@ -239,10 +339,10 @@ end --- }) --- ``` --- ---- See |vim.lsp.start_client()| for all available options. The most important are: +--- See |vim.lsp.ClientConfig| for all available options. The most important are: --- --- - `name` arbitrary name for the LSP client. Should be unique per language server. ---- - `cmd` command string[] or function, described at |vim.lsp.start_client()|. +--- - `cmd` command string[] or function. --- - `root_dir` path to the project root. By default this is used to decide if an existing client --- should be re-used. The example above uses |vim.fs.root()| to detect the root by traversing --- the file system upwards starting from the current directory until either a `pyproject.toml` @@ -262,7 +362,7 @@ end --- `ftplugin/<filetype_name>.lua` (See |ftplugin-name|) --- --- @param config vim.lsp.ClientConfig Configuration for the server. ---- @param opts vim.lsp.start.Opts? Optional keyword arguments +--- @param opts vim.lsp.start.Opts? Optional keyword arguments. --- @return integer? client_id function lsp.start(config, opts) opts = opts or {} @@ -271,6 +371,10 @@ function lsp.start(config, opts) for _, client in pairs(all_clients) do if reuse_client(client, config) then + if opts.attach == false then + return client.id + end + if lsp.buf_attach_client(bufnr, client.id) then return client.id else @@ -279,7 +383,7 @@ function lsp.start(config, opts) end end - local client_id, err = lsp.start_client(config) + local client_id, err = create_and_initialize_client(config) if err then if not opts.silent then vim.notify(err, vim.log.levels.WARN) @@ -287,6 +391,10 @@ function lsp.start(config, opts) return nil end + if opts.attach == false then + return client_id + end + if client_id and lsp.buf_attach_client(bufnr, client_id) then return client_id end @@ -383,78 +491,7 @@ function lsp._set_defaults(client, bufnr) end end ---- Reset defaults set by `set_defaults`. ---- Must only be called if the last client attached to a buffer exits. -local function reset_defaults(bufnr) - if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then - vim.bo[bufnr].tagfunc = nil - end - if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then - vim.bo[bufnr].omnifunc = nil - end - if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then - vim.bo[bufnr].formatexpr = nil - end - vim._with({ buf = bufnr }, function() - local keymap = vim.fn.maparg('K', 'n', false, true) - if keymap and keymap.callback == vim.lsp.buf.hover and keymap.buffer == 1 then - vim.keymap.del('n', 'K', { buffer = bufnr }) - end - end) -end - ---- @param code integer ---- @param signal integer ---- @param client_id integer -local function on_client_exit(code, signal, client_id) - local client = all_clients[client_id] - - vim.schedule(function() - for bufnr in pairs(client.attached_buffers) do - if client and client.attached_buffers[bufnr] and api.nvim_buf_is_valid(bufnr) then - api.nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) - end - - client.attached_buffers[bufnr] = nil - - if #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 then - reset_defaults(bufnr) - end - end - - local namespace = vim.lsp.diagnostic.get_namespace(client_id) - vim.diagnostic.reset(namespace) - end) - - local name = client.name or 'unknown' - - -- Schedule the deletion of the client object so that it exists in the execution of LspDetach - -- autocommands - vim.schedule(function() - all_clients[client_id] = nil - - -- Client can be absent if executable starts, but initialize fails - -- init/attach won't have happened - if client then - changetracking.reset(client) - end - if code ~= 0 or (signal ~= 0 and signal ~= 15) then - local msg = string.format( - 'Client %s quit with exit code %s and signal %s. Check log for errors: %s', - name, - code, - signal, - lsp.get_log_path() - ) - vim.notify(msg, vim.log.levels.WARN) - end - end) -end - +--- @deprecated --- Starts and initializes a client with the given configuration. --- @param config vim.lsp.ClientConfig Configuration for the server. --- @return integer? client_id |vim.lsp.get_client_by_id()| Note: client may not be @@ -462,21 +499,8 @@ end --- the client has been initialized. --- @return string? # Error message, if any function lsp.start_client(config) - local ok, res = pcall(require('vim.lsp.client').create, config) - if not ok then - return nil, res --[[@as string]] - end - - local client = assert(res) - - --- @diagnostic disable-next-line: invisible - table.insert(client._on_exit_cbs, on_client_exit) - - all_clients[client.id] = client - - client:initialize() - - return client.id, nil + vim.deprecate('vim.lsp.start_client()', 'vim.lsp.start()', '0.13') + return create_and_initialize_client(config) end ---Buffer lifecycle handler for textDocument/didSave diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index a14b6ccda6..a83d75bf75 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -78,7 +78,7 @@ local validate = vim.validate --- @field settings? table --- --- Table that maps string of clientside commands to user-defined functions. ---- Commands passed to start_client take precedence over the global command registry. Each key +--- Commands passed to `start()` take precedence over the global command registry. Each key --- must be a unique command name, and the value is a function which is called if any LSP action --- (code action, code lenses, ...) triggers the command. --- @field commands? table<string,fun(command: lsp.Command, ctx: table)> @@ -104,7 +104,7 @@ local validate = vim.validate --- @field on_error? fun(code: integer, err: string) --- --- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters ---- being sent to the server and `config` is the config that was passed to |vim.lsp.start_client()|. +--- being sent to the server and `config` is the config that was passed to |vim.lsp.start()|. --- You can use this to modify parameters before they are sent. --- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) --- @@ -167,7 +167,7 @@ local validate = vim.validate --- @field requests table<integer,{ type: string, bufnr: integer, method: string}> --- --- copy of the table that was passed by the user ---- to |vim.lsp.start_client()|. +--- to |vim.lsp.start()|. --- @field config vim.lsp.ClientConfig --- --- Response from the server sent on `initialize` describing the server's @@ -307,7 +307,7 @@ local function default_get_language_id(_bufnr, filetype) return filetype end ---- Validates a client configuration as given to |vim.lsp.start_client()|. +--- Validates a client configuration as given to |vim.lsp.start()|. --- @param config vim.lsp.ClientConfig local function validate_config(config) validate('config', config, 'table') diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 6c8564845f..2327a37ab1 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -617,7 +617,7 @@ end --- - a host and port via TCP --- --- Return a function that can be passed to the `cmd` field for ---- |vim.lsp.start_client()| or |vim.lsp.start()|. +--- |vim.lsp.start()|. --- ---@param host_or_path string host to connect to or path to a pipe/domain socket ---@param port integer? TCP port to connect to. If absent the first argument must be a pipe |