diff --git a/src/config.rs b/src/config.rs index fd66f546..b66dfc79 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,12 +2,13 @@ use schemars::JsonSchema; use crate::languages::{ blade::Blade, c::C, clojure::Clojure, cpp::Cpp, crystal::Crystal, csharp::CSharp, css::Css, - dart::Dart, elixir::Elixir, elm::Elm, gleam::Gleam, go::Go, graphql::GraphQL, groovy::Groovy, - haskell::Haskell, html::Html, java::Java, javascript::JavaScript, json::Json, just::Just, - kotlin::Kotlin, lua::Lua, markdown::Markdown, nim::Nim, objective_c::ObjectiveC, ocaml::OCaml, - perl::Perl, protobuf::Protobuf, purescript::PureScript, python::Python, rescript::ReScript, - roc::Roc, ruby::Ruby, rust::Rust, scala::Scala, shell::Shell, sql::Sql, swift::Swift, - toml::Toml, typescript::TypeScript, vue::Vue, xml::Xml, yaml::Yaml, zig::Zig, Lang, + dart::Dart, elixir::Elixir, elm::Elm, erlang::Erlang, gleam::Gleam, go::Go, graphql::GraphQL, + groovy::Groovy, haskell::Haskell, html::Html, java::Java, javascript::JavaScript, json::Json, + just::Just, kotlin::Kotlin, lua::Lua, markdown::Markdown, nim::Nim, objective_c::ObjectiveC, + ocaml::OCaml, perl::Perl, protobuf::Protobuf, purescript::PureScript, python::Python, + rescript::ReScript, roc::Roc, ruby::Ruby, rust::Rust, scala::Scala, shell::Shell, sql::Sql, + swift::Swift, toml::Toml, typescript::TypeScript, vue::Vue, xml::Xml, yaml::Yaml, zig::Zig, + Lang, }; #[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)] @@ -47,6 +48,9 @@ pub struct MdsfConfig { #[serde(default)] pub elm: Lang, + #[serde(default)] + pub erlang: Lang, + #[serde(default)] pub gleam: Lang, @@ -165,6 +169,7 @@ impl Default for MdsfConfig { dart: Lang::::default(), elixir: Lang::::default(), elm: Lang::::default(), + erlang: Lang::::default(), gleam: Lang::::default(), go: Lang::::default(), graphql: Lang::::default(), diff --git a/src/formatters/erlfmt.rs b/src/formatters/erlfmt.rs new file mode 100644 index 00000000..8c4a1c8c --- /dev/null +++ b/src/formatters/erlfmt.rs @@ -0,0 +1,42 @@ +use super::execute_command; + +#[inline] +pub fn format_using_erlfmt(file_path: &std::path::Path) -> std::io::Result<(bool, Option)> { + let mut cmd = std::process::Command::new("erlfmt"); + + cmd.arg("-w") + .arg(format!("'{}'", file_path.to_string_lossy())); + + execute_command(&mut cmd, file_path) +} + +#[cfg(test)] +mod test_erlfmt { + use crate::{ + formatters::{erlfmt::format_using_erlfmt, setup_snippet}, + languages::Language, + }; + + #[test_with::executable(erlfmt)] + #[test] + fn it_should_format_erlang() { + let input = "what_is(Erlang) -> +case Erlang of movie->[hello(mike,joe,robert),credits]; language->formatting_arguments end +."; + + let expected_output = "what_is(Erlang) -> + case Erlang of + movie -> [hello(mike, joe, robert), credits]; + language -> no_more_formatting_arguments + end."; + let snippet = setup_snippet(input, Language::Erlang.to_file_ext()) + .expect("it to create a snippet file"); + + let output = format_using_erlfmt(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 9589c4e5..16176f0c 100644 --- a/src/formatters/mod.rs +++ b/src/formatters/mod.rs @@ -17,6 +17,7 @@ pub mod crystal_format; pub mod dart_format; pub mod deno_fmt; pub mod elm_format; +pub mod erlfmt; pub mod fourmolu; pub mod gleam_format; pub mod gofmt; @@ -135,6 +136,7 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S Language::Dart => config.dart.format(snippet_path), Language::Elixir => config.elixir.format(snippet_path), Language::Elm => config.elm.format(snippet_path), + Language::Erlang => config.erlang.format(snippet_path), Language::Gleam => config.gleam.format(snippet_path), Language::Go => config.go.format(snippet_path), Language::GraphQL => config.graphql.format(snippet_path), diff --git a/src/languages/erlang.rs b/src/languages/erlang.rs new file mode 100644 index 00000000..f6e3974e --- /dev/null +++ b/src/languages/erlang.rs @@ -0,0 +1,102 @@ +use schemars::JsonSchema; + +use crate::formatters::{gleam_format::format_using_gleam_format, MdsfFormatter}; + +use super::{Lang, LanguageFormatter}; + +#[derive(Debug, Default, serde::Serialize, serde::Deserialize, JsonSchema)] +#[cfg_attr(test, derive(PartialEq, Eq))] +pub enum Erlang { + #[default] + #[serde(rename = "erlfmt")] + Erlfmt, +} + +impl Default for Lang { + #[inline] + fn default() -> Self { + Self { + enabled: true, + formatter: MdsfFormatter::::default(), + } + } +} + +impl Default for MdsfFormatter { + #[inline] + fn default() -> Self { + Self::Single(Erlang::Erlfmt) + } +} + +impl LanguageFormatter for Erlang { + #[inline] + fn format_snippet( + &self, + snippet_path: &std::path::Path, + ) -> std::io::Result<(bool, Option)> { + match self { + Self::Erlfmt => format_using_gleam_format(snippet_path), + } + } +} + +#[cfg(test)] +mod test_gleam { + use crate::{ + formatters::{setup_snippet, MdsfFormatter}, + languages::Lang, + }; + + use super::Erlang; + + const INPUT: &str = "what_is(Erlang) -> +case Erlang of movie->[hello(mike,joe,robert),credits]; language->formatting_arguments end +."; + + const EXTENSION: &str = crate::languages::Language::Gleam.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(Erlang::default()) + } + .format(snippet_path) + .expect("it to not fail") + .is_none()); + } + + #[test_with::executable(erlfmt)] + #[test] + fn test_gleam_format() { + let l = Lang:: { + enabled: true, + formatter: MdsfFormatter::Single(Erlang::Erlfmt), + }; + + 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 = "what_is(Erlang) -> + case Erlang of + movie -> [hello(mike, joe, robert), credits]; + language -> no_more_formatting_arguments + end."; + + assert_eq!(output, expected_output); + } +} diff --git a/src/languages/mod.rs b/src/languages/mod.rs index 4baf6388..b2a0cc72 100644 --- a/src/languages/mod.rs +++ b/src/languages/mod.rs @@ -13,6 +13,7 @@ pub enum Language { Dart, Elixir, Elm, + Erlang, Gleam, Go, GraphQL, @@ -54,7 +55,6 @@ pub enum Language { // TODO: Dockerfile, // TODO: XML, // TODO: D, - // TODO: Erlang, // TODO: R, } @@ -68,6 +68,7 @@ pub mod css; pub mod dart; pub mod elixir; pub mod elm; +pub mod erlang; pub mod gleam; pub mod go; pub mod graphql; @@ -123,6 +124,7 @@ impl Language { "dart" => Some(Self::Dart), "elixir" => Some(Self::Elixir), "elm" => Some(Self::Elm), + "erlang" => Some(Self::Erlang), "gleam" => Some(Self::Gleam), "go" | "golang" => Some(Self::Go), "graphql" | "gql" => Some(Self::GraphQL), @@ -176,6 +178,7 @@ impl Language { Self::Dart => ".dart", Self::Elixir => ".ex", Self::Elm => ".elm", + Self::Erlang => ".erl", Self::Gleam => ".gleam", Self::Go => ".go", Self::GraphQL => ".gql",