Skip to content

Instantly share code, notes, and snippets.

@rizary
Last active January 15, 2021 11:34
Show Gist options
  • Select an option

  • Save rizary/930fc9ee649ba37205a5208dfa08fead to your computer and use it in GitHub Desktop.

Select an option

Save rizary/930fc9ee649ba37205a5208dfa08fead to your computer and use it in GitHub Desktop.
pub fn run_fmt(toml_content: &Root, cwd: PathBuf) -> anyhow::Result<()> {
let commands = toml_content
.formatters
.values()
.map(|c| c.command.clone().unwrap_or("".into()));
let args = toml_content.formatters.values().map(|c| {
let arg = match c.args.clone() {
Some(vstr) => vstr,
None => Vec::new(),
};
arg
});
let all_files = toml_content
.formatters
.values()
.map(|f| f.files.clone())
.filter_map(|glob| glob_to_path(cwd.clone(), glob).ok());
for cmd in commands.clone() {
check_bin(cmd)?;
}
// TODO: implement `filtered_files: Vec<Paths>` for `[includes]` and `[exclude]`
let cmd_args = commands.zip(args).zip(all_files);
println!("===========================");
for ((cmd, _args), paths) in cmd_args.clone() {
println!("Command: {}", cmd);
println!("Files:");
for f in paths {
println!(" - {}", f?.display());
}
println!("===========================");
}
for ((cmd_arg, args), paths) in cmd_args.clone() {
for f in paths {
let path = f?;
let arg = args.clone();
cmd!("{cmd_arg} {arg...} {path}").run()?;
}
}
Ok(())
}
/// fmt.toml structure
#[derive(Debug, Deserialize)]
pub struct Root {
/// Map of formatters into the config
pub formatters: BTreeMap<String, FmtConfig>,
}
/// Config for each formatters
#[derive(Debug, Deserialize)]
pub struct FmtConfig {
/// File extensions that want to be formatted
pub files: FileExtensions,
/// File or Folder that is included to be formatted
pub includes: Option<Vec<String>>,
/// File or Folder that is excluded to be formatted
pub excludes: Option<Vec<String>>,
/// Command formatter to run
pub command: Option<String>,
/// Argument for formatter
pub args: Option<Vec<String>>,
}
/// File extensions can be single string (e.g. "*.hs") or
/// list of string (e.g. [ "*.hs", "*.rs" ])
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
pub enum FileExtensions {
/// Single file type
SingleFile(String),
/// List of file type
MultipleFile(Vec<String>),
}
/// Convert glob pattern into list of pathBuf
pub fn glob_to_path(cwd: PathBuf, extensions: FileExtensions) -> Result<Paths> {
match extensions {
FileExtensions::SingleFile(sfile) => {
let dir = cwd.as_path().to_str().unwrap_or("");
let pat = format!("{}**/{}", dir, &sfile);
match glob(&pat) {
Ok(paths) => Ok(paths),
Err(err) => {
anyhow::bail!(
"{} Error at position: {} due to {}",
emoji::ERROR,
err.pos,
err.msg
)
}
}
}
FileExtensions::MultipleFile(strs) => {
let files = strs
.into_iter()
.map(|str| {
let dir = cwd.as_path().to_str().unwrap_or("");
let pat = format!("{}**/{}", dir, &str);
match glob(&pat) {
Ok(paths) => Ok(paths),
Err(err) => {
anyhow::bail!(
"{} Error at position: {} due to {}",
emoji::ERROR,
err.pos,
err.msg
)
}
}
})
.flatten()
.nth(0);
match files {
Some(paths) => Ok(paths),
None => {
anyhow::bail!("{} Blob not found", emoji::ERROR)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment