Skip to content
This repository has been archived by the owner on Nov 12, 2022. It is now read-only.

Commit

Permalink
feat: integrate with lspconfig's on_setup hook (#631)
Browse files Browse the repository at this point in the history
* feat: integrate with lspconfig's on_setup hook

* fix!: don't use aliased installation directories if new .setup() fn is used

This makes it so servers are always installed in a directory name that
corresponds with the server name. The reason aliased installation directories
is supported is lost on me, but it's legacy and complicates things
unnecessarily.

This is a breaking change for users who previously were using the `.on_server_ready()`
hook, and now transitioned to setting up servers directly via lspconfig.
These users will need to reinstall the server.

* fix: block usage of the deprecated server:setup() method if new setup method is used

* fix: allow passing no arg to setup()

* docs: ok final.v3 readme
  • Loading branch information
williamboman authored Apr 27, 2022
1 parent 36b4467 commit 090c8a8
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 111 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
82 changes: 28 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,34 @@
- [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 works in tandem with [`lspconfig`](https://github.com/neovim/nvim-lspconfig)<sup>1</sup> by registering a hook that
enhances the `PATH` environment variable, allowing neovim's LSP client to locate the installed server executable.<sup>2</sup>

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 <img src="https://user-images.githubusercontent.com/6705160/131256603-cacf7f66-dfa9-4515-8ae4-0e42d08cfc6a.png" height="20">

<sup>1 - while lspconfig is the main target, this plugin may also be used for other use cases</sup>
<br>
<sup>2 - some servers don't provide an executable, in which case the full command to spawn the server is provided instead</sup>

## Screenshots

| | | |
Expand Down Expand Up @@ -83,6 +84,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
Expand All @@ -92,54 +104,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 = "",
Expand Down Expand Up @@ -289,10 +263,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
Expand All @@ -309,12 +279,16 @@ local DEFAULT_SETTINGS = {
keymaps = {
-- Keymap to expand a server in the UI
toggle_server_expand = "<CR>",
-- 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",
},
Expand Down
89 changes: 43 additions & 46 deletions doc/nvim-lsp-installer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -49,6 +48,25 @@ 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 {}
<

Next, in your initialization files |init.lua|, setup the servers you want to use.
Refer to |lspconfig| for more information! For example: >
local lspconfig = require("lspconfig")
local function on_attach(client, bufnr)
-- set up buffer keymaps, etc.
end
lspconfig.sumneko_lua.setup { on_attach = on_attach }
lspconfig.tsserver.setup { on_attach = on_attach }
<

To view the UI for nvim-lsp-installer, run: >
:LspInstallInfo
Expand Down Expand Up @@ -76,32 +94,7 @@ buffer, simply just run: >
:LspInstall
<

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!

Please refer to each server's own release page to find which versions are available.

==============================================================================
COMMANDS *nvim-lsp-installer-commands*
Expand Down Expand Up @@ -156,20 +149,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 = "✓",
Expand All @@ -178,10 +165,6 @@ Example: >
}
}
})
lsp_installer.on_server_ready(function (server)
server:setup {}
end)
<
*nvim-lsp-installer-default-settings*

Expand All @@ -200,12 +183,16 @@ The following settings are applied by default. >
keymaps = {
-- Keymap to expand a server in the UI
toggle_server_expand = "<CR>",
-- 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",
},
Expand Down Expand Up @@ -238,7 +225,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
Expand All @@ -247,6 +236,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
Expand Down Expand Up @@ -345,7 +339,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:
Expand All @@ -356,7 +350,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.
Expand All @@ -365,13 +359,16 @@ 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.

- get_default_options()
Returns a deep copy of the default options provided to
lspconfig in the setup({opts}) method.
Note: These only include the options provided by
nvim-lsp-installer, and not the default options provided
by lspconfig.

- on_ready({handler})
Registers the provided {handler} to be called when the
Expand Down
9 changes: 9 additions & 0 deletions lua/nvim-lsp-installer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ local M = {}

M.settings = settings.set

---@param config table
function M.setup(config)
if config then
settings.set(config)
end
settings.uses_new_setup = true
require("nvim-lsp-installer.middleware").register_lspconfig_hook()
end

M.info_window = {
---Opens the status window.
open = function()
Expand Down
32 changes: 32 additions & 0 deletions lua/nvim-lsp-installer/middleware.lua
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions lua/nvim-lsp-installer/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ end
---Sets up the language server and attaches all open buffers.
---@param opts table @The lspconfig server configuration.
function M.Server:setup(opts)
assert(
not settings.uses_new_setup,
"Please set up servers directly via lspconfig instead of going through nvim-lsp-installer (this method is now deprecated)! Refer to :h nvim-lsp-installer-quickstart for more information."
)
self:setup_lsp(opts)
if not (opts.autostart == false) then
self:attach_buffers()
Expand Down
Loading

0 comments on commit 090c8a8

Please sign in to comment.