diff --git a/Cargo.toml b/Cargo.toml index 8b8d473..90c6656 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,5 +23,5 @@ tempfile = "3.10.1" [dev-dependencies] test-with = { version = "0.12.6", default-features = false, features = [ - "executable" + "executable", ] } diff --git a/README.md b/README.md index 5f91349..88c9f8d 100644 --- a/README.md +++ b/README.md @@ -58,40 +58,45 @@ mdsf init > > Only formatters that are already installed will be used. -| Language | Formatters | -| ----------- | ------------------------------------------------------------- | -| Blade | `blade-formatter` | -| C | `clang-format` | -| Cpp | `clang-format` | -| Crystal | `crystal_format` | -| CSharp | `clang-format` | -| CSS | `prettier` | -| Dart | `dart_format` | -| Elm | `elm-format` | -| Elixir | `mix_format` | -| Gleam | `gleam_format` | -| Go | `gofmt`, `gofumpt` | -| GraphQL | `prettier` | -| HTML | `prettier` | -| Java | `clang-format` | -| JavaScript | `prettier`, `biome`, `clang-format`, `deno_fmt` | -| JSON | `prettier`, `biome`, `clang-format`, `deno_fmt` | -| Just | `just_fmt` | -| Lua | `stylua` | -| Nim | `nimpretty` | -| Objective C | `clang-format` | -| OCaml | `ocamlformat` | -| Protobuf | `clang-format` | -| Python | `ruff`, `black`, `blue`, `yapf`, `autopep8`, `isort`, `usort` | -| ReScript | `rescript_format` | -| Roc | `roc_format` | -| Ruby | `rubocop` | -| Rust | `rustfmt` | -| Shell | `shfmt` | -| SQL | `sqlfluff`, `sql-formatter` | -| TOML | `taplo` | -| TypeScript | `prettier`, `biome`, `deno_fmt` | -| Vue | `prettier` | -| Xml | `xmllint` | -| YAML | `prettier` | -| Zig | `zigfmt` | + + +| Language | Formatters | +| ---------- | ------------------------------------------------------------- | +| Blade | `blade-formatter` | +| C | `clang-format` | +| CSharp | `clang-format` | +| Cpp | `clang-format` | +| Crystal | `crystal_format` | +| Css | `prettier` | +| Dart | `dart_format` | +| Elixir | `mix_format` | +| Elm | `elm-format` | +| Gleam | `gleam_format` | +| Go | `gofmt`, `gofumpt` | +| GraphQL | `prettier` | +| Html | `prettier` | +| Java | `clang-format` | +| JavaScript | `biome`, `clang-format`, `deno_fmt`, `prettier` | +| Json | `biome`, `clang-format`, `deno_fmt`, `prettier` | +| Just | `just_fmt` | +| Lua | `stylua` | +| Markdown | `prettier` | +| Nim | `nimpretty` | +| OCaml | `ocamlformat` | +| ObjectiveC | `clang-format` | +| Protobuf | `clang-format` | +| Python | `autopep8`, `black`, `blue`, `isort`, `ruff`, `usort`, `yapf` | +| ReScript | `rescript_format` | +| Roc | `roc_format` | +| Ruby | `rubocop` | +| Rust | `rustfmt` | +| Shell | `shfmt` | +| Sql | `sql-formatter`, `sqlfluff` | +| Toml | `taplo` | +| TypeScript | `biome`, `deno_fmt`, `prettier` | +| Vue | `prettier` | +| Xml | `xmllint` | +| Yaml | `prettier` | +| Zig | `zigfmt` | + + diff --git a/justfile b/justfile index 04fe80c..889caff 100644 --- a/justfile +++ b/justfile @@ -36,6 +36,7 @@ precommit: just lint just test cargo run -- schema + node scripts/update-supported-languages.mjs npx --yes prettier --write . git restore tests/ typos . diff --git a/scripts/update-supported-languages.mjs b/scripts/update-supported-languages.mjs new file mode 100644 index 0000000..8c4b20e --- /dev/null +++ b/scripts/update-supported-languages.mjs @@ -0,0 +1,112 @@ +import fs from "fs/promises"; + +async function getVersion() { + const content = await fs + .readFile("Cargo.toml") + .then((data) => data.toString()); + + const line = content.split("\n").find((l) => l.startsWith("version =")); + + return line.split('"')[1]; +} + +/** + * @param version {string} + */ +function loadSchema(version) { + return fs + .readFile(`schemas/v${version}/mdsf.schema.json`) + .then((data) => data.toString()) + .then(JSON.parse) + .then((data) => { + if (!data || typeof data !== "object") { + throw new Error("Expected schema to be an object"); + } + + return data; + }); +} + +/** + * @param schema {Awaited>} + */ +function createLanguageTable(schema) { + const languageHeading = "Language"; + let languageWidth = languageHeading.length; + + const formatterHeading = "Formatters"; + let formatterWidth = formatterHeading.length; + + /** @type {Map} */ + const languages = new Map(); + + for (const [key, value] of Object.entries(schema.definitions)) { + if (key.startsWith("MdsfFormatter_") || key.startsWith("Lang_")) { + continue; + } + + const formatterLine = value.enum + .sort() + .map((f) => "`" + f + "`") + .join(", "); + + languageWidth = Math.max(languageWidth, key.length); + formatterWidth = Math.max(formatterWidth, formatterLine.length); + + languages.set(key, formatterLine); + } + + /** @type {string[]} */ + const lines = []; + + for (const [key, value] of languages) { + const line = `| ${key.padEnd(languageWidth, " ")} | ${value.padEnd( + formatterWidth, + " ", + )} |`; + + lines.push(line); + } + + lines.sort(); + + const filler = `| ${"".padEnd(languageWidth, "-")} | ${"".padEnd( + formatterWidth, + "-", + )} |`; + + lines.unshift(filler); + + const heading = `| ${languageHeading.padEnd( + languageWidth, + " ", + )} | ${formatterHeading.padEnd(formatterWidth, " ")} |`; + + lines.unshift(heading); + + return lines.join("\n"); +} + +/** + * @param table {string} + */ +async function updateReadme(table) { + const content = await fs + .readFile("README.md") + .then((data) => data.toString()); + + const re = + /()[^{}]*/gm; + const update = `\n\n${table}\n\n`; + + await fs.writeFile("README.md", content.replace(re, update)); +} + +(async () => { + const version = await getVersion(); + + const schema = await loadSchema(version); + const table = createLanguageTable(schema); + + await updateReadme(table); +})(); diff --git a/src/config.rs b/src/config.rs index 6320737..52a3a79 100644 --- a/src/config.rs +++ b/src/config.rs @@ -138,8 +138,8 @@ impl Default for MdsfConfig { csharp: Lang::::default(), css: Lang::::default(), dart: Lang::::default(), - elm: Lang::::default(), elixir: Lang::::default(), + elm: Lang::::default(), gleam: Lang::::default(), go: Lang::::default(), graphql: Lang::::default(), diff --git a/src/formatters/mod.rs b/src/formatters/mod.rs index 9ec0e01..730046f 100644 --- a/src/formatters/mod.rs +++ b/src/formatters/mod.rs @@ -107,8 +107,8 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S Language::Crystal => config.crystal.format(snippet_path), Language::Css => config.css.format(snippet_path), Language::Dart => config.dart.format(snippet_path), - Language::Elm => config.elm.format(snippet_path), Language::Elixir => config.elixir.format(snippet_path), + Language::Elm => config.elm.format(snippet_path), Language::Gleam => config.gleam.format(snippet_path), Language::Go => config.go.format(snippet_path), Language::GraphQL => config.graphql.format(snippet_path), @@ -120,10 +120,11 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S Language::Lua => config.lua.format(snippet_path), Language::Markdown => config.markdown.format(snippet_path), Language::Nim => config.nim.format(snippet_path), - Language::ObjectiveC => config.objective_c.format(snippet_path), Language::OCaml => config.ocaml.format(snippet_path), + Language::ObjectiveC => config.objective_c.format(snippet_path), Language::Protobuf => config.protobuf.format(snippet_path), Language::Python => config.python.format(snippet_path), + Language::ReScript => config.rescript.format(snippet_path), Language::Roc => config.roc.format(snippet_path), Language::Ruby => config.ruby.format(snippet_path), Language::Rust => config.rust.format(snippet_path), @@ -132,10 +133,9 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S Language::Toml => config.toml.format(snippet_path), Language::TypeScript => config.typescript.format(snippet_path), Language::Vue => config.vue.format(snippet_path), + Language::Xml => config.xml.format(snippet_path), Language::Yaml => config.yaml.format(snippet_path), Language::Zig => config.zig.format(snippet_path), - Language::ReScript => config.rescript.format(snippet_path), - Language::Xml => config.xml.format(snippet_path), } { let mut f = formatted_code.trim().to_owned(); diff --git a/src/languages/mod.rs b/src/languages/mod.rs index 4d58531..775ca95 100644 --- a/src/languages/mod.rs +++ b/src/languages/mod.rs @@ -5,16 +5,16 @@ use crate::formatters::MdsfFormatter; pub enum Language { Blade, C, - Crystal, - Cpp, CSharp, + Cpp, + Crystal, Css, Dart, - Elm, Elixir, + Elm, Gleam, - GraphQL, Go, + GraphQL, Html, Java, JavaScript, @@ -23,8 +23,8 @@ pub enum Language { Lua, Markdown, Nim, - ObjectiveC, OCaml, + ObjectiveC, Protobuf, Python, ReScript, @@ -110,8 +110,10 @@ impl Language { "css" | "scss" => Some(Self::Css), "dart" => Some(Self::Dart), "elixir" => Some(Self::Elixir), + "elm" => Some(Self::Elm), "gleam" => Some(Self::Gleam), "go" | "golang" => Some(Self::Go), + "graphql" | "gql" => Some(Self::GraphQL), "html" => Some(Self::Html), "java" => Some(Self::Java), "javascript" | "js" | "jsx" => Some(Self::JavaScript), @@ -124,9 +126,10 @@ impl Language { "ocaml" => Some(Self::OCaml), "profobuf" | "profo" => Some(Self::Protobuf), "python" => Some(Self::Python), + "rescript" => Some(Self::ReScript), "roc" => Some(Self::Roc), - "ruby" => Some(Self::Ruby), - "rust" | "rb" => Some(Self::Rust), + "ruby" | "rb" => Some(Self::Ruby), + "rust" | "rs" => Some(Self::Rust), "shell" | "sh" | "bash" | "zsh" => Some(Self::Shell), "sql" | "bigquery" | "db2" | "db2i" | "hive" | "mariadb" | "mysql" | "n1ql" | "plsql" | "postgresql" | "redshift" | "singlestoredb" | "snowflake" | "spark" @@ -134,12 +137,9 @@ impl Language { "toml" => Some(Self::Toml), "typescript" | "ts" | "tsx" => Some(Self::TypeScript), "vue" => Some(Self::Vue), + "xml" => Some(Self::Xml), "yml" | "yaml" => Some(Self::Yaml), "zig" => Some(Self::Zig), - "graphql" | "gql" => Some(Self::GraphQL), - "elm" => Some(Self::Elm), - "rescript" => Some(Self::ReScript), - "xml" => Some(Self::Xml), _ => None, } } @@ -147,28 +147,31 @@ impl Language { #[inline] pub const fn to_file_ext(&self) -> &'static str { match self { - // NOTE: since scss is a superset of css we might as well support both at the same time + Self::Blade => ".blade.php", Self::C => ".c", + Self::CSharp => ".cs", Self::Cpp => ".cpp", Self::Crystal => ".cr", - Self::CSharp => ".cs", Self::Css => ".scss", Self::Dart => ".dart", Self::Elixir => ".ex", + Self::Elm => ".elm", Self::Gleam => ".gleam", Self::Go => ".go", + Self::GraphQL => ".gql", Self::Html => ".html", Self::Java => ".java", Self::JavaScript => ".js", Self::Json => ".jsonc", - // NOTE: just does not have any file ext Self::Just => ".justfile", Self::Lua => ".lua", Self::Markdown => ".md", Self::Nim => ".nim", + Self::OCaml => ".ml", Self::ObjectiveC => ".m", Self::Protobuf => ".proto", Self::Python => ".py", + Self::ReScript => ".res", Self::Roc => ".roc", Self::Ruby => ".rb", Self::Rust => ".rs", @@ -177,14 +180,9 @@ impl Language { Self::Toml => ".toml", Self::TypeScript => ".ts", Self::Vue => ".vue", + Self::Xml => ".xml", Self::Yaml => ".yml", Self::Zig => ".zig", - Self::GraphQL => ".gql", - Self::Elm => ".elm", - Self::Blade => ".blade.php", - Self::OCaml => ".ml", - Self::ReScript => ".res", - Self::Xml => ".xml", } } }