From 7dfcbae17db8c47c8c855dd6cc08fcea5038370d Mon Sep 17 00:00:00 2001 From: Mads Hougesen Date: Sat, 9 Mar 2024 00:08:13 +0100 Subject: [PATCH] feat: add support for mix format (#36) --- .github/workflows/validate.yml | 9 ++++++- schemas/v0.0.0/mdsf.schema.json | 32 ++++++++++++++++++++++++ src/config.rs | 24 +++++++++++++++--- src/formatters/gleam_format.rs | 1 - src/formatters/mix_format.rs | 44 +++++++++++++++++++++++++++++++++ src/formatters/mod.rs | 2 ++ src/languages/elixir.rs | 43 ++++++++++++++++++++++++++++++++ src/languages/mod.rs | 4 +++ tests/elixir.md | 6 +++++ 9 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 src/formatters/mix_format.rs create mode 100644 src/languages/elixir.rs create mode 100644 tests/elixir.md diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index b22b230..f8087bd 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -59,8 +59,9 @@ jobs: # Used by gleam format - uses: erlef/setup-beam@v1 with: - otp-version: false + otp-version: "26" gleam-version: "1.0.0" + elixir-version: "1.16.1" - run: rustup toolchain install stable --profile minimal - run: rustup component add rustfmt clippy @@ -80,6 +81,9 @@ jobs: - name: Validate biome run: npx --yes @biomejs/biome --version + - name: Validate prettier + run: npx --yes prettier --version + - name: Validate nimpretty run: nimpretty --version @@ -89,6 +93,9 @@ jobs: - name: Validate gleam format run: gleam format --help + - name: Validate mix format + run: mix help format + - name: Install stylua run: cargo install stylua diff --git a/schemas/v0.0.0/mdsf.schema.json b/schemas/v0.0.0/mdsf.schema.json index b917bfa..5957806 100644 --- a/schemas/v0.0.0/mdsf.schema.json +++ b/schemas/v0.0.0/mdsf.schema.json @@ -14,6 +14,17 @@ } ] }, + "elixir": { + "default": { + "enabled": true, + "formatter": "mix_format" + }, + "allOf": [ + { + "$ref": "#/definitions/Elixir" + } + ] + }, "gleam": { "default": { "enabled": true, @@ -180,6 +191,27 @@ "type": "string", "enum": ["prettier"] }, + "Elixir": { + "type": "object", + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "formatter": { + "default": "mix_format", + "allOf": [ + { + "$ref": "#/definitions/ElixirFormatter" + } + ] + } + } + }, + "ElixirFormatter": { + "type": "string", + "enum": ["mix_format"] + }, "Gleam": { "type": "object", "properties": { diff --git a/src/config.rs b/src/config.rs index 9ce10d7..2025637 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,9 @@ use schemars::JsonSchema; use crate::languages::{ - css::Css, gleam::Gleam, html::Html, javascript::JavaScript, json::Json, lua::Lua, - markdown::Markdown, nim::Nim, python::Python, rust::Rust, toml::Toml, typescript::TypeScript, - yaml::Yaml, zig::Zig, + css::Css, elixir::Elixir, gleam::Gleam, html::Html, javascript::JavaScript, json::Json, + lua::Lua, markdown::Markdown, nim::Nim, python::Python, rust::Rust, toml::Toml, + typescript::TypeScript, yaml::Yaml, zig::Zig, }; #[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)] @@ -11,32 +11,49 @@ pub struct MdsfConfig { #[schemars(skip)] #[serde(rename = "$schema", default = "default_schema_location")] pub schema: String, + #[serde(default)] pub css: Css, + + #[serde(default)] + pub elixir: Elixir, + #[serde(default)] pub gleam: Gleam, + #[serde(default)] pub html: Html, + #[serde(default)] pub javascript: JavaScript, + #[serde(default)] pub json: Json, + #[serde(default)] pub lua: Lua, + #[serde(default)] pub markdown: Markdown, + #[serde(default)] pub nim: Nim, + #[serde(default)] pub python: Python, + #[serde(default)] pub rust: Rust, + #[serde(default)] pub toml: Toml, + #[serde(default)] pub typescript: TypeScript, + #[serde(default)] pub yaml: Yaml, + #[serde(default)] pub zig: Zig, } @@ -47,6 +64,7 @@ impl Default for MdsfConfig { Self { schema: default_schema_location(), css: Css::default(), + elixir: Elixir::default(), gleam: Gleam::default(), html: Html::default(), javascript: JavaScript::default(), diff --git a/src/formatters/gleam_format.rs b/src/formatters/gleam_format.rs index 2cff495..f48c1ce 100644 --- a/src/formatters/gleam_format.rs +++ b/src/formatters/gleam_format.rs @@ -2,7 +2,6 @@ use super::{execute_command, read_snippet}; #[inline] pub fn format_using_gleam_format(file_path: &std::path::Path) -> std::io::Result> { - // TODO: use installed biome instead let mut cmd = std::process::Command::new("gleam"); // Incase the use hasn't installed biome diff --git a/src/formatters/mix_format.rs b/src/formatters/mix_format.rs new file mode 100644 index 0000000..b6aea2e --- /dev/null +++ b/src/formatters/mix_format.rs @@ -0,0 +1,44 @@ +use super::{execute_command, read_snippet}; + +#[inline] +pub fn format_using_mix_format(file_path: &std::path::Path) -> std::io::Result> { + let mut cmd = std::process::Command::new("mix"); + + // Incase the use hasn't installed biome + cmd.arg("format").arg(file_path); + + if execute_command(&mut cmd)? { + return read_snippet(file_path).map(Some); + } + + Ok(None) +} + +#[cfg(test)] +mod test_gleam_format { + use crate::{ + formatters::{mix_format::format_using_mix_format, setup_snippet}, + languages::Language, + }; + + #[test] + fn it_should_format_gleam() { + let input = " + def add(a , b ) do a + b end + +"; + let expected_output = "def add(a, b) do + a + b +end +"; + + let snippet = setup_snippet(input, Language::Elixir.to_file_ext()) + .expect("it to create a snippet file"); + + let output = format_using_mix_format(snippet.path()) + .expect("it to be succesful") + .expect("it to be some"); + + assert_eq!(expected_output, output); + } +} diff --git a/src/formatters/mod.rs b/src/formatters/mod.rs index 5d3e95c..4190ef1 100644 --- a/src/formatters/mod.rs +++ b/src/formatters/mod.rs @@ -12,6 +12,7 @@ use crate::{ pub mod biome; pub mod gleam_format; +pub mod mix_format; pub mod nimpretty; pub mod prettier; pub mod ruff; @@ -55,6 +56,7 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S if let Ok(Some(formatted_code)) = match language { Language::Css => config.css.format(snippet_path), + Language::Elixir => config.elixir.format(snippet_path), Language::Gleam => config.gleam.format(snippet_path), Language::Html => config.html.format(snippet_path), Language::JavaScript => config.javascript.format(snippet_path), diff --git a/src/languages/elixir.rs b/src/languages/elixir.rs new file mode 100644 index 0000000..e81d4bd --- /dev/null +++ b/src/languages/elixir.rs @@ -0,0 +1,43 @@ +use schemars::JsonSchema; + +use crate::{config::default_enabled, formatters::mix_format::format_using_mix_format}; + +use super::LanguageFormatter; + +#[derive(Debug, Default, serde::Serialize, serde::Deserialize, JsonSchema)] +pub enum ElixirFormatter { + #[default] + #[serde(rename = "mix_format")] + MixFormat, +} + +#[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)] +pub struct Elixir { + #[serde(default = "default_enabled")] + pub enabled: bool, + #[serde(default)] + pub formatter: ElixirFormatter, +} + +impl Default for Elixir { + #[inline] + fn default() -> Self { + Self { + enabled: true, + formatter: ElixirFormatter::default(), + } + } +} + +impl LanguageFormatter for Elixir { + #[inline] + fn format(&self, snippet_path: &std::path::Path) -> std::io::Result> { + if !self.enabled { + return Ok(None); + } + + match self.formatter { + ElixirFormatter::MixFormat => format_using_mix_format(snippet_path), + } + } +} diff --git a/src/languages/mod.rs b/src/languages/mod.rs index 9775e41..9f4936a 100644 --- a/src/languages/mod.rs +++ b/src/languages/mod.rs @@ -1,5 +1,6 @@ pub enum Language { Css, + Elixir, Gleam, Html, JavaScript, @@ -16,6 +17,7 @@ pub enum Language { } pub mod css; +pub mod elixir; pub mod gleam; pub mod html; pub mod javascript; @@ -39,6 +41,7 @@ impl Language { pub fn maybe_from_str(input: &str) -> Option { match input { "css" | "scss" => Some(Self::Css), + "elixir" => Some(Self::Elixir), "gleam" => Some(Self::Gleam), "html" => Some(Self::Html), "js" | "jsx" | "javascript" => Some(Self::JavaScript), @@ -61,6 +64,7 @@ impl Language { match self { // NOTE: since scss is a superset of css we might as well support both at the same time Self::Css => ".scss", + Self::Elixir => ".ex", Self::Gleam => ".gleam", Self::Html => ".html", Self::JavaScript => ".js", diff --git a/tests/elixir.md b/tests/elixir.md new file mode 100644 index 0000000..f9c86d3 --- /dev/null +++ b/tests/elixir.md @@ -0,0 +1,6 @@ +```elixir + + def add(a , b ) do a + b end + + +```