Skip to content
Get started

Configure Vim, Neovim, or another LSP client

Use Get started to install the Python package and save its decay.eqi and run.py. The language server is a separate executable: it analyzes source while the Python environment runs your model.

These recipes were tested on Linux x86-64 with Neovim 0.12.5 and Vim 9.1 (Debian patches 1–16, 647, 678, 697) plus vim-lsp revision bbffa60cb08a6a2d67e2086a89699ab00a084fe9. Both used the server from the published Eqiora extension 0.1.1, which reports version 0.1.2. Other platforms, clients, and remote hosts have not been tested.

The extension release includes a standalone server. You can extract it without installing VS Code or compiling Eqiora. From your project directory, run these commands on Linux x86-64; they require curl, unzip and sha256sum:

Terminal windowbash
mkdir -p .tools/eqiora-0.1.1
cd .tools/eqiora-0.1.1
curl -fL https://github.com/eqiora/eqiora-vscode/releases/download/v0.1.1/eqiora-linux-x64.vsix -o eqiora-linux-x64.vsix
curl -fL https://github.com/eqiora/eqiora-vscode/releases/download/v0.1.1/eqiora-linux-x64.sha256 -o eqiora-linux-x64.sha256
sha256sum --check eqiora-linux-x64.sha256
unzip -p eqiora-linux-x64.vsix extension/server/eqiora-language-server > eqiora-language-server
chmod +x eqiora-language-server
export PATH="$PWD:$PATH"
eqiora-language-server --version
cd ../..

Launch your editor from this shell. Alternatively, use the executable’s full absolute path in the client configuration. The server matches its release, so reference pages built from newer source may describe features it lacks. The upstream.json file inside the VSIX records the Eqiora revision it was built from.

Add this to init.lua:

lua
vim.filetype.add({ extension = { eqi = "eqiora" } })
vim.api.nvim_create_autocmd("FileType", {
pattern = "eqiora",
callback = function()
vim.lsp.start({
name = "eqiora",
cmd = { "eqiora-language-server" },
root_dir = vim.fs.root(0, { "eqiora.toml", ".git" })
or vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
})
end,
})

Open decay.eqi. Use :lua vim.lsp.buf.hover() for hover, :lua vim.lsp.buf.definition() for a supported declaration reference, :lua vim.lsp.buf.document_symbol() for the outline and :lua vim.lsp.buf.format({async = false}) to format the file. Diagnostics are available through :lua vim.diagnostic.open_float().

Vim needs an LSP client plugin. Install the tested vim-lsp revision using Vim’s native package directory:

Terminal windowbash
git clone https://github.com/prabirshrestha/vim-lsp.git ~/.vim/pack/eqiora/start/vim-lsp
git -C ~/.vim/pack/eqiora/start/vim-lsp checkout bbffa60cb08a6a2d67e2086a89699ab00a084fe9

If you already manage vim-lsp with a plugin manager, use that installation. Add this to .vimrc:

vim
filetype plugin on
augroup eqiora_filetype
autocmd!
autocmd BufRead,BufNewFile *.eqi setfiletype eqiora
augroup END
function! EqioraRoot() abort
let root = lsp#utils#find_nearest_parent_file_directory(
\ lsp#utils#get_buffer_path(), ['eqiora.toml', '.git/'])
return lsp#utils#path_to_uri(empty(root) ? expand('%:p:h') : root)
endfunction
augroup eqiora_lsp
autocmd!
autocmd User lsp_setup call lsp#register_server({
\ 'name': 'eqiora',
\ 'cmd': {info->['eqiora-language-server']},
\ 'allowlist': ['eqiora'],
\ 'root_uri': {info->EqioraRoot()},
\ })
augroup END

Open decay.eqi. Use :LspHover, :LspDefinition, :LspDocumentSymbol, :LspDocumentFormatSync and :LspDocumentDiagnostics. Key mappings are optional; the commands invoke the same server operations.

Open decay.eqi from Get started and add this before its model declaration:

eqiora
dimension Rate = 1 / s;

Change the parameter declaration to parameter rate: Rate = 1;. Hover over Rate in this declaration and navigate to its definition. The outline contains the dimension and the model. The released server navigates only to top-level declarations in the same file; it cannot jump from rate inside an equation to its declaration.

Change the dimension definition to dimension Rate = m;. The evolution equation now adds terms with incompatible dimensions, so the editor reports an error. Restore 1 / s; the error disappears. Format and save the model, then run the existing script with uv run python run.py from the project directory. The parameter still means one inverse second, so the values match those in Get started.

Eqiora 0.1.3 adds the following server features. The VSIX above still contains the older server; upgrading the Python package does not replace it. To build the 0.1.3 server, download the example files, then run:

Terminal windowbash
cargo install --locked --path eqiora-source/crates/eqiora-language-server

This needs Rust and a linker. The editor recipes above were tested with the older VSIX server, not this build.

Types and values. Hover and the outline resolve static Model parameters and let expressions: after parameter n:integer=3;, the declaration variable values:array<1,n>; shows shape [3] and rank 1. Values that depend on a caller’s binding or a borrowed clock stay symbolic; the server never guesses an array size. Owned periodic Clock declarations show their period and phase in seconds. Component Fields, Parameters, and Ports, including private locals and Components that are never instantiated, get the same hover and outline types as Model declarations, and Parameter completion uses those types.

Definitions and references. Go to definition works from references to owned Fields, Parameters, Ports, Clocks, and Events, from public Ports of a Model’s direct children, and from Clock names in period(tick) and at clauses. The target may be in an imported component file or an unsaved buffer. For child.value, place the cursor on value. Find References returns every reference to the same declaration across the project’s source files, and keeps separate declarations with the same name apart. Because a.p and b.p can share one declaration, results refer to declarations rather than physical instances, and there is no rename. Qualifiers, deeper member chains, private child Ports, record members, aliases, and nested binders have no definition target.

Outline. Events, indexset and observable declarations, Component let declarations, and Model Relation families appear in the outline with their documentation text. Hovering over an Event shows its crossing expression; the server does not compute event times.

These details describe the 0.1.3 server.

Associate .eqi files with the language ID eqiora and start eqiora-language-server over stdio with no arguments. Send the project directory as rootUri or workspaceFolders during initialization. The server uses UTF-16 positions and incremental text synchronization. Keep stdout for LSP messages; stderr carries the server log.

Clients that support hierarchical document symbols receive a nested outline; others receive a flat list. Clients that declare a symbol-kind value set receive the extended symbol kinds. Diagnostics, hover, formatting, symbols, folding, and definition and reference requests are standard LSP and need no VS Code extension. Document highlights show the resolved references in the current file, without distinguishing reads from writes.

For a package project, use the directory that contains eqiora.toml as the workspace root, not a source subdirectory. The server reads the manifest and the locally installed packages; it never fetches dependencies or updates the lockfile. Prepare those with the project workflow.

The 0.1.3 server asks clients that support file watching to report changes to .eqi, eqiora.toml, and eqiora.lock, and refreshes open documents when they change. Saving an open document also reloads its project, which helps with clients that do not watch files. Unsaved editor text always takes precedence over the file on disk, and a manifest that was missing or invalid at startup is picked up after such a change. Clients that send workspace-folder changes can add or remove roots without a restart; with other clients, restart the server after changing roots.

To run a model and inspect results, use the Python workflow.

  • Server not found: run eqiora-language-server --version in the shell that launches your editor, or configure its absolute path. Installing the Python package does not install this executable.
  • Wrong project: check the workspace root and use the directory containing eqiora.toml. Missing dependencies have to be installed through the project workflow.
  • Feature missing: compare the server version and the revision in the VSIX’s upstream.json with the documentation you are reading. An older server does not have features added since its release.
  • Need logs: in Neovim, use :lua vim.lsp.set_log_level("debug") and :lua print(vim.lsp.log.get_filename()). With vim-lsp, set let g:lsp_log_file = expand('~/eqiora-lsp.log') before reproducing the issue. Turn verbose logging off afterwards.

For the official extension, see the VS Code guide. All of these clients use the same analysis from the Eqiora compiler; the recipes add no editor-specific rules.