diff --git a/Makefile b/Makefile
index 4a7fc81c6..cd43a116d 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ NVIM_HEADLESS:=nvim --headless --noplugin -u tests/minimal_init.vim
dependencies:
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim dependencies/pack/vendor/start/plenary.nvim
+ git clone --depth 1 https://github.com/neovim/nvim-lspconfig dependencies/pack/vendor/start/nvim-lspconfig
.PHONY: clean_dependencies
clean_dependencies:
diff --git a/README.md b/README.md
index 82454362f..43098c7a8 100644
--- a/README.md
+++ b/README.md
@@ -5,33 +5,32 @@
- [About](#about)
- [Screenshots](#screenshots)
- [Installation](#installation)
- - [Packer](#packer)
- - [vim-plug](#vim-plug)
- [Usage](#usage)
- - [Commands](#commands)
- [Setup](#setup)
+ - [Commands](#commands)
- [Configuration](#configuration)
- [Available LSPs](#available-lsps)
- [Custom servers](#custom-servers)
- [Logo](#logo)
-- [Roadmap](#roadmap)
- [Default configuration](#default-configuration)
## About
-Neovim plugin that allows you to seamlessly install LSP servers locally (inside `:echo stdpath("data")`).
+Neovim plugin that allows you to manage LSP servers (servers are installed inside `:echo stdpath("data")` by default).
+It registers a hook with [`lspconfig`](https://github.com/neovim/nvim-lspconfig) that enhances the `PATH` environment,
+allowing neovim's LSP client to locate the installed server executable1.
On top of just providing commands for installing & uninstalling LSP servers, it:
- provides a graphical UI
-- is optimized for blazing fast startup times
-- provides the ability to check for new server versions
+- provides the ability to check for, and upgrade to, new server versions through a single interface
- supports installing custom versions of LSP servers (for example `:LspInstall rust_analyzer@nightly`)
- relaxes the minimum requirements by attempting multiple different utilities (for example, only one of `wget`, `curl`, or `Invoke-WebRequest` is required for HTTP requests)
-- allows you to install and setup servers without having to restart neovim
- hosts [a suite of system tests](https://github.com/williamboman/nvim-lspconfig-test) for all supported servers
- has full support for Windows
+1 - some servers don't provide an executable, in which case the full command to spawn the server is provided instead
+
## Screenshots
| | | |
@@ -83,6 +82,17 @@ Plug 'williamboman/nvim-lsp-installer'
## Usage
+### Setup
+
+In order for nvim-lsp-installer to register the necessary hooks at the right moment, **make sure you call the `.setup()`
+function before you set up any servers with `lspconfig`**!
+
+```lua
+require("nvim-lsp-installer").setup {}
+```
+
+Refer to the [Configuration](#configuration) section for information about which settings are available.
+
### Commands
- `:LspInstallInfo` - opens a graphical overview of your language servers
@@ -92,54 +102,16 @@ Plug 'williamboman/nvim-lsp-installer'
- `:LspInstallLog` - opens the log file in a new tab window
- `:LspPrintInstalled` - prints all installed language servers
-### Setup
-
-The recommended way of setting up your installed servers is to do it through nvim-lsp-installer.
-By doing so, nvim-lsp-installer will make sure to inject any necessary properties before calling lspconfig's setup
-function for you. You may find a minimal example below. To see how you can override the default settings for a server,
-refer to the [Wiki][overriding-default-settings].
-
-Make sure you don't also set up your servers directly via lspconfig (e.g. `require("lspconfig").clangd.setup {}`), as
-this will cause servers to be set up twice!
-
-[overriding-default-settings]: https://github.com/williamboman/nvim-lsp-installer/wiki/Advanced-Configuration#overriding-the-default-lsp-server-options
-
-```lua
-local lsp_installer = require("nvim-lsp-installer")
-
--- Register a handler that will be called for each installed server when it's ready (i.e. when installation is finished
--- or if the server is already installed).
-lsp_installer.on_server_ready(function(server)
- local opts = {}
-
- -- (optional) Customize the options passed to the server
- -- if server.name == "tsserver" then
- -- opts.root_dir = function() ... end
- -- end
-
- -- This setup() function will take the provided server configuration and decorate it with the necessary properties
- -- before passing it onwards to lspconfig.
- -- Refer to https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
- server:setup(opts)
-end)
-```
-
-For more advanced use cases you may also interact with more APIs nvim-lsp-installer has to offer, refer to `:help nvim-lsp-installer` for more docs.
-
### Configuration
-You can configure certain behavior of nvim-lsp-installer by calling the `.settings()` function.
-
-_Make sure to provide your settings before any other interactions with nvim-lsp-installer!_
+You may optionally configure certain behavior of nvim-lsp-installer when calling the `.setup()` function.
Refer to the [default configuration](#default-configuration) for all available settings.
Example:
```lua
-local lsp_installer = require("nvim-lsp-installer")
-
-lsp_installer.settings({
+require("nvim-lsp-installer").setup({
ui = {
icons = {
server_installed = "✓",
@@ -289,10 +261,6 @@ You can create your own installers by using the same APIs nvim-lsp-installer its
Illustrations in the logo are derived from [@Kaligule](https://schauderbasis.de/)'s "Robots" collection.
-## Roadmap
-
-- Command (and corresponding Lua API) to update outdated servers (e.g., `:LspUpdateAll`)
-
## Default configuration
```lua
@@ -309,12 +277,16 @@ local DEFAULT_SETTINGS = {
keymaps = {
-- Keymap to expand a server in the UI
toggle_server_expand = "",
- -- Keymap to install a server
+ -- Keymap to install the server under the current cursor position
install_server = "i",
- -- Keymap to reinstall/update a server
+ -- Keymap to reinstall/update the server under the current cursor position
update_server = "u",
+ -- Keymap to check for new version for the server under the current cursor position
+ check_server_version = "c",
-- Keymap to update all installed servers
update_all_servers = "U",
+ -- Keymap to check which installed servers are outdated
+ check_outdated_servers = "C",
-- Keymap to uninstall a server
uninstall_server = "X",
},
diff --git a/doc/nvim-lsp-installer.txt b/doc/nvim-lsp-installer.txt
index 863ad2c93..811ce4cd9 100644
--- a/doc/nvim-lsp-installer.txt
+++ b/doc/nvim-lsp-installer.txt
@@ -20,7 +20,6 @@ it:
- relaxes the minimum requirements by attempting multiple different
utilities (for example, only one of `wget`, `curl`, or `Invoke-WebRequest`
is required for HTTP requests)
-- allows you to install and setup servers without having to restart neovim
- hosts a suite of system tests for all supported servers
- has full support for Windows
@@ -49,6 +48,12 @@ https://github.com/williamboman/nvim-lsp-installer/blob/main/CUSTOM_SERVERS.md.
==============================================================================
QUICK START *nvim-lsp-installer-quickstart*
+The only thing needed to get started with nvim-lsp-installer is to make sure
+to call the `setup()` function _before_ you set up any servers: >
+
+ require("nvim-lsp-installer").setup {}
+<
+
To view the UI for nvim-lsp-installer, run: >
:LspInstallInfo
@@ -79,30 +84,6 @@ buffer, simply just run: >
Please refer to each server's own release page to find which versions are
available.
-Then, somewhere in your initialization script (see `:h init.lua`): >
-
- -- Register a handler that will be called for each installed server when it's ready (i.e. when installation is finished
- -- or if the server is already installed).
- lsp_installer.on_server_ready(function(server)
- local opts = {}
-
- -- (optional) Customize the options passed to the server
- -- if server.name == "tsserver" then
- -- opts.root_dir = function() ... end
- -- end
-
- -- This setup() function will take the provided server configuration and decorate it with the necessary properties
- -- before passing it onwards to lspconfig.
- -- Refer to https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
- server:setup(opts)
- end)
-<
-
-Make sure you don't also set up your servers directly via lspconfig (e.g.
-`require("lspconfig").clangd.setup {}`), as this will cause servers to be set
-up twice!
-
-
==============================================================================
COMMANDS *nvim-lsp-installer-commands*
@@ -156,20 +137,14 @@ Prints all installed language servers.
==============================================================================
SETTINGS *nvim-lsp-installer-settings*
-You can configure certain behavior of nvim-lsp-installer by calling the
-`.settings()` function.
-
-Make sure to provide your settings before any other interactions with
-nvim-lsp-installer!
+You can configure certain behavior of nvim-lsp-installer when calling the
+`.setup()` function.
Refer to the |nvim-lsp-installer-default-settings| for all available settings.
Example: >
- local lsp_installer = require("nvim-lsp-installer")
-
- -- Provide settings first!
- lsp_installer.settings({
+ require("nvim-lsp-installer").setup({
ui = {
icons = {
server_installed = "✓",
@@ -178,10 +153,6 @@ Example: >
}
}
})
-
- lsp_installer.on_server_ready(function (server)
- server:setup {}
- end)
<
*nvim-lsp-installer-default-settings*
@@ -200,12 +171,16 @@ The following settings are applied by default. >
keymaps = {
-- Keymap to expand a server in the UI
toggle_server_expand = "",
- -- Keymap to install a server
+ -- Keymap to install the server under the current cursor position
install_server = "i",
- -- Keymap to reinstall/update a server
+ -- Keymap to reinstall/update the server under the current cursor position
update_server = "u",
+ -- Keymap to check for new version for the server under the current cursor position
+ check_server_version = "c",
-- Keymap to update all installed servers
update_all_servers = "U",
+ -- Keymap to check which installed servers are outdated
+ check_outdated_servers = "C",
-- Keymap to uninstall a server
uninstall_server = "X",
},
@@ -238,7 +213,9 @@ DEBUGGING *nvim-lsp-installer-debugging*
To help with debugging issues with installing/uninstall servers, please make
sure to set nvim-lsp-installer's log level to DEBUG or TRACE, like so: >
- :lua require("nvim-lsp-installer").settings({ log_level = vim.log.levels.DEBUG })
+ require("nvim-lsp-installer").setup {
+ log_level = vim.log.levels.DEBUG
+ }
<
You may find the logs by entering the command `:LspInstallLog`. Providing the
@@ -247,6 +224,11 @@ contents of this file when reporting an issue will help tremendously.
==============================================================================
Lua module: nvim-lsp-installer
+ *nvim-lsp-installer.setup()*
+setup({config})
+ Sets up nvim-lsp-installer with the provided {config} (see
+ |nvim-lsp-installer-settings|).
+
*nvim-lsp-installer.install()*
install({server_name})
Installs the provided {server_name}. If {server_name} is already
@@ -345,7 +327,7 @@ class: Server
servers.
Methods: ~
- - setup({opts})
+ - setup({opts}) *DEPRECATED - setup servers directly via lspconfig instead*
Sets up the language server and attaches all open buffers.
See:
@@ -356,7 +338,7 @@ class: Server
{opts} (table) The lspconfig server configuration.
See https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
- - setup_lsp({opts})
+ - setup_lsp({opts}) *DEPRECATED - setup servers directly via lspconfig instead*
Sets up the language server via lspconfig.
This function has the same signature as the setup function
in nvim-lspconfig.
@@ -365,7 +347,7 @@ class: Server
{opts} (table) The lspconfig server configuration.
See https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
- - attach_buffers()
+ - attach_buffers() *DEPRECATED - setup servers directly via lspconfig instead*
Attaches this server to all current open buffers with a
'filetype' that matches the server's configured filetypes.
diff --git a/lua/nvim-lsp-installer.lua b/lua/nvim-lsp-installer.lua
index 62b20a1e2..f044fee58 100644
--- a/lua/nvim-lsp-installer.lua
+++ b/lua/nvim-lsp-installer.lua
@@ -14,6 +14,12 @@ local M = {}
M.settings = settings.set
+---@param config table
+function M.setup(config)
+ settings.set(config)
+ require("nvim-lsp-installer.middleware").register_lspconfig_hook()
+end
+
M.info_window = {
---Opens the status window.
open = function()
diff --git a/lua/nvim-lsp-installer/middleware.lua b/lua/nvim-lsp-installer/middleware.lua
new file mode 100644
index 000000000..3e01b976a
--- /dev/null
+++ b/lua/nvim-lsp-installer/middleware.lua
@@ -0,0 +1,32 @@
+local util = require "lspconfig.util"
+local servers = require "nvim-lsp-installer.servers"
+
+local M = {}
+
+---@param t1 table
+---@param t2 table
+local function merge_in_place(t1, t2)
+ for k, v in pairs(t2) do
+ if type(v) == "table" then
+ if type(t1[k]) == "table" and not vim.tbl_islist(t1[k]) then
+ merge_in_place(t1[k], v)
+ else
+ t1[k] = v
+ end
+ else
+ t1[k] = v
+ end
+ end
+ return t1
+end
+
+function M.register_lspconfig_hook()
+ util.on_setup = util.add_hook_before(util.on_setup, function(config)
+ local ok, server = servers.get_server(config.name)
+ if ok then
+ merge_in_place(config, server._default_options)
+ end
+ end)
+end
+
+return M
diff --git a/tests/middleware_spec.lua b/tests/middleware_spec.lua
new file mode 100644
index 000000000..5c629ee6d
--- /dev/null
+++ b/tests/middleware_spec.lua
@@ -0,0 +1,39 @@
+local util = require "lspconfig.util"
+local servers = require "nvim-lsp-installer.servers"
+local middleware = require "nvim-lsp-installer.middleware"
+
+describe("middleware", function()
+ it("should register on_setup hook with lspconfig", function()
+ -- 1. setup dummy server
+ local default_options = {
+ cmd = { "dummy-lsp" },
+ cmd_env = { PATH = "/keep/my/path/out/your/f/mouth" },
+ }
+ local server = ServerGenerator {
+ name = "dummy",
+ default_options = default_options,
+ }
+ servers.register(server)
+
+ -- 2. register hook
+ middleware.register_lspconfig_hook()
+
+ -- 3. call lspconfig hook
+ local config = {
+ name = "dummy",
+ cmd = { "should", "be", "overwritten" },
+ custom = "setting",
+ cmd_env = { SOME_DEFAULT_ENV = "important" },
+ }
+ util.on_setup(config)
+ assert.are.same({
+ cmd = { "dummy-lsp" },
+ name = "dummy",
+ custom = "setting",
+ cmd_env = {
+ PATH = "/keep/my/path/out/your/f/mouth",
+ SOME_DEFAULT_ENV = "important",
+ },
+ }, config)
+ end)
+end)
diff --git a/tests/minimal_debug_init.lua b/tests/minimal_debug_init.lua
index cd42ed246..144db1a72 100644
--- a/tests/minimal_debug_init.lua
+++ b/tests/minimal_debug_init.lua
@@ -22,7 +22,7 @@ local function load_plugins()
{
"wbthomason/packer.nvim",
"neovim/nvim-lspconfig",
- "williamboman/nvim-lsp-installer",
+ { "williamboman/nvim-lsp-installer", branch = "feat/on_setup_hook" },
},
config = {
package_root = package_root,
@@ -32,25 +32,21 @@ local function load_plugins()
end
function _G.load_config()
- -- ==================================================
- -- ======= MODIFY YOUR CONFIG HERE, IF NEEDED =======
- -- ==================================================
- local lsp_installer = require "nvim-lsp-installer"
+ local lspconfig = require "lspconfig"
local function on_attach(client, bufnr)
vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")
end
- require("nvim-lsp-installer").settings {
+ require("nvim-lsp-installer").setup {
log = vim.log.levels.DEBUG,
}
- lsp_installer.on_server_ready(function(server)
- server:setup {
- on_attach = on_attach,
- }
- end)
-- ==================================================
+ -- ========= SETUP RELEVANT SERVER(S) HERE! =========
+ -- ==================================================
+ --
+ -- lspconfig.sumneko_lua.setup { on_attach = on_attach }
end
if vim.fn.isdirectory(install_path) == 0 then