There is no tidy editor extension and no language server yet. Every recipe below runs the binary on the file, which every editor can do.
Because tidy is fast, running the whole binary on save costs a few milliseconds — about the same as an extension would, without one existing.
VS Code
Install an extension that can run a command on save, such as Run on Save (emeraldwalk.RunOnSave), then:
{
"emeraldwalk.runonsave": {
"commands": [
{
"match": "\\.(js|jsx|mjs|cjs|ts|tsx|mts|cts|css|scss|less|html|vue|hbs|md|json|jsonc|yaml|yml|toml|xml|svg|graphql)$",
"cmd": "tidy up ${file}"
}
]
}
}Turn off the built-in formatter for those languages so the two do not both write:
{
"editor.formatOnSave": false
}Zed
Zed can format with an external command, per language:
{
"languages": {
"TypeScript": {
"formatter": {
"external": {
"command": "tidy",
"arguments": ["--stdin-filepath", "{buffer_path}"]
}
}
}
}
}Repeat the block for each language. --stdin-filepath is what makes it work: tidy reads the buffer from stdin and uses the path only to pick the language and find the config files.
Neovim
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = { "*.ts", "*.tsx", "*.js", "*.jsx", "*.css", "*.scss", "*.html", "*.vue", "*.md", "*.json", "*.yaml", "*.yml", "*.toml" },
callback = function(args)
local view = vim.fn.winsaveview()
vim.cmd("silent %!tidy --stdin-filepath " .. vim.fn.shellescape(args.file))
if vim.v.shell_error ~= 0 then
vim.cmd("silent undo")
end
vim.fn.winrestview(view)
end,
})The shell_error check matters: without it, a file that does not parse is replaced by tidy's error message. Saving the view and restoring it keeps the cursor where it was.
With conform.nvim:
require("conform").setup({
formatters = {
tidy = {
command = "tidy",
args = { "--stdin-filepath", "$FILENAME" },
stdin = true,
},
},
formatters_by_ft = {
typescript = { "tidy" },
javascript = { "tidy" },
css = { "tidy" },
html = { "tidy" },
markdown = { "tidy" },
yaml = { "tidy" },
json = { "tidy" },
},
format_on_save = { timeout_ms = 2000 },
})JetBrains
Settings → Tools → File Watchers → + → <custom>:
| Field | Value |
|---|---|
| File type | the type you want, one watcher each |
| Program | tidy |
| Arguments | up $FilePath$ |
| Output paths to refresh | $FilePath$ |
| Auto-save edited files | off |
Turn off "Auto-save edited files to trigger the watcher", or the watcher runs while you type.
Which flag to use
| Form | When |
|---|---|
tidy up <path> |
The editor can run a command on a saved file. |
tidy --stdin-filepath <path> |
The editor pipes the buffer in and takes stdout. Formats unsaved buffers too. |
Prefer the stdin form where the editor supports it: it never writes a half-formatted file if something goes wrong, and it works before the first save.