Format Document and Format on save (Settings > Editor) run a command line formatter over the file. Tori does not ship any formatter: it runs the one your project already uses, so what you see on save is what CI checks. Settings > Formatters has a card for each with its version and an on or off switch.
Supported formatters
| Formatter | Languages | Picked up from | Install |
|---|---|---|---|
| Biome | JS, TS, JSON, CSS, GraphQL | biome.json, biome.jsonc |
npm install --save-dev --save-exact @biomejs/biome |
| oxfmt | JS, TS and more | .oxfmtrc.json, .oxfmtrc.jsonc, oxfmt.config.ts |
npm install --save-dev oxfmt |
| Prettier | Whatever its plugins cover | .prettierrc*, prettier.config.*, or prettier in package.json |
npm install --save-dev prettier |
| Black | Python | [tool.black] in pyproject.toml |
pip install black in the project’s virtualenv |
| Ruff | Python | ruff.toml, .ruff.toml, or [tool.ruff] in pyproject.toml |
pip install ruff in the project’s virtualenv |
| StyLua | Lua, Luau | stylua.toml, .stylua.toml |
brew install stylua |
| gofmt | Go | Only when you name it (below) | Ships with Go |
| shfmt | Shell | Only when you name it | brew install shfmt |
| Vite+ | JS, TS and more | Only when you name it | The project’s own vp |
Biome, oxfmt, Prettier, Black, Ruff and Vite+ run the project’s own copy,
from the nearest node_modules/.bin, .venv/bin or venv/bin, else your
PATH. StyLua, gofmt and shfmt come from your PATH. A formatter installed
after Tori started shows up once you reopen Tori.
Languages with a language server but none of these (Rust, C and C++, and others) still get Format Document from the server, for example rustfmt through rust-analyzer. Format on save only runs the formatters above.
Which formatter a file gets
A project with no formatter config gets no formatter, unless you name one: formatting with a tool’s defaults puts a surprise diff in somebody’s pull request. Otherwise Tori asks, in order, and the first answer wins:
- The project’s own pick,
format.byExtensionin<project>/.tori/settings.json. - A formatter config file in a folder between the file and the project root, nearest folder first.
- Your pick,
format.byExtensionin~/.config/tori/settings.json. - The language server’s formatting (Format Document only).
{ "format": { "byExtension": { "go": "gofmt", "sh": "shfmt", "py": "ruff" } } }Keys are file extensions and values are formatter ids. gofmt, shfmt and Vite+ are only ever used this way, because no file in a repo says it formats with them.
When one folder has configs for several formatters, the one that names the
file’s language goes first. A pyproject.toml with both [tool.black] and
[tool.ruff] formats with Black, since a project set up that way usually
lints with Ruff. A formatter that says “not my kind of file” hands it to the
next one, so a .rs file in a repo with a .prettierrc still reaches
rust-analyzer. A real failure, like a syntax error, stops and is shown.
If the picked formatter is not installed, Tori says so instead of skipping
it, so a fresh clone before npm install does not look like a project that
does not format.
Turning one off
The card’s switch writes format.disabled in ~/.config/tori/settings.json.
A disabled formatter is skipped and the file goes on to the next one.
{ "format": { "disabled": ["biome"] } }Adding a formatter
Any formatter that reads the file on stdin and writes the result to stdout
can be added as a TOML file in ~/.config/tori/packs/formatters/, or from the
catalog with Add a formatter. This one adds clang-format:
schema_version = 1id = "clang-format"label = "clang-format"extensions = ["c", "h", "cc", "cpp", "hpp"]
[markers]files = [".clang-format", "_clang-format"]
[launch]kind = "path"program = "clang-format"args = ["--assume-filename={file}"]{file} becomes the file’s path, which is how a formatter picks its parser
and finds its settings. [markers] takes exact files, filename
prefixes, or keys inside a JSON or TOML file ({ file = "pyproject.toml", key = "tool.black" }). Use kind = "project_bin" for a formatter the
project installs itself. Restart Tori after adding the file.
A file may not reuse a built in formatter’s id. To keep Prettier to web
files, copy it under a new id, add an extensions list, and switch the built
in Prettier off on its card. A broken file is listed under Needs fixing in
Settings > Formatters, and the built in keeps running.
Missing a formatter?
Request a formatter. Say which tool, the config file that marks a project as using it, and whether it can read from stdin.