#![forbid(unsafe_code)]
#![allow(clippy::result_large_err)]
mod cargo;
mod check;
mod compile;
mod convert;
mod dump;
mod error;
mod exchange;
mod fmt;
mod init;
#[cfg(test)]
mod listing;
mod pseudo;
mod stats;
mod watch;
#[cfg(all(test, mf2_workspace))]
mod workspace_tests;
use std::path::PathBuf;
use std::process::ExitCode;
use clap::{Args, Parser, Subcommand, ValueEnum};
use crate::error::{Error, Result};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, ValueEnum)]
pub(crate) enum Format {
#[default]
Text,
Json,
}
#[derive(Debug, Parser)]
#[command(name = "mf2", version, about, long_about = None)]
struct Cli {
#[arg(
long,
short = 'C',
global = true,
default_value = ".",
value_name = "DIR"
)]
dir: PathBuf,
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Args, Clone, Default)]
pub(crate) struct FeatureArgs {
#[arg(long, value_name = "LIST")]
features: Option<String>,
}
impl FeatureArgs {
pub(crate) fn features(&self) -> mf2_build::Features {
self.given().unwrap_or_default()
}
pub(crate) fn given(&self) -> Option<mf2_build::Features> {
self.features.as_deref().map(mf2_build::Features::parse)
}
}
#[derive(Debug, Subcommand)]
enum Command {
Init(init::Args),
Check(check::Args),
Compile(compile::Args),
Fmt(fmt::Args),
Stats(stats::Args),
Dump(dump::Args),
Pseudo(pseudo::Args),
Export(exchange::ExportArgs),
Import(exchange::ImportArgs),
Watch(watch::Args),
Convert(convert::Args),
}
fn main() -> ExitCode {
let cli = Cli::parse();
match run(&cli) {
Ok(()) => ExitCode::SUCCESS,
Err(Error::Corpus) => ExitCode::FAILURE,
Err(e) => {
eprintln!("mf2: {e}");
ExitCode::FAILURE
}
}
}
fn run(cli: &Cli) -> Result<()> {
match &cli.command {
Command::Init(args) => init::run(&cli.dir, args),
Command::Check(args) => check::run(&cli.dir, args),
Command::Compile(args) => compile::run(&cli.dir, args),
Command::Fmt(args) => fmt::run(&cli.dir, args),
Command::Stats(args) => stats::run(&cli.dir, args),
Command::Dump(args) => dump::run(args),
Command::Pseudo(args) => pseudo::run(&cli.dir, args),
Command::Export(args) => exchange::export(&cli.dir, args),
Command::Import(args) => exchange::import(&cli.dir, args),
Command::Watch(args) => watch::run(&cli.dir, args),
Command::Convert(args) => convert::run(&cli.dir, args),
}
}
#[cfg(test)]
mod tests {
use super::Cli;
use clap::CommandFactory;
#[test]
fn the_command_line_is_well_formed() {
Cli::command().debug_assert();
}
}