Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions data/tutorials/getting-started/2_00_editor_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,85 @@ opam user-setup install
- Type `:MerlinTypeOf` and press <kbd>Enter</kbd>.
- The type information will be displayed in the command bar.
Other Merlin commands for Vim are available and you can checkout their usage on the [Merlin official documentation for Vim](https://ocaml.github.io/merlin/editor/vim/).

## Neovim

Neovim comes with an LSP client.

One note here is that is that `ocaml-lsp-server` is sensitive to versioning, and often does not play well with the sometimes outdated sources in Mason, a popular package manager for language services. We recommend you install the LSP server directly in the switch, and pointing your Neovim config to use that.

To install the LSP server and the formatter, run the following.
```shell
opam install ocaml-lsp-server ocamlformat
```

There are two main ways to install and manage LSP servers.
- A newer, more recommended way is to use the new Neovim LSP API for versions newer than v0.11.0 via `vim.lsp`.
- A more traditional way is to use `nvim-lspconfig`. For more info, `kickstart.nvim` has a great example setup.

### Using vim.lsp:

Add this to your toplevel `init.lua`.
```lua
vim.lsp.config['ocamllsp'] = {
cmd = { 'ocamllsp' },
filetypes = { 'ocaml', 'ocaml.interface', 'ocaml.menhir', 'reason' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ocamllsp.lua from nvim-lspconfig also adds ocaml.ocamllex, and dune to this list, but it does it in an awkward way, the filetype is actually called ocamlinterface and it gets mapped to ocaml.interface using get_language_id.

root_markers = { { 'dune-project', 'dune-workspace' }, '.git' },
settings = {},
}

vim.lsp.enable 'ocamllsp'
```

You can also use `vim.lsp` with a modular config.

Assume that your config has the following structure. The internal structure of `lua` does not matter much.
```text
.
├── init.lua
└── lua
├── custom
│   └── plugins
│   └── some-plugin.lua
└── kickstart
   ├── health.lua
   └── plugins
   └── some-plugin.lua
```

Then run the following at the root of your config.
```text
mkdir lsp
touch lsp/ocamllsp.lua
```

We now add our LSP configs to `lsp/ocamllsp.lua`...
```lua
return {
cmd = { 'ocamllsp' },
filetypes = { 'ocaml', 'ocaml.interface', 'ocaml.menhir', 'reason' },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, this filetype list could probably be longer

root_markers = { { 'dune-project', 'dune-workspace' }, '.git' },
settings = {},
}
```

...and import them in the toplevel `init.lua`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missunderstanding lsp/ folder.
It's a runtimepath file. Read automatically by Neovim on startup. It's not a lua module.

When calling vim.lsp.enable, we aren't importing it. We've already done configuring by placing the lsp config table in <rtp>/lua/<name>.lua files or by calling/setting vim.lsp.config directly.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boltlessengineer this correct, my understanding is he mean to create lsp/ folder in root config. It will get installed to ~/.config/nvim/lsp/ocamllsp.lua.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boltlessengineer should've been more pedantic about the wording here, mb. What I meant by import was to call require.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I said to add the lsp configs to lua? But I can see how giving more context on the config folder structure can be potentially misleading.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm saying that we aren't requiring lsp/ocamllsp.lua by calling vim.lsp.enable().
vim.lsp.config and vim.lsp.enable are completely different things.

Both term 'import' and 'require' doesn't fit here.

What vim.lsp.enable is doing is just: Setup that language server with configured value which is pre-merged vim.lsp.config table. It isn't about loading & merging configs, but about setting up a required autocmds. (to auto-start language server on filetypes)

When someone wants to configure a server, defining a table in <rtp>/lsp/<name>.lua is just enough. It will be auto-merged whenever you indexed the vim.lsp.config like vim.lsp.config['ocamllsp']

check this out:

  • write lsp/ocamllsp.lua and do nothing else, don't enable it yet
  • open neovim and run `:=vim.lsp.config['ocamllsp']
  • see it already contains the merged config.

```lua
vim.lsp.enable 'ocamllsp'
```

### Using nvim-lspconfig

Add this to your `nvim-lspconfig` setup.
```lua
{
'neovim/nvim-lspconfig',
config = function()
-- rest of config...

-- add this line specifically for OCaml
require('lspconfig').ocamllsp.setup {}

This comment was marked as resolved.

end,
},
```