Language servers in src blocks
Stability: experimental (org-extensions-stability)
src_lsp lets the language server of a block's language work inside #+begin_src blocks, like otter.nvim: its diagnostics show in the block, and go to definition, hover, references and completion are answered by it. It uses the servers you configured with vim.lsp.config() and vim.lsp.enable(); list the languages it should serve:
vim.lsp.enable("lua_ls")
require("org").setup({
extensions = { src_lsp = { languages = { "lua", "python" } } },
})
Nothing is loaded and no server started until an org buffer (a file) with a block of a listed language opens. For each such buffer and language, a hidden buffer holds that language's blocks at their own line numbers (every other line blank), with the language's filetype (src_lang_modes, as in the edit buffer of org-babel), and the language servers attach to it. It follows your edits debounce ms after the last one. A small in-process server attached to the org buffer forwards requests made inside a block to those servers and maps the answers back, so the LSP functions and keys work there: vim.lsp.buf.definition() (map it to gd), K (hover), grr, gri, grt, <C-s> (signature help); a definition in another block jumps to its line in the org buffer. Outside the blocks it answers nothing, and org's own features (org-extensions-lsp included) keep working.
Completion
The forwarding server is an LSP completion source: lsp-completion, blink.cmp and nvim-cmp's LSP sources offer the server's items inside a block, and <C-x><C-o> (org's 'omnifunc') hands over to vim.lsp.omnifunc() there. completion = false turns this off.
Options
languages | `{}`
or name -> `{ servers = { ... } }` to choose the
servers: names of |vim.lsp.config()| configurations or
config tables (`{ name = ..., cmd = ... }`). Without
`servers`, every enabled configuration whose `filetypes`
has the language's filetype starts. A block whose
language has the same filetype as a listed one (`sh`
and `bash`) shares its hidden buffer. | the languages served: names ({ "lua", "sh" }), |
debounce | `200`
hidden buffers are updated (a request inside a block
updates them first). | milliseconds after the last change before the |
diagnostics | `true`
bodies (namespace `org_src_lsp`). | show the servers' diagnostics in the block |
completion | `true` | see above. |
Notes
- Each block is seen as it is in the file: noweb references (
<<name>>) are not expanded,:varvalues are not defined and:prologueis not added, so a server may report them; blocks of one language form one file whatever their:tangleor:session. - A block's common indentation is removed (unless
-iorsrc_preserve_indentation), and the comma of an escaped,*line becomes a space; positions are mapped back. - The hidden buffer is named after the org file with the language's extension (
notes.org.src-lua.lua) and never written; its root directory comes from the configuration'sroot_markers(orroot_dir) searched from the org file's directory. Some servers (lua_ls) only report diagnostics for a file inside a root. - The servers' diagnostics also stay on the hidden buffer, so a workspace-wide diagnostics list shows them under its name.
- Rename, code actions and formatting are not forwarded.
:checkhealth orglists the servers of each language and warns about a language without one, or a server whose program is missing.- otter.nvim does the same for many filetypes; enable only one of the two for org buffers.