Skip to content

Commit

Permalink
feat(erlang): support erlfmt (#123)
Browse files Browse the repository at this point in the history
* feat(erlang): support erlfmt

* fix: use correct formatter
  • Loading branch information
hougesen authored Mar 21, 2024
1 parent 30dceda commit c56b8e8
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mdsf init
| Dart | `dart_format` |
| Elixir | `mix_format` |
| Elm | `elm-format` |
| Erlang | `erlfmt` |
| Gleam | `gleam_format` |
| Go | `gofmt`, `gofumpt`, `goimports` |
| GraphQL | `prettier` |
Expand All @@ -94,7 +95,7 @@ mdsf init
| Python | `autopep8`, `black`, `blue`, `isort`, `ruff`, `usort`, `yapf` |
| ReScript | `rescript_format` |
| Roc | `roc_format` |
| Ruby | `rubocop`, `rubyfmt`, `rufo` |
| Ruby | `rubocop`, `rubyfmt`, `rufo`, `standardrb` |
| Rust | `rustfmt` |
| Scala | `scalafmt` |
| Shell | `beautysh`, `shfmt` |
Expand Down
44 changes: 42 additions & 2 deletions schemas/v0.0.2/mdsf.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@
}
]
},
"erlang": {
"default": {
"enabled": true,
"formatter": "erlfmt"
},
"allOf": [
{
"$ref": "#/definitions/Lang_for_Erlang"
}
]
},
"gleam": {
"default": {
"enabled": true,
Expand Down Expand Up @@ -361,7 +372,7 @@
"ruby": {
"default": {
"enabled": true,
"formatter": [["rubocop", "rufo", "rubyfmt"]]
"formatter": [["rubocop", "rufo", "rubyfmt", "standardrb"]]
},
"allOf": [
{
Expand Down Expand Up @@ -532,6 +543,10 @@
"type": "string",
"enum": ["elm-format"]
},
"Erlang": {
"type": "string",
"enum": ["erlfmt"]
},
"Gleam": {
"type": "string",
"enum": ["gleam_format"]
Expand Down Expand Up @@ -696,6 +711,18 @@
}
}
},
"Lang_for_Erlang": {
"type": "object",
"required": ["enabled", "formatter"],
"properties": {
"enabled": {
"type": "boolean"
},
"formatter": {
"$ref": "#/definitions/MdsfFormatter_for_Erlang"
}
}
},
"Lang_for_Gleam": {
"type": "object",
"required": ["enabled", "formatter"],
Expand Down Expand Up @@ -1242,6 +1269,19 @@
}
]
},
"MdsfFormatter_for_Erlang": {
"anyOf": [
{
"$ref": "#/definitions/Erlang"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/MdsfFormatter_for_Erlang"
}
}
]
},
"MdsfFormatter_for_Gleam": {
"anyOf": [
{
Expand Down Expand Up @@ -1722,7 +1762,7 @@
},
"Ruby": {
"type": "string",
"enum": ["rubyfmt", "rubocop", "rufo"]
"enum": ["rubyfmt", "rubocop", "rufo", "standardrb"]
},
"Rust": {
"type": "string",
Expand Down
17 changes: 11 additions & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -47,6 +48,9 @@ pub struct MdsfConfig {
#[serde(default)]
pub elm: Lang<Elm>,

#[serde(default)]
pub erlang: Lang<Erlang>,

#[serde(default)]
pub gleam: Lang<Gleam>,

Expand Down Expand Up @@ -165,6 +169,7 @@ impl Default for MdsfConfig {
dart: Lang::<Dart>::default(),
elixir: Lang::<Elixir>::default(),
elm: Lang::<Elm>::default(),
erlang: Lang::<Erlang>::default(),
gleam: Lang::<Gleam>::default(),
go: Lang::<Go>::default(),
graphql: Lang::<GraphQL>::default(),
Expand Down
42 changes: 42 additions & 0 deletions src/formatters/erlfmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use super::execute_command;

#[inline]
pub fn format_using_erlfmt(file_path: &std::path::Path) -> std::io::Result<(bool, Option<String>)> {
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);
}
}
2 changes: 2 additions & 0 deletions src/formatters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -136,6 +137,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),
Expand Down
102 changes: 102 additions & 0 deletions src/languages/erlang.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use schemars::JsonSchema;

use crate::formatters::{erlfmt::format_using_erlfmt, 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<Erlang> {
#[inline]
fn default() -> Self {
Self {
enabled: true,
formatter: MdsfFormatter::<Erlang>::default(),
}
}
}

impl Default for MdsfFormatter<Erlang> {
#[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<String>)> {
match self {
Self::Erlfmt => format_using_erlfmt(snippet_path),
}
}
}

#[cfg(test)]
mod test_erlang {
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::<Erlang>::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::<Erlang> {
enabled: false,
formatter: MdsfFormatter::Single(Erlang::default())
}
.format(snippet_path)
.expect("it to not fail")
.is_none());
}

#[test_with::executable(erlfmt)]
#[test]
fn test_erlfmt() {
let l = Lang::<Erlang> {
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);
}
}
5 changes: 4 additions & 1 deletion src/languages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum Language {
Dart,
Elixir,
Elm,
Erlang,
Gleam,
Go,
GraphQL,
Expand Down Expand Up @@ -54,7 +55,6 @@ pub enum Language {
// TODO: Dockerfile,
// TODO: XML,
// TODO: D,
// TODO: Erlang,
// TODO: R,
}

Expand All @@ -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;
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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",
Expand Down

0 comments on commit c56b8e8

Please sign in to comment.