Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Editor Setup

Fatou includes a language server (fatou lsp, stdio JSON-RPC) that any LSP client can drive. It provides formatting (whole document and range), lint and parse diagnostics with quick fixes, completion, hover, signature help, go-to definition, references, rename (of symbols, and of files and folders — moving a file rewrites the include paths that name it), document and workspace symbols, call and type hierarchy, folding ranges, document links, selection ranges, and semantic tokens. It also checks your Project.toml and Manifest.toml themselves, navigates an open Project.toml’s dependency names with inlay hints for their resolved versions, and links an open Manifest.toml’s path entries to the packages they pin.

Prerequisites

Except in the VS Code family, where the extension bundles a binary, install Fatou (see Getting Started) and make sure the fatou binary is on your PATH, or note its absolute path.

VS Code

Install the Fatou extension (jolars.fatou) from the Marketplace, or from the command line:

code --install-extension jolars.fatou

The extension activates on Julia files, starts fatou lsp for you, and registers itself as the default formatter for [julia]. Each platform-specific build bundles a matching fatou binary, so nothing else is needed; on a platform without one, it downloads a binary from GitHub releases.

To format on save, add to settings.json:

{
  "[julia]": {
    "editor.defaultFormatter": "jolars.fatou",
    "editor.formatOnSave": true
  }
}

To use a fatou you installed yourself instead of the bundled one:

{
  "fatou.executableStrategy": "environment"
}

or point at an exact binary:

{
  "fatou.executableStrategy": "path",
  "fatou.executablePath": "/usr/local/bin/fatou"
}

The extension’s README documents the available settings and their defaults.

Using Only Some Features

The formatter, linter, and language features share one server but can be turned off independently, so you can adopt just the parts you want:

  • fatou.formatting.enable — use Fatou as a formatter.
  • fatou.diagnostics.enable — show Fatou diagnostics (the linter).
  • fatou.languageFeatures.enable — hover, completion, navigation, symbols, rename, code actions, and the rest.

All three default to true. They are client-side gates, so the server keeps running and the toggles take effect without a restart. For a formatter-only setup, turn off the other two:

{
  "fatou.diagnostics.enable": false,
  "fatou.languageFeatures.enable": false
}

Turning off fatou.diagnostics.enable suppresses every diagnostic, including the parse errors that a fatou.toml [lint] selection cannot silence. The fatou.toml route stays the right tool when you want to keep parse errors but mute specific lint rules across every editor and the CLI.

VSCodium and Other Code OSS Editors

The same extension is published to the Open VSX Registry, which VSCodium and most Code OSS builds use by default:

codium --install-extension jolars.fatou

If your build ships a different registry, download the VSIX matching your OS and architecture from the Open VSX page and install it with Extensions: Install from VSIX…, or from the command line:

codium --install-extension fatou-linux-x64.vsix

Settings are identical to VS Code’s.

Cursor

Search for Fatou in the Extensions view and install it. If your Cursor build does not list it, download the VSIX for your platform from Open VSX and install it with Extensions: Install from VSIX… from the command palette.

Cursor reads the same settings.json keys as VS Code, so the format-on-save and binary-selection snippets above apply unchanged.

Neovim

Neovim 0.11+ (built-in vim.lsp.config)

Add to your config (e.g. init.lua or a file under lua/):

vim.lsp.config("fatou", {
  cmd = { "fatou", "lsp" },              -- or the absolute path to the binary
  filetypes = { "julia" },
  root_markers = { "Project.toml", "JuliaProject.toml", ".git" },
})
vim.lsp.enable("fatou")

Format on save:

vim.api.nvim_create_autocmd("BufWritePre", {
  pattern = "*.jl",
  callback = function() vim.lsp.buf.format({ name = "fatou" }) end,
})

Older Neovim (autocmd + vim.lsp.start)

vim.api.nvim_create_autocmd("FileType", {
  pattern = "julia",
  callback = function(args)
    vim.lsp.start({
      name = "fatou",
      cmd = { "fatou", "lsp" },
      root_dir = vim.fs.root(args.buf, { "Project.toml", "JuliaProject.toml", ".git" }),
    })
  end,
})

Helix

Add to ~/.config/helix/languages.toml:

[language-server.fatou]
command = "fatou"
args = ["lsp"]

[[language]]
name = "julia"
language-servers = ["fatou"]
auto-format = true

Listing language-servers replaces Helix’s default for Julia, which is LanguageServer.jl. To keep it for the features Fatou does not cover yet while Fatou handles formatting, list both and take formatting away from the other server:

[[language]]
name = "julia"
language-servers = [{ name = "julia", except-features = ["format"] }, "fatou"]
auto-format = true

hx --health julia shows which servers Helix resolved for the language.

Other LSP clients

Any client that speaks LSP over stdio works: launch fatou lsp with no arguments for *.jl files, rooted at Project.toml, JuliaProject.toml, or .git. Nothing else is required, because Fatou discovers its own configuration from the file’s directory upward.

Fatou also checks your Project.toml and Manifest.toml themselves, and publishes those findings on the file at fault whether or not it is open. If you additionally attach the server to those files (the VS Code extension does), an open one reports its TOML errors as you type, before you save.

An open Project.toml also answers on its dependency names: go-to-definition and a document link take you to the package’s entry file, hovering reports the version, kind, and resolved path the environment gave it, and an inlay hint puts each resolved version beside its UUID, so you can read off what you are actually on without opening the Manifest.toml. In an open Manifest.toml, each path entry — a package you have dev’d — is a link to that package’s Project.toml. Everything else stays off for these files — formatting a Project.toml would mean parsing TOML as Julia.

Configuration

Fatou reads its settings from a fatou.toml next to your project (see the Configuration guide), which is the recommended way to configure it in any editor, since the whole team gets the same behavior.

A client can also push settings over LSP, as initializationOptions or workspace/didChangeConfiguration, using the same schema as the file, either bare or wrapped in a "fatou" key the way VS Code namespaces settings. In Helix, for example:

[language-server.fatou.config.format]
line-width = 100

[language-server.fatou.config.lint]
ignore = ["unused-binding"]

A discovered fatou.toml shadows editor-pushed settings entirely rather than merging with them, so a project file always wins.

Unicode Symbol Input

Completion also offers the LaTeX and emoji sequences the Julia REPL substitutes on tab, so \alpha inserts α, \_1 inserts , and \:smile: inserts 😄. Type the backslash to open the list, keep typing to narrow it, and accepting an entry replaces the whole sequence, backslash included. As in the REPL, a bare \ lists the LaTeX sequences and \: opens the emoji. The table comes from the running Julia’s REPL.REPLCompletions, so it matches what your REPL does.

Two places stay quiet, so the list does not get in the way:

  • inside a string macro or command literal (r"\d", raw"\n", `ls \d`), where every backslash belongs to the literal itself;
  • on a lone escape in a plain string, so typing "\n does not offer \nabla. A second character brings the sequences back, so \nu and \alpha still work in strings and docstrings.

Check It Works

Open a .jl file containing x=1 and format the buffer: it becomes x = 1. In Neovim that is :lua vim.lsp.buf.format(), in Helix :format, and in the VS Code family Format Document. Diagnostics appear inline, and a lint finding with a fix offers it as a quick fix (:lua vim.lsp.buf.code_action(), <space>a in Helix, or the lightbulb in VS Code).

Notes

  • Document sync is incremental, and both whole-document and range formatting are supported.
  • Multiple formatters attached? In Neovim, pass { name = "fatou" } to vim.lsp.buf.format(); in Helix, strip format from the other server as shown above; in VS Code, set editor.defaultFormatter for [julia].
  • undefined-name and call-arity need project context, so the language server enables them for workspace member files even though the command line leaves them opt-in. An ignore entry still turns them off.