/nvim-lsp-loader

Load language servers everywhere~

Primary LanguageLuaMIT LicenseMIT

nvim-lsp-loader

English | 中文

Load your language servers from .json or .lua files from individual projects. It's a wrapper for nvim-lspconfig and mason.nvim.

If you are still using nvim-lsp-installer, please switch to this branch. And there will not be new feature on this branch due the nvim-lsp-installer is not under active development, see here.

There is a big file to configure my LSP servers. I tried to split it to serveral parts but failed, due to this PR of packer.nvim is stll in WIP. So I gave up to split this file then, and turned to build a middleware which could load servers from static configuration files.

This plugin is inspired by coc.nvim and nlsp-settings.nvim.

Highlight of Features

  • Load default server configurations from specific path, e.g. ~/.config/nvim/languages.json,
  • Find the .nvim/languages.json in the root path of porject, or current work directory, and load it,
  • highly customized lsp,
  • Support load servers from .lua files,
  • Provide user command to load specific server configuration from configuration,
  • More idea is on the road...

Usage

Install

I use packer.nvim to manage my neovim plugins and configurations. But it is supposed to be managed by paq.nvim or vim-plug.

-- packer.nvim
use 'neovim/nvim-lspconfig'
use 'williamboman/mason.nvim'
use 'rcarriga/nvim-notify' -- this is an optional dependency

use {
    'zhang-stephen/nvim-lsp-loader'
    after = 'nvim-lspconfig',
    config = function()
        -- DEFAULT CONFIGURATION
        require('nvim-lsp-loader').setup({
            ---@type string | nil where to find the default server configuations, could be nil
            default_config_path = '~/.config/nvim/languages.json',

            ---@type boolean support nested json keys or not, default is false
            nested_json_keys = false,

            ---@type boolean allow lsp server update or not, default is false
            auto_update = false,

            ---@type table<string> the patterns to detect the root of project
            root_patterns = { '.git/' },

            ---@type function | nil callback when server is attached to buffer, could be nil
            ---@param client_id integer
            ---@param bufnr integer
            on_attach = nil,

            ---@type function | nil to overwrite the capabilities of server, could be nil
            ---@return table language server capabilities
            make_capabilities = nil,

            ---@type function | nil callback for resolving server configuration, would be invoked before server setup
            ---@param name string the name of language server
            ---@param config table the configuration table of language server
            server_config_cb = nil,

            ---@type string working mode, must be one of {'user-first', 'user-only', 'default-first', 'default-only'}
            mode = 'user-first',
        })
    end
}

It shall support to be lazy-loaded if you prefer this way, but this way hasn't been tested.

Generate Configuration

User-defined configuration should follow this example.

NOTICE: Comments is not supported in many json decoder.

{
    "languages": {
        // the programming language will be served by its server, its naming is not restricted.
        // but if there are serveral servers for one language, the name shall be unique in all configurations.
        "lua": {
            // name of language server, should be acceptable in nvim-lspconfig/mason.nvim.
            "name": "sumneko_lua",
            // set it to true if the auto update is expected, could be null.
            // higher priority than same-name field in the plugin configuration.
            "auto_update": true,
            "managed_by": {
                // indicates whether it is installer from mason.nvim
                // e.g. C/C++ server, ccls or clangd could be installed by package manager, instead of mason.nvim
                "mason": true
            },
            // this field will be passed to nvim-lspconfig after resolved, could be null
            // a simple example for neovim plugin developer
            // all available configuration could be found here:
            // https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
            "config": {
                "settings": {
                    "Lua": {
                        "diagnostics": {
                            "globals": [
                                "vim", "packer_plugins"
                            ]
                        },
                        "workspace": {
                            "library": [
                                "$VIMRUNTIME/lua",
                                "$VIMRUNTIME/lua/vim/lsp"
                            ],
                            "maxPreload": 100000,
                            "preloadFileSize": 10000
                        },
                        "telemtry": {
                            "enable": false
                        },
                        "completion": {
                            "keywordSnippet": "Disable",
                            "callSnippet": "Disable"
                        },
                        "runtime": {
                            "version": "Lua 5.1"
                        }
                    }
                },
                // this field will be resolved and overwrotten by lspconfig.util.root_pattern
                // could be null
                "root_dir": [
                    ".git/",
                    "stylua.toml"
                ],
                // this field will be resolved and overwrotten.
                "cmd": [
                    // for the command itself, the first element is the executable
                    // absolute path would be passed to nvim-lspconfig directly,
                    // if this server is managed by mason.nvim:
                    //  - the first could be null, empty string or something else as a placeholder, will be replaced by true command in absolute path
                    //  - others are options, will be passed to lspconfig directly
                    ""
                ]
            }
        },
        // other examples for jsonls/clangd
        "json": {
            "name": "jsonls",
            // nested keys in json is supported if nested_json_keys was set to true
            "managed_by.mason": true,
            "config": {
                "cmd": [
                    // will be replaced to absolute executable path
                    null,
                    "--stdio"
                ]
            }
        },
        "c_cpp": {
            "name": "clangd",
            "managed_by": {
                "mason": false
            },
            "config": {
                "cmd": [
                    // this command will be passed to lspconfig without conversion because it is not managed by mason.nvim
                    // so it shall be guaranteed that could be found in `$PATH`
                    "clangd",
                    "--log=error",
                    "--background-index",
                    "--clang-tidy",
                    "-j=12",
                    "--enable-config"
                ],
                "root_dir": [
                    ".git/", ".clangd"
                ],
                "single_file_support": true
            }
        }
    }
}

Another example from my neovim configuration: Click Here.

How the configuration to be loaded?

It will read server configuration from default_config_path and <proj_root>/.config/nvim/languages.json, which in the root path of project with fixed filename, and mix up the configurations according to the work mode.

  • The configuration from the default will be overloaded by configuration which from <proj_root> if the mode were 'user-first',

  • Or the configuration from the <proj_root> will be overloaded by configuration from the default if the mode were 'default-first',

  • The configuration from the default will be ignored if the mode were 'user-only',

  • Or configuration from <proj_root> will be ignored if the mode is 'default-only'.

Then the servers should be configured automatically.

Code Contributions

This plugin is open-sourced under MIT license. Welcome for all PRs, issues, and great/cool ideas!