Skip to content

Commit

Permalink
feat: support shfmt (#38)
Browse files Browse the repository at this point in the history
* feat: support shfmt

* ci: setup go
  • Loading branch information
hougesen authored Mar 9, 2024
1 parent 7dfcbae commit db8e6dd
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 5 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ jobs:
otp-version: "26"
gleam-version: "1.0.0"
elixir-version: "1.16.1"
# Used go shfmt
- uses: actions/setup-go@v5
with:
go-version: "stable"

- run: rustup toolchain install stable --profile minimal
- run: rustup component add rustfmt clippy
Expand Down Expand Up @@ -99,4 +103,10 @@ jobs:
- name: Install stylua
run: cargo install stylua

- name: Install shfmt
run: go install mvdan.cc/sh/v3/cmd/shfmt@latest

- name: Validate shfmt
run: shfmt --version

- run: cargo test
32 changes: 32 additions & 0 deletions schemas/v0.0.0/mdsf.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
"title": "MdsfConfig",
"type": "object",
"properties": {
"bash": {
"default": {
"enabled": true,
"formatter": "shfmt"
},
"allOf": [
{
"$ref": "#/definitions/Bash"
}
]
},
"css": {
"default": {
"enabled": true,
Expand Down Expand Up @@ -170,6 +181,27 @@
}
},
"definitions": {
"Bash": {
"type": "object",
"properties": {
"enabled": {
"default": true,
"type": "boolean"
},
"formatter": {
"default": "shfmt",
"allOf": [
{
"$ref": "#/definitions/BashFormatter"
}
]
}
}
},
"BashFormatter": {
"type": "string",
"enum": ["shfmt"]
},
"Css": {
"type": "object",
"properties": {
Expand Down
8 changes: 6 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use schemars::JsonSchema;

use crate::languages::{
css::Css, elixir::Elixir, gleam::Gleam, html::Html, javascript::JavaScript, json::Json,
lua::Lua, markdown::Markdown, nim::Nim, python::Python, rust::Rust, toml::Toml,
bash::Bash, 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,
};

Expand All @@ -12,6 +12,9 @@ pub struct MdsfConfig {
#[serde(rename = "$schema", default = "default_schema_location")]
pub schema: String,

#[serde(default)]
pub bash: Bash,

#[serde(default)]
pub css: Css,

Expand Down Expand Up @@ -63,6 +66,7 @@ impl Default for MdsfConfig {
fn default() -> Self {
Self {
schema: default_schema_location(),
bash: Bash::default(),
css: Css::default(),
elixir: Elixir::default(),
gleam: Gleam::default(),
Expand Down
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 nimpretty;
pub mod prettier;
pub mod ruff;
pub mod rustfmt;
pub mod shfmt;
pub mod stylua;
pub mod taplo;
pub mod zigfmt;
Expand Down Expand Up @@ -55,6 +56,7 @@ pub fn format_snippet(config: &MdsfConfig, language: &Language, code: &str) -> S
let snippet_path = snippet.path();

if let Ok(Some(formatted_code)) = match language {
Language::Bash => config.bash.format(snippet_path),
Language::Css => config.css.format(snippet_path),
Language::Elixir => config.elixir.format(snippet_path),
Language::Gleam => config.gleam.format(snippet_path),
Expand Down
93 changes: 93 additions & 0 deletions src/formatters/shfmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::{execute_command, read_snippet};

#[inline]
pub fn format_using_shfmt(file_path: &std::path::Path) -> std::io::Result<Option<String>> {
let mut cmd = std::process::Command::new("shfmt");

// Incase the use hasn't installed biome
cmd.arg("--write").arg(file_path);

if execute_command(&mut cmd)? {
return read_snippet(file_path).map(Some);
}

Ok(None)
}

#[cfg(test)]
mod test_shfmt {
use crate::{
formatters::{setup_snippet, shfmt::format_using_shfmt},
languages::Language,
};

#[test]
fn it_should_format_sh() {
let input = "
#!/bin/sh
add () {
echo \"$1\" + \"$2\"
}
";
let expected_output = "#!/bin/sh
add() {
\techo \"$1\" + \"$2\"
}
";

let snippet = setup_snippet(input, Language::Bash.to_file_ext())
.expect("it to create a snippet file");

let output = format_using_shfmt(snippet.path())
.expect("it to be succesful")
.expect("it to be some");

assert_eq!(expected_output, output);
}

#[test]
fn it_should_format_bash() {
let input = "
#!/bin/bash
add () {
echo \"$1\" + \"$2\"
}
";
let expected_output = "#!/bin/bash
add() {
\techo \"$1\" + \"$2\"
}
";

let snippet = setup_snippet(input, Language::Bash.to_file_ext())
.expect("it to create a snippet file");

let output = format_using_shfmt(snippet.path())
.expect("it to be succesful")
.expect("it to be some");

assert_eq!(expected_output, output);
}
}
43 changes: 43 additions & 0 deletions src/languages/bash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use schemars::JsonSchema;

use crate::{config::default_enabled, formatters::shfmt::format_using_shfmt};

use super::LanguageFormatter;

#[derive(Debug, Default, serde::Serialize, serde::Deserialize, JsonSchema)]
pub enum BashFormatter {
#[default]
#[serde(rename = "shfmt")]
Shfmt,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, JsonSchema)]
pub struct Bash {
#[serde(default = "default_enabled")]
pub enabled: bool,
#[serde(default)]
pub formatter: BashFormatter,
}

impl Default for Bash {
#[inline]
fn default() -> Self {
Self {
enabled: true,
formatter: BashFormatter::default(),
}
}
}

impl LanguageFormatter for Bash {
#[inline]
fn format(&self, snippet_path: &std::path::Path) -> std::io::Result<Option<String>> {
if !self.enabled {
return Ok(None);
}

match self.formatter {
BashFormatter::Shfmt => format_using_shfmt(snippet_path),
}
}
}
4 changes: 4 additions & 0 deletions src/languages/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub enum Language {
Bash,
Css,
Elixir,
Gleam,
Expand All @@ -16,6 +17,7 @@ pub enum Language {
Zig,
}

pub mod bash;
pub mod css;
pub mod elixir;
pub mod gleam;
Expand All @@ -40,6 +42,7 @@ impl Language {
#[inline]
pub fn maybe_from_str(input: &str) -> Option<Self> {
match input {
"sh" | "shell" | "bash" => Some(Self::Bash),
"css" | "scss" => Some(Self::Css),
"elixir" => Some(Self::Elixir),
"gleam" => Some(Self::Gleam),
Expand All @@ -62,6 +65,7 @@ impl Language {
#[inline]
pub const fn to_file_ext(&self) -> &'static str {
match self {
Self::Bash => ".sh",
// NOTE: since scss is a superset of css we might as well support both at the same time
Self::Css => ".scss",
Self::Elixir => ".ex",
Expand Down
10 changes: 7 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,13 @@ pub fn format_file(config: &MdsfConfig, path: &std::path::Path) -> Result<(), Md
s.finalize(&mut output).map_err(MdsfError::from)?;
}

if config.markdown.enabled && !output.is_empty() {
output = format_snippet(config, &Language::Markdown, &output);
modified = true;
if config.markdown.enabled {
if !output.is_empty() {
output = format_snippet(config, &Language::Markdown, &output);
modified = true;
}
} else {
output.push('\n');
}

let duration = time.elapsed();
Expand Down
18 changes: 18 additions & 0 deletions tests/bash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
```sh

#!/bin/bash

add () {
echo "$1" + "$2"
}










```
18 changes: 18 additions & 0 deletions tests/sh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
```sh

#!/bin/sh

add () {
echo "$1" + "$2"
}










```

0 comments on commit db8e6dd

Please sign in to comment.