use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
path::{Path, PathBuf},
process::Command,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum JavascriptPackageManagerType {
Npm,
Yarn,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RuffLintBehavior {
CheckOnly,
CheckAndFix,
FixOnly,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ShellCommandTransformer {
Rustfmt,
Gofmt,
ClangFormat,
System {
command: String,
env: HashMap<String, String>,
args: Vec<String>,
},
DenoFmt,
Prettier {
package_json_directory: Option<PathBuf>,
package_manager_type: Option<JavascriptPackageManagerType>,
},
RuffLint {
behavior: RuffLintBehavior,
venv_path: Option<PathBuf>,
#[serde(default)]
unsafe_fixes: bool,
},
RuffFormat {
venv_path: Option<PathBuf>,
},
}
impl ShellCommandTransformer {
pub fn get_command<P: AsRef<Path>>(
&self,
repository_path: P,
extension: Option<&str>,
) -> Command {
match self {
Self::Rustfmt => {
let mut command = Command::new("rustfmt");
command.args(["--emit", "stdout"]);
command
}
Self::Gofmt => Command::new("gofmt"),
Self::ClangFormat => {
let mut command = Command::new("clang-format");
if let Some(extension) = extension {
command.args(["--assume-filename", &format!("example.{}", extension)]);
}
command
}
Self::System { command, env, args } => {
let mut command = Command::new(command);
command.envs(env);
command.args(args);
command
}
Self::DenoFmt => {
let mut command = Command::new("deno");
command.arg("fmt");
if let Some(extension) = extension {
command.args(["--ext", extension]);
}
command.arg("-");
command
}
Self::Prettier {
package_json_directory,
package_manager_type,
} => {
let mut command = match package_manager_type {
Some(JavascriptPackageManagerType::Npm) => {
let mut command = Command::new("npx");
command.arg("prettier");
command
}
Some(JavascriptPackageManagerType::Yarn) => {
let mut command = Command::new("yarn");
command.args(["--silent", "run", "prettier"]);
command
}
None => Command::new("prettier"),
};
if let Some(package_json_directory) = package_json_directory {
let prettier_path = repository_path.as_ref().join(package_json_directory);
command.current_dir(prettier_path);
}
if let Some(extension) = extension {
command.args(["--stdin-filepath", &format!("example.{}", extension)]);
}
command
}
Self::RuffLint {
behavior,
venv_path,
unsafe_fixes,
} => {
let mut command = match venv_path {
Some(venv_path) => {
let python_path = repository_path
.as_ref()
.join(venv_path)
.join("bin")
.join("python");
let mut command = Command::new(python_path);
command.args(["-m", "ruff"]);
command
}
None => Command::new("ruff"),
};
command.arg("check");
match behavior {
RuffLintBehavior::FixOnly => {
command.arg("--fix-only");
}
RuffLintBehavior::CheckAndFix => {
command.arg("--fix");
}
RuffLintBehavior::CheckOnly => {}
}
if *unsafe_fixes {
command.arg("--unsafe-fixes");
}
if let Some(extension) = extension {
command.args(["--stdin-filename", &format!("example.{}", extension)]);
}
command.args(["--quiet", "-"]);
command
}
Self::RuffFormat { venv_path } => {
let mut command = match venv_path {
Some(venv_path) => {
let python_path = repository_path
.as_ref()
.join(venv_path)
.join("bin")
.join("python");
let mut command = Command::new(python_path);
command.args(["-m", "ruff"]);
command
}
None => Command::new("ruff"),
};
command.arg("format");
if let Some(extension) = extension {
command.args(["--stdin-filename", &format!("example.{}", extension)]);
}
command.args(["--quiet", "-"]);
command
}
}
}
}