1use crate::config::FormatterConfig;
2
3#[derive(Debug, Clone, Copy)]
4pub struct FormatterPresetMetadata {
5 pub name: &'static str,
6 pub url: &'static str,
7 pub description: &'static str,
8 pub cmd: &'static str,
9 pub args: &'static [&'static str],
10 pub stdin: bool,
11 pub supported_languages: &'static [&'static str],
12}
13
14impl FormatterPresetMetadata {
15 pub fn to_formatter_config(self) -> FormatterConfig {
16 FormatterConfig {
17 cmd: self.cmd.to_string(),
18 args: self.args.iter().map(ToString::to_string).collect(),
19 enabled: true,
20 stdin: self.stdin,
21 }
22 }
23}
24
25const PRESETS: &[FormatterPresetMetadata] = &[
26 FormatterPresetMetadata {
27 name: "air",
28 url: "https://github.com/posit-dev/air",
29 description: "R formatter for reproducible style conventions.",
30 cmd: "air",
31 args: &["format", "{}"],
32 stdin: false,
33 supported_languages: &["r"],
34 },
35 FormatterPresetMetadata {
36 name: "alejandra",
37 url: "https://kamadorueda.com/alejandra/",
38 description: "Uncompromising Nix formatter.",
39 cmd: "alejandra",
40 args: &[],
41 stdin: true,
42 supported_languages: &["nix"],
43 },
44 FormatterPresetMetadata {
45 name: "asmfmt",
46 url: "https://github.com/klauspost/asmfmt",
47 description: "Go assembler formatter.",
48 cmd: "asmfmt",
49 args: &[],
50 stdin: true,
51 supported_languages: &["asm", "assembly"],
52 },
53 FormatterPresetMetadata {
54 name: "astyle",
55 url: "https://astyle.sourceforge.net/astyle.html",
56 description: "Formatter for C/C++/Java/C# source code.",
57 cmd: "astyle",
58 args: &["--quiet"],
59 stdin: true,
60 supported_languages: &["c", "cpp", "c++", "java", "csharp", "c#"],
61 },
62 FormatterPresetMetadata {
63 name: "autocorrect",
64 url: "https://github.com/huacnlee/autocorrect",
65 description: "Formatter/linter for CJK spacing and punctuation.",
66 cmd: "autocorrect",
67 args: &["--stdin"],
68 stdin: true,
69 supported_languages: &["text", "txt", "markdown", "md"],
70 },
71 FormatterPresetMetadata {
72 name: "bean-format",
73 url: "https://beancount.github.io/docs/running_beancount_and_generating_reports.html#bean-format",
74 description: "Reformat Beancount files to align posting amounts.",
75 cmd: "bean-format",
76 args: &["-"],
77 stdin: true,
78 supported_languages: &["beancount", "bean"],
79 },
80 FormatterPresetMetadata {
81 name: "bibtex-tidy",
82 url: "https://github.com/FlamingTempura/bibtex-tidy",
83 description: "Cleaner and formatter for BibTeX files.",
84 cmd: "bibtex-tidy",
85 args: &["--quiet"],
86 stdin: true,
87 supported_languages: &["bibtex", "bib"],
88 },
89 FormatterPresetMetadata {
90 name: "beautysh",
91 url: "https://github.com/lovesegfault/beautysh",
92 description: "Bash beautifier for shell scripts.",
93 cmd: "beautysh",
94 args: &["-"],
95 stdin: true,
96 supported_languages: &["sh", "bash", "shell"],
97 },
98 FormatterPresetMetadata {
99 name: "black",
100 url: "https://github.com/psf/black",
101 description: "Opinionated Python formatter.",
102 cmd: "black",
103 args: &["-"],
104 stdin: true,
105 supported_languages: &["python", "py"],
106 },
107 FormatterPresetMetadata {
108 name: "clang-format",
109 url: "https://clang.llvm.org/docs/ClangFormat.html",
110 description: "Formatter for C-family languages.",
111 cmd: "clang-format",
112 args: &["-"],
113 stdin: true,
114 supported_languages: &[
115 "c",
116 "h",
117 "cpp",
118 "c++",
119 "hpp",
120 "cc",
121 "cxx",
122 "objc",
123 "objective-c",
124 "obj-c",
125 "java",
126 "csharp",
127 "c#",
128 ],
129 },
130 FormatterPresetMetadata {
131 name: "cmake-format",
132 url: "https://github.com/cheshirekow/cmake_format",
133 description: "Formatter for CMake listfiles.",
134 cmd: "cmake-format",
135 args: &["-"],
136 stdin: true,
137 supported_languages: &["cmake"],
138 },
139 FormatterPresetMetadata {
140 name: "bpfmt",
141 url: "https://source.android.com/docs/setup/reference/androidbp",
142 description: "Android Blueprint file formatter.",
143 cmd: "bpfmt",
144 args: &["-w", "{}"],
145 stdin: false,
146 supported_languages: &["bp", "blueprint"],
147 },
148 FormatterPresetMetadata {
149 name: "bsfmt",
150 url: "https://github.com/rokucommunity/brighterscript-formatter",
151 description: "Formatter for BrighterScript and BrightScript.",
152 cmd: "bsfmt",
153 args: &["{}", "--write"],
154 stdin: false,
155 supported_languages: &["brs", "brighterscript", "brightscript"],
156 },
157 FormatterPresetMetadata {
158 name: "buf",
159 url: "https://buf.build/docs/reference/cli/buf/format",
160 description: "Formatter for Protocol Buffer files.",
161 cmd: "buf",
162 args: &["format", "-w", "{}"],
163 stdin: false,
164 supported_languages: &["proto", "protobuf"],
165 },
166 FormatterPresetMetadata {
167 name: "buildifier",
168 url: "https://github.com/bazelbuild/buildtools/tree/main/buildifier",
169 description: "Formatter for Bazel BUILD and .bzl files.",
170 cmd: "buildifier",
171 args: &["-path", "{}", "-"],
172 stdin: true,
173 supported_languages: &["bazel", "bzl", "starlark"],
174 },
175 FormatterPresetMetadata {
176 name: "cabal-fmt",
177 url: "https://hackage.haskell.org/package/cabal-fmt",
178 description: "Formatter for Haskell .cabal files.",
179 cmd: "cabal-fmt",
180 args: &["--inplace", "{}"],
181 stdin: false,
182 supported_languages: &["cabal", "haskell"],
183 },
184 FormatterPresetMetadata {
185 name: "cljfmt",
186 url: "https://github.com/weavejester/cljfmt",
187 description: "Detect and fix formatting errors in Clojure code.",
188 cmd: "cljfmt",
189 args: &["fix", "-"],
190 stdin: true,
191 supported_languages: &["clojure", "clj", "cljs", "cljc", "edn"],
192 },
193 FormatterPresetMetadata {
194 name: "cue-fmt",
195 url: "https://cuelang.org",
196 description: "Format CUE files.",
197 cmd: "cue",
198 args: &["fmt", "-"],
199 stdin: true,
200 supported_languages: &["cue"],
201 },
202 FormatterPresetMetadata {
203 name: "dfmt",
204 url: "https://github.com/dlang-community/dfmt",
205 description: "Formatter for D source code.",
206 cmd: "dfmt",
207 args: &[],
208 stdin: true,
209 supported_languages: &["d"],
210 },
211 FormatterPresetMetadata {
212 name: "efmt",
213 url: "https://github.com/sile/efmt",
214 description: "Erlang code formatter.",
215 cmd: "efmt",
216 args: &["-"],
217 stdin: true,
218 supported_languages: &["erlang", "erl"],
219 },
220 FormatterPresetMetadata {
221 name: "fish_indent",
222 url: "https://fishshell.com/docs/current/cmds/fish_indent.html",
223 description: "Indent or prettify fish shell scripts.",
224 cmd: "fish_indent",
225 args: &[],
226 stdin: true,
227 supported_languages: &["fish"],
228 },
229 FormatterPresetMetadata {
230 name: "fixjson",
231 url: "https://github.com/rhysd/fixjson",
232 description: "JSON fixer using relaxed JSON5 parsing.",
233 cmd: "fixjson",
234 args: &[],
235 stdin: true,
236 supported_languages: &["json", "json5"],
237 },
238 FormatterPresetMetadata {
239 name: "gdformat",
240 url: "https://github.com/Scony/godot-gdscript-toolkit",
241 description: "Formatter for Godot GDScript.",
242 cmd: "gdformat",
243 args: &["-"],
244 stdin: true,
245 supported_languages: &["gdscript", "gd"],
246 },
247 FormatterPresetMetadata {
248 name: "google-java-format",
249 url: "https://github.com/google/google-java-format",
250 description: "Reformats Java code to Google Java Style.",
251 cmd: "google-java-format",
252 args: &["-"],
253 stdin: true,
254 supported_languages: &["java"],
255 },
256 FormatterPresetMetadata {
257 name: "gleam",
258 url: "https://github.com/gleam-lang/gleam",
259 description: "Format Gleam source files.",
260 cmd: "gleam",
261 args: &["format", "--stdin"],
262 stdin: true,
263 supported_languages: &["gleam"],
264 },
265 FormatterPresetMetadata {
266 name: "gofmt",
267 url: "https://pkg.go.dev/cmd/gofmt",
268 description: "Go formatter.",
269 cmd: "gofmt",
270 args: &[],
271 stdin: true,
272 supported_languages: &["go", "golang"],
273 },
274 FormatterPresetMetadata {
275 name: "gofumpt",
276 url: "https://github.com/mvdan/gofumpt",
277 description: "Stricter formatting for Go.",
278 cmd: "gofumpt",
279 args: &[],
280 stdin: true,
281 supported_languages: &["go", "golang"],
282 },
283 FormatterPresetMetadata {
284 name: "hurlfmt",
285 url: "https://hurl.dev/",
286 description: "Formatter for Hurl files.",
287 cmd: "hurlfmt",
288 args: &[],
289 stdin: true,
290 supported_languages: &["hurl"],
291 },
292 FormatterPresetMetadata {
293 name: "jsonnetfmt",
294 url: "https://github.com/google/go-jsonnet",
295 description: "Format Jsonnet files.",
296 cmd: "jsonnetfmt",
297 args: &["-"],
298 stdin: true,
299 supported_languages: &["jsonnet", "libsonnet"],
300 },
301 FormatterPresetMetadata {
302 name: "ktfmt",
303 url: "https://github.com/facebook/ktfmt",
304 description: "Kotlin formatter for community style conventions.",
305 cmd: "ktfmt",
306 args: &["-"],
307 stdin: true,
308 supported_languages: &["kotlin", "kt", "kts"],
309 },
310 FormatterPresetMetadata {
311 name: "leptosfmt",
312 url: "https://github.com/bram209/leptosfmt",
313 description: "Formatter for Leptos `view!` macro code.",
314 cmd: "leptosfmt",
315 args: &["--stdin"],
316 stdin: true,
317 supported_languages: &["rust", "rs"],
318 },
319 FormatterPresetMetadata {
320 name: "mdformat",
321 url: "https://github.com/executablebooks/mdformat",
322 description: "Opinionated Markdown formatter.",
323 cmd: "mdformat",
324 args: &["-"],
325 stdin: true,
326 supported_languages: &["md", "markdown", "qmd", "rmd"],
327 },
328 FormatterPresetMetadata {
329 name: "nixfmt",
330 url: "https://github.com/NixOS/nixfmt",
331 description: "Official formatter for Nix code.",
332 cmd: "nixfmt",
333 args: &[],
334 stdin: true,
335 supported_languages: &["nix"],
336 },
337 FormatterPresetMetadata {
338 name: "nginxfmt",
339 url: "https://github.com/slomkowski/nginx-config-formatter",
340 description: "Formatter for nginx configuration files.",
341 cmd: "nginxfmt",
342 args: &["-"],
343 stdin: true,
344 supported_languages: &["nginx", "nginxconf"],
345 },
346 FormatterPresetMetadata {
347 name: "prettier",
348 url: "https://prettier.io/",
349 description: "Opinionated formatter for web, JSON, YAML, and Markdown ecosystems.",
350 cmd: "prettier",
351 args: &["--stdin-filepath", "{}"],
352 stdin: true,
353 supported_languages: &[
354 "javascript",
355 "js",
356 "typescript",
357 "ts",
358 "jsx",
359 "tsx",
360 "json",
361 "jsonc",
362 "yaml",
363 "yml",
364 "markdown",
365 "md",
366 "css",
367 "scss",
368 "less",
369 "html",
370 "vue",
371 "svelte",
372 "graphql",
373 "gql",
374 ],
375 },
376 FormatterPresetMetadata {
377 name: "pycln",
378 url: "https://github.com/hadialqattan/pycln",
379 description: "Removes unused Python imports.",
380 cmd: "pycln",
381 args: &["--silence", "-"],
382 stdin: true,
383 supported_languages: &["python", "py"],
384 },
385 FormatterPresetMetadata {
386 name: "pyproject-fmt",
387 url: "https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt",
388 description: "Formatter for pyproject.toml with comment support.",
389 cmd: "pyproject-fmt",
390 args: &["-"],
391 stdin: true,
392 supported_languages: &["toml"],
393 },
394 FormatterPresetMetadata {
395 name: "racketfmt",
396 url: "https://docs.racket-lang.org/fmt",
397 description: "Formatter for Racket language files.",
398 cmd: "raco",
399 args: &["fmt"],
400 stdin: true,
401 supported_languages: &["racket", "rkt"],
402 },
403 FormatterPresetMetadata {
404 name: "rubyfmt",
405 url: "https://github.com/fables-tales/rubyfmt",
406 description: "Ruby autoformatter written in Rust.",
407 cmd: "rubyfmt",
408 args: &[],
409 stdin: true,
410 supported_languages: &["ruby", "rb"],
411 },
412 FormatterPresetMetadata {
413 name: "ruff",
414 url: "https://docs.astral.sh/ruff/",
415 description: "Python formatter via Ruff.",
416 cmd: "ruff",
417 args: &["format", "--stdin-filename", "stdin.py", "-"],
418 stdin: true,
419 supported_languages: &["python", "py"],
420 },
421 FormatterPresetMetadata {
422 name: "rufo",
423 url: "https://github.com/ruby-formatter/rufo",
424 description: "Opinionated Ruby formatter.",
425 cmd: "rufo",
426 args: &[],
427 stdin: true,
428 supported_languages: &["ruby", "rb"],
429 },
430 FormatterPresetMetadata {
431 name: "shfmt",
432 url: "https://github.com/mvdan/sh",
433 description: "Shell script formatter.",
434 cmd: "shfmt",
435 args: &["-"],
436 stdin: true,
437 supported_languages: &["sh", "bash", "zsh", "ksh", "shell"],
438 },
439 FormatterPresetMetadata {
440 name: "sqlfmt",
441 url: "https://sqlfmt.com",
442 description: "SQL formatter inspired by Black.",
443 cmd: "sqlfmt",
444 args: &["-"],
445 stdin: true,
446 supported_languages: &["sql"],
447 },
448 FormatterPresetMetadata {
449 name: "styler",
450 url: "https://styler.r-lib.org/",
451 description: "R formatter via styler::style_file.",
452 cmd: "Rscript",
453 args: &["-e", "styler::style_file('{}')"],
454 stdin: false,
455 supported_languages: &["r"],
456 },
457 FormatterPresetMetadata {
458 name: "taplo",
459 url: "https://taplo.tamasfe.dev/",
460 description: "TOML formatter.",
461 cmd: "taplo",
462 args: &["format", "-"],
463 stdin: true,
464 supported_languages: &["toml"],
465 },
466 FormatterPresetMetadata {
467 name: "tclfmt",
468 url: "https://github.com/nmoroze/tclint",
469 description: "Formatter for Tcl scripts (from tclint).",
470 cmd: "tclfmt",
471 args: &["-"],
472 stdin: true,
473 supported_languages: &["tcl"],
474 },
475 FormatterPresetMetadata {
476 name: "tex-fmt",
477 url: "https://github.com/WGUNDERWOOD/tex-fmt",
478 description: "Fast formatter for LaTeX source files.",
479 cmd: "tex-fmt",
480 args: &["-s"],
481 stdin: true,
482 supported_languages: &["tex", "latex"],
483 },
484 FormatterPresetMetadata {
485 name: "terraform-fmt",
486 url: "https://developer.hashicorp.com/terraform/cli/commands/fmt",
487 description: "Terraform formatter.",
488 cmd: "terraform",
489 args: &["fmt", "-no-color", "-"],
490 stdin: true,
491 supported_languages: &["terraform", "hcl", "tf"],
492 },
493 FormatterPresetMetadata {
494 name: "typstyle",
495 url: "https://github.com/Enter-tainer/typstyle",
496 description: "Formatter for Typst code.",
497 cmd: "typstyle",
498 args: &[],
499 stdin: true,
500 supported_languages: &["typst"],
501 },
502 FormatterPresetMetadata {
503 name: "yamlfmt",
504 url: "https://github.com/google/yamlfmt",
505 description: "YAML formatter.",
506 cmd: "yamlfmt",
507 args: &["-"],
508 stdin: true,
509 supported_languages: &["yaml", "yml"],
510 },
511 FormatterPresetMetadata {
512 name: "yamlfix",
513 url: "https://github.com/lyz-code/yamlfix",
514 description: "YAML formatter preserving comments.",
515 cmd: "yamlfix",
516 args: &["-"],
517 stdin: true,
518 supported_languages: &["yaml", "yml"],
519 },
520 FormatterPresetMetadata {
521 name: "yq",
522 url: "https://github.com/mikefarah/yq",
523 description: "YAML processor in pretty-print mode.",
524 cmd: "yq",
525 args: &["-P", "-"],
526 stdin: true,
527 supported_languages: &["yaml", "yml"],
528 },
529];
530
531pub fn formatter_preset_metadata(name: &str) -> Option<&'static FormatterPresetMetadata> {
532 PRESETS.iter().find(|preset| preset.name == name)
533}
534
535pub fn all_formatter_preset_metadata() -> &'static [FormatterPresetMetadata] {
536 PRESETS
537}
538
539pub fn formatter_presets_for_language(language: &str) -> Vec<&'static FormatterPresetMetadata> {
540 let normalized = language.trim().to_ascii_lowercase().replace('_', "-");
541 PRESETS
542 .iter()
543 .filter(|preset| {
544 preset
545 .supported_languages
546 .iter()
547 .any(|supported| *supported == normalized)
548 })
549 .collect()
550}
551
552pub fn get_formatter_preset(name: &str) -> Option<FormatterConfig> {
553 formatter_preset_metadata(name)
554 .copied()
555 .map(|meta| meta.to_formatter_config())
556}
557
558pub fn formatter_preset_supported_languages(name: &str) -> Option<&'static [&'static str]> {
559 formatter_preset_metadata(name).map(|meta| meta.supported_languages)
560}
561
562pub fn formatter_preset_names() -> &'static [&'static str] {
563 &[
564 "air",
565 "alejandra",
566 "asmfmt",
567 "astyle",
568 "autocorrect",
569 "bean-format",
570 "bibtex-tidy",
571 "beautysh",
572 "black",
573 "bpfmt",
574 "bsfmt",
575 "buf",
576 "buildifier",
577 "cabal-fmt",
578 "clang-format",
579 "cljfmt",
580 "cmake-format",
581 "cue-fmt",
582 "dfmt",
583 "efmt",
584 "fish_indent",
585 "fixjson",
586 "gdformat",
587 "google-java-format",
588 "gleam",
589 "gofmt",
590 "gofumpt",
591 "hurlfmt",
592 "jsonnetfmt",
593 "ktfmt",
594 "leptosfmt",
595 "mdformat",
596 "nixfmt",
597 "nginxfmt",
598 "prettier",
599 "pycln",
600 "pyproject-fmt",
601 "racketfmt",
602 "rubyfmt",
603 "ruff",
604 "rufo",
605 "shfmt",
606 "sqlfmt",
607 "styler",
608 "tclfmt",
609 "taplo",
610 "tex-fmt",
611 "terraform-fmt",
612 "typstyle",
613 "yamlfix",
614 "yamlfmt",
615 "yq",
616 ]
617}