Vim & Neovim
elements man vim Read as markdownElements ships the same language server that powers its VS Code integration, and it works in Vim and Neovim too: diagnostics, completion, hover, go-to-definition, references, rename, and project-wide symbol search.
Elements builds no editor UI of its own. The server speaks standard LSP, and your editor's own LSP client renders everything, so your existing setup (telescope, trouble, nvim-cmp, coc, the quickfix, whatever you run) works against Elements with nothing new to learn.
Install
Nothing to do. Installing Elements installs the Vim and Neovim integration
automatically, the same way it installs the VS Code extension. No plugin manager
and no .vimrc/init.lua changes required.
- Neovim: a self-contained
plugin/elements.luais placed in your config dir (~/.config/nvim/plugin/). That directory is always on the runtimepath, so it loads whether or not you use a plugin manager (lazy.nvim, packer, ...). - Classic Vim: the plugin is installed as a native package under
~/.vim/pack/elements/start/vim-elements, which Vim auto-loads. Everything Elements installs lives underpack/elements, so it never touches a pack namespace you're using yourself.
The plugin only attaches inside an Elements project (a directory with an
.elements/id marker), so it never interferes with your other work. If you'd
rather wire it up yourself (e.g. through nvim-lspconfig), see the snippet
below.
Neovim
Neovim (0.8+) has a built-in LSP client, so this works out of the box after
install, with nothing to configure. The plugin registers the Elements server for
.jsoc, .html, .ts, .js, and .css files in an Elements project, and
every UI plugin on Neovim's built-in LSP bus picks it up automatically:
- Symbol search:
vim.lsp.buf.workspace_symbol(), or Telescope'slsp_dynamic_workspace_symbols/ fzf-lua'slsp_live_workspace_symbols. - Diagnostics: pushed project-wide (an error your edit causes in a file you
never opened still shows up). Browse them with
vim.diagnostic.setqflist(), trouble.nvim, or fzf-lua. - Completion: via nvim-cmp or blink.cmp using the built-in LSP source.
- Hover, definition, references, rename:
vim.lsp.buf.*and your keymaps.
If you drive your LSP setup through nvim-lspconfig, you can point it at the
same binary instead of using the bundled plugin:
vim.lsp.config('elements', {
cmd = { vim.fn.expand('~/elements/bin/elements-lsp'), 'stdio' },
filetypes = { 'jsoc', 'html', 'typescript', 'javascript', 'css' },
root_markers = { '.elements' },
})
vim.lsp.enable('elements')
Classic Vim
Classic Vim has no built-in LSP client, so Elements bundles one (vim-lsp) and loads it on demand. it works out of the box with nothing to install. Your own client always wins, so this only kicks in when you don't already have one:
- You already use vim-lsp: Elements registers with it; the bundled copy is never loaded.
- You use coc.nvim or ALE: Elements stays out of the way (loading a second client would run the language server twice). Configure Elements through your client instead. See below.
- You have no client: Elements loads its bundled vim-lsp automatically.
With vim-lsp, the usual commands work:
:LspDefinition
:LspHover
:LspWorkspaceSymbol
:LspDocumentDiagnostics
Escape hatches:
let g:elements_lsp_enabled = 0 " disable Elements LSP entirely
let g:elements_lsp_no_bundle = 1 " never load the bundled vim-lsp
If you use coc.nvim, add Elements to :CocConfig:
{
"languageserver": {
"elements": {
"command": "elements-lsp",
"args": ["stdio"],
"filetypes": ["jsoc", "html", "typescript", "javascript", "css"],
"rootPatterns": [".elements"]
}
}
}
Syntax highlighting
Templates are HTML with a TypeScript frontmatter and { } bindings, which
Vim's stock HTML syntax doesn't understand, such as a bare > or && in the
frontmatter, or the } closing a binding, comes out flagged as an error. Both
editors get Elements' own syntax instead, which highlights the frontmatter as
TypeScript and colors e: directives and bindings.
It applies to .html files inside an Elements project only. HTML anywhere
else on your machine keeps Vim's own syntax, untouched. Turn it off for a buffer
with :set syntax=html.
Elements also highlights .jsoc config files, in both editors.
How it connects
The plugin launches elements-lsp stdio, which ensures the project server is
running and bridges the editor's stdin/stdout to that project's LSP socket. It's
the same server, over the same protocol, that VS Code connects to. Your editor
just reaches it through a stdio child process instead of dialing the socket
directly.
Troubleshooting
- Nothing lights up in Neovim: confirm you're inside an Elements project
(
.elements/idexists) and that~/elements/binis onPATH(or setELEMENTS_SYSTEM_PATH). Check:checkhealth vim.lspand:LspInfo-style client lists with:lua =vim.lsp.get_clients(). - Nothing lights up in classic Vim: the bundled vim-lsp loads only when you
have no client of your own. If you use coc.nvim or ALE, wire Elements through
it (above); Elements won't load a second client on top. Confirm the bundle is
installed with
:echo globpath(&packpath, 'pack/*/opt/vim-lsp'), and that it loaded with:echo exists(':LspDefinition'). - A template looks full of syntax errors: Vim's stock HTML syntax is still
in charge. Check with
:set syntax?: inside a project it should readelementshtmlin Neovim, and in classic Vim:echo b:current_syntaxshould behtmlwithelementsFrontmatteramong the groups in:syntax list. If it's the stock one, confirm.elements/idexists and that~/.config/nvim/syntax/elementshtml.vim(Neovim) or~/.vim/pack/elements/start/vim-elements/(Vim) is installed. - Logs: server-side detail is in
.elements/logs/project.log.