Skip to content
Merged
Changes from 1 commit
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
37 changes: 20 additions & 17 deletions data/tutorials/getting-started/2_00_editor_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,29 +175,30 @@ vim.lsp.config['ocamllsp'] = {
vim.lsp.enable 'ocamllsp'
```

You can also use `vim.lsp` with a modular config.
See `:h lsp-config` for more detail on configuration options.

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
```
#### Modular Config With Runtimepath

You can also use `vim.lsp` with a modular config via `runtimepath`. Putting your config table inside `lsp/<some_name>.lua` or `after/lsp/<some_name>.lua` will allow Neovim to search for them automatically.

See `:h runtimepath` for more detail.

Choose a reason for hiding this comment

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

The term "modular" might confuse users with typical lua modules. They aren't. Lua modules in Neovim config only lives in lua/ directory and lsp/*.lua are just plain standalone lua files loaded by neovim directly.

I think "multi-file" can be better for clarity.

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'm not sure if that distinction is strictly necessary 🤔 I think most people understand what a modular config means in general and are more familiar with that term. I've seen lots of modular config out there but not a single multi-file config.

Copy link

@boltlessengineer boltlessengineer Sep 20, 2025

Choose a reason for hiding this comment

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

People don't use runtimepath much for lsp/general config because of historical reasons.
But now they are available and is completely different thing from structuring everything under lua/ directory.

Even though we clearly stated that they should put that file under lsp/ and not lua/lsp/, I think calling it as a "module" or saying this structure "modular" might confuse users between runtimepath and lua-modules.

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 I'll make the changes and request for another review 👍


Then run the following at the root of your config.
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`...
Your Neovim config should have the following structure now.
```text
.
├── init.lua
├── lsp
│ └── ocamllsp.lua
└── ...
```

Add your LSP config to `lsp/ocamllsp.lua`.
```lua
return {
cmd = { 'ocamllsp' },
Expand All @@ -207,7 +208,7 @@ return {
}
```

...and import them in the toplevel `init.lua`.
Then enable 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.

another nit: Can we explain what vim.lsp.enable() do here? It will help users understand the difference between configuration and enabling.

Then enable them in the toplevel init.lua. This will make Neovim to automatically start the ocamllsp for associated filetypes.
..codeblock..
To start ocamllsp manually, you can use vim.lsp.start. (see :h vim.lsp.start)

:lua vim.lsp.start(vim.lsp.config['ocamllsp'])

Not sure if we want to mention vim.lsp.start here. I think it can help users to understand what vim.lsp.enable actually does, but it can be yet another code snippet they should read and understand.

Copy link
Contributor Author

@jpoly1219 jpoly1219 Sep 20, 2025

Choose a reason for hiding this comment

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

I feel like this is a bit out of scope for the purpose of this doc. I think the curious readers will go out and research this further on their own.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe instead of calling lsp.enable with just ocamllsp we could show that you only need to call this once, with a list of languages (OCaml being just one of them), but it is fine as it is too.
Maybe add a link to the official NeoVim LSP docs? https://neovim.io/doc/user/lsp.html

Choose a reason for hiding this comment

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

We are already mentioning it. :h lsp-config should be enough.

```lua
vim.lsp.enable 'ocamllsp'
```
Expand All @@ -227,3 +228,5 @@ Add this to your `nvim-lspconfig` setup.
},
```

There is no need to pass more settings to `setup` because `nvim-lspconfig` provides reasonable defaults. See [here](https://github.com/neovim/nvim-lspconfig/blob/master/lsp/ocamllsp.lua) for more info.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we explain about tree-sitter? (with nvim-treesitter)?

local treesitter_langs = {
 'menhir', 'ocaml', 'ocaml_interface', 'ocamllex'
}

require('nvim-treesitter').install(treesitter_langs)

It isn't strictly required, although might help with performance on large files, before the LSP finishes parsing it.
Maybe leave it out for now, I'll do some experiments with using just the LSP, and see how well that works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. Let me know if you have more updates 👍

Copy link
Contributor

@edwintorok edwintorok Sep 20, 2025

Choose a reason for hiding this comment

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

I figured out how to configure tree-sitter for ocamllex, but it is quite complicated: ocaml/vim-ocaml#61 (comment).

For now I'd leave out tree-sitter from the official docs, until that PR is merged (and an equivalent PR is merged into NeoVim).

The workaround is (fixes both picking the right tree-sitter syntax and the LSP errors):

vim.filetype.add({
    extension = {
        mll = 'ocamllex',
        mly = 'menhir',
        mli = 'ocamlinterface'
    }
})

followed by the usual tree-sitter config:

local treesitter_langs = {
 'menhir', 'ocaml', 'ocaml_interface', 'ocamllex'
}

require('nvim-treesitter').install(treesitter_langs)

(This doesn't require a new release of NeoVim to work, but if your tree-sitter grammar fails to install you'll be without syntax highlighting, so I wouldn't propose it in the official docs, even though I'll start using it myself).