Skip to content
Saule
Docs

Editor Support

Every editor plugin is a thin client. The intelligence lives in saule-lsp, a Language Server Protocol implementation that ships with the toolchain, so all three editors get the same feature set:

  • Diagnostics — lex, parse, semantic, and type errors, live on every edit
  • Hover — types and signatures for locals, functions, methods, classes, enums, and stdlib members, with generic substitution
  • Go-to-definition and find-all-references
  • Document highlights and document symbols (outline / breadcrumbs)
  • Inlay hints — inferred local types and parameter-name labels
  • Signature help — parameter popups while typing call arguments
  • Formatting — full-document and range formatting

Each plugin lives in its own repository:

Editor Repository
VS Code lauriszz123/saule-vscode
Neovim lauriszz123/saule-nvim
IntelliJ IDEA lauriszz123/saule-intellij

All three plugins need the binary, and the installer puts it on your PATH along with the saule CLI:

Terminal window
curl -fsSL https://lauriszz123.github.io/saule/install.sh | sh

Plugins find it on your PATH, then in ~/.saule/bin. They do not run a binary from the project you open, because a repository can contain a target/debug/saule-lsp of its own. If you work on Saule itself and want your own build, turn on the setting for it: saule.allowProjectBuild in VS Code, vim.g.saule_use_project_build = true in Neovim, or Run the binaries from a project’s own target/ folder in IntelliJ.

Syntax highlighting and indentation are client-side, so they work even without the server. Everything in the list above does not.

Or search for Saule in the Extensions view, or install it from a terminal:

Terminal window
code --install-extension saule.saule
Setting Default Purpose
saule.server.path "" Absolute path to saule-lsp. Empty means auto-detect.
saule.cli.path "" Absolute path to saule, used by the run commands. Empty means auto-detect.
saule.toolchainDir "" Directory holding both binaries, used when no explicit path is set.
saule.allowProjectBuild false Use a project’s own target/ build. Opening a folder then runs any target/debug/saule-lsp it contains, so this is only for working on Saule itself.
saule.server.extraArgs [] Extra CLI arguments for the server.
saule.trace.server "off" LSP message tracing — off, messages, or verbose.
  • Saule: Run File / Saule: Run Project — saule run on the active file or from the workspace root.
  • Saule: Restart Language Server — relaunch the server, e.g. after a fresh cargo build.
  • Saule: Show Language Server Output — open the server’s output channel.

The repository is a plugin root, so any plugin manager installs it directly. With lazy.nvim:

return {
{ "lauriszz123/saule-nvim", ft = "saule" },
}

Then enable the language server. On Neovim 0.11+ the bundled lsp/saule.lua definition is picked up from the runtimepath:

vim.lsp.enable("saule")

With nvim-lspconfig (including NvChad), register it through the helper instead, which picks up your shared on_attach and capabilities:

require("saule.lsp").setup()

Either way the server is found on $PATH or in ~/.saule/bin, which the installer covers. vim.g.saule_lsp_path overrides it.

Works in Community and Ultimate (and other JetBrains IDEs) — it rides on the open-source LSP4IJ client rather than the Ultimate-only native LSP API.

Or install it from inside the IDE: Settings ▸ Plugins ▸ Marketplace, then search for Saule. The IDE offers to install LSP4IJ along with it.

Beyond the shared LSP features it adds:

  • File ▸ New ▸ Project… ▸ Saule — scaffolds exactly what saule init produces.
  • Run configurations — the gutter icon on any .sau file runs the project if the file sits inside a saule.config tree, and the single file otherwise.

Colouring, brace matching, and indent-while-typing come from a native IntelliJ lexer rather than the server, so they stay responsive.

The TextMate grammar is written once, in the language repository at grammar/saule.tmLanguage.json, next to the lexer it has to agree with. This site reads it at build time, and the VS Code extension ships a copy that npm run sync:grammar refreshes — so a keyword added in one place shows up everywhere.