diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 576c573f..bfcc6d91 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -82,6 +82,8 @@ jobs: - uses: denoland/setup-deno@v1 with: deno-version: v1.x + # just_fmt + - uses: taiki-e/install-action@just - run: rustup toolchain install stable --profile minimal - run: rustup component add rustfmt clippy diff --git a/README.md b/README.md index 9a756ea4..ba33429d 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ mdsf init | 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` | diff --git a/schemas/v0.0.1/mdsf.schema.json b/schemas/v0.0.1/mdsf.schema.json index fb23b9b4..c7fb36f7 100644 --- a/schemas/v0.0.1/mdsf.schema.json +++ b/schemas/v0.0.1/mdsf.schema.json @@ -146,6 +146,17 @@ } ] }, + "just": { + "default": { + "enabled": true, + "formatter": "just_fmt" + }, + "allOf": [ + { + "$ref": "#/definitions/Lang_for_Just" + } + ] + }, "lua": { "default": { "enabled": true, @@ -379,6 +390,10 @@ "type": "string", "enum": ["prettier", "biome", "deno_fmt", "clang-format"] }, + "Just": { + "type": "string", + "enum": ["just_fmt"] + }, "Lang_for_C": { "type": "object", "required": ["enabled", "formatter"], @@ -535,6 +550,18 @@ } } }, + "Lang_for_Just": { + "type": "object", + "required": ["enabled", "formatter"], + "properties": { + "enabled": { + "type": "boolean" + }, + "formatter": { + "$ref": "#/definitions/MdsfFormatter_for_Just" + } + } + }, "Lang_for_Lua": { "type": "object", "required": ["enabled", "formatter"], @@ -904,6 +931,19 @@ } ] }, + "MdsfFormatter_for_Just": { + "anyOf": [ + { + "$ref": "#/definitions/Just" + }, + { + "type": "array", + "items": { + "$ref": "#/definitions/MdsfFormatter_for_Just" + } + } + ] + }, "MdsfFormatter_for_Lua": { "anyOf": [ { diff --git a/src/config.rs b/src/config.rs index 5d0dc252..3c986d43 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,10 +2,10 @@ use schemars::JsonSchema; use crate::languages::{ c::C, cpp::Cpp, crystal::Crystal, csharp::CSharp, css::Css, dart::Dart, elixir::Elixir, - gleam::Gleam, go::Go, html::Html, java::Java, javascript::JavaScript, json::Json, lua::Lua, - markdown::Markdown, nim::Nim, objective_c::ObjectiveC, protobuf::Protobuf, python::Python, - roc::Roc, ruby::Ruby, rust::Rust, shell::Shell, sql::Sql, toml::Toml, typescript::TypeScript, - vue::Vue, yaml::Yaml, zig::Zig, Lang, + gleam::Gleam, go::Go, html::Html, java::Java, javascript::JavaScript, json::Json, just::Just, + lua::Lua, markdown::Markdown, nim::Nim, objective_c::ObjectiveC, protobuf::Protobuf, + python::Python, roc::Roc, ruby::Ruby, rust::Rust, shell::Shell, sql::Sql, toml::Toml, + typescript::TypeScript, vue::Vue, yaml::Yaml, zig::Zig, Lang, }; #[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)] @@ -54,6 +54,9 @@ pub struct MdsfConfig { #[serde(default)] pub json: Lang, + #[serde(default)] + pub just: Lang, + #[serde(default)] pub lua: Lang, @@ -122,6 +125,7 @@ impl Default for MdsfConfig { java: Lang::::default(), javascript: Lang::::default(), json: Lang::::default(), + just: Lang::::default(), lua: Lang::::default(), markdown: Lang::::default(), nim: Lang::::default(), diff --git a/src/formatters/just_fmt.rs b/src/formatters/just_fmt.rs new file mode 100644 index 00000000..e70020ad --- /dev/null +++ b/src/formatters/just_fmt.rs @@ -0,0 +1,47 @@ +use super::execute_command; + +#[inline] +pub fn format_using_just_fmt( + snippet_path: &std::path::Path, +) -> std::io::Result<(bool, Option)> { + let mut cmd = std::process::Command::new("just"); + + cmd.arg("--fmt") + // TODO: remove once it is stabilized + .arg("--unstable") + .arg("--justfile") + .arg(snippet_path); + + execute_command(&mut cmd, snippet_path) +} + +#[cfg(test)] +mod test_just_fmt { + use crate::{ + formatters::{just_fmt::format_using_just_fmt, setup_snippet}, + languages::Language, + }; + + #[test] + fn it_should_format_just() { + let input = "build: + cargo build + cargo build --release + "; + + let expected_output = "build: + cargo build + cargo build --release +"; + + let snippet = setup_snippet(input, Language::Gleam.to_file_ext()) + .expect("it to create a snippet file"); + + let output = format_using_just_fmt(snippet.path()) + .expect("it to be successful") + .1 + .expect("it to be some"); + + assert_eq!(expected_output, output); + } +} diff --git a/src/formatters/mod.rs b/src/formatters/mod.rs index 69cf926a..d6a3e18a 100644 --- a/src/formatters/mod.rs +++ b/src/formatters/mod.rs @@ -17,6 +17,7 @@ pub mod gleam_format; pub mod gofmt; pub mod gofumpt; pub mod isort; +pub mod just_fmt; pub mod mix_format; pub mod nimpretty; pub mod prettier; @@ -107,6 +108,7 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S Language::Java => config.java.format(snippet_path), Language::JavaScript => config.javascript.format(snippet_path), Language::Json => config.json.format(snippet_path), + Language::Just => config.just.format(snippet_path), Language::Lua => config.lua.format(snippet_path), Language::Markdown => config.markdown.format(snippet_path), Language::Nim => config.nim.format(snippet_path), diff --git a/src/languages/just.rs b/src/languages/just.rs new file mode 100644 index 00000000..cf92e1b1 --- /dev/null +++ b/src/languages/just.rs @@ -0,0 +1,103 @@ +use schemars::JsonSchema; + +use crate::formatters::{just_fmt::format_using_just_fmt, MdsfFormatter}; + +use super::{Lang, LanguageFormatter}; + +#[derive(Debug, Default, serde::Serialize, serde::Deserialize, JsonSchema)] +#[cfg_attr(test, derive(PartialEq, Eq))] +pub enum Just { + #[default] + #[serde(rename = "just_fmt")] + JustFmt, +} + +impl Default for Lang { + #[inline] + fn default() -> Self { + Self { + enabled: true, + formatter: MdsfFormatter::::default(), + } + } +} + +impl Default for MdsfFormatter { + #[inline] + fn default() -> Self { + Self::Single(Just::JustFmt) + } +} + +impl LanguageFormatter for Just { + #[inline] + fn format_snippet( + &self, + snippet_path: &std::path::Path, + ) -> std::io::Result<(bool, Option)> { + match self { + Self::JustFmt => format_using_just_fmt(snippet_path), + } + } +} + +#[cfg(test)] +mod test_just { + use crate::{ + formatters::{setup_snippet, MdsfFormatter}, + languages::Lang, + }; + + use super::Just; + + const INPUT: &str = " + + +build: + cargo build + cargo build --release + "; + const EXTENSION: &str = crate::languages::Language::Just.to_file_ext(); + + #[test] + fn it_should_be_enabled_by_default() { + assert!(Lang::::default().enabled); + } + + #[test] + fn it_should_not_format_when_enabled_is_false() { + let snippet = setup_snippet(INPUT, EXTENSION).expect("it to save the file"); + let snippet_path = snippet.path(); + + assert!(Lang:: { + enabled: false, + formatter: MdsfFormatter::Single(Just::default()) + } + .format(snippet_path) + .expect("it to not fail") + .is_none()); + } + + #[test] + fn test_just_fmt() { + let l = Lang:: { + enabled: true, + formatter: MdsfFormatter::Single(Just::JustFmt), + }; + + let snippet = setup_snippet(INPUT, EXTENSION).expect("it to save the file"); + let snippet_path = snippet.path(); + + let output = l + .format(snippet_path) + .expect("it to not fail") + .expect("it to be a snippet"); + + let expected_output = "build: + cargo build + cargo build --release +"; + + assert_eq!(output, expected_output); + } +} diff --git a/src/languages/mod.rs b/src/languages/mod.rs index 2cefb7b5..28fbbf9c 100644 --- a/src/languages/mod.rs +++ b/src/languages/mod.rs @@ -16,6 +16,7 @@ pub enum Language { Java, JavaScript, Json, + Just, Lua, Markdown, Nim, @@ -63,6 +64,7 @@ pub mod html; pub mod java; pub mod javascript; pub mod json; +pub mod just; pub mod lua; pub mod markdown; pub mod nim; @@ -103,7 +105,8 @@ impl Language { "html" => Some(Self::Html), "java" => Some(Self::Java), "javascript" | "js" | "jsx" => Some(Self::JavaScript), - "json" => Some(Self::Json), + "json" | "jsonc" => Some(Self::Json), + "just" | "justfile" => Some(Self::Just), "lua" => Some(Self::Lua), "markdown" | "md" => Some(Self::Markdown), "nim" => Some(Self::Nim), @@ -143,6 +146,8 @@ impl Language { 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",