154 lines
3.9 KiB
Rust
154 lines
3.9 KiB
Rust
use std::sync::LazyLock;
|
|
use std::{fmt::Display, path::PathBuf};
|
|
|
|
use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
|
|
|
|
pub static CLI_ARGS: LazyLock<CliArgs> = LazyLock::new(|| CliArgs::parse());
|
|
|
|
#[derive(Debug, Parser)]
|
|
#[clap(author, version)]
|
|
#[command(help_template = "{author-section}\n{usage-heading} {usage}\n\n{all-args}")]
|
|
pub struct CliArgs {
|
|
#[command(subcommand)]
|
|
pub command: Command,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Subcommand)]
|
|
pub enum Command {
|
|
/// Create a new raven project
|
|
New {
|
|
#[clap(flatten)]
|
|
type_: ProjectFlag,
|
|
project_name: String,
|
|
},
|
|
/// Create a new raven project in an existing directory
|
|
Init,
|
|
/// Compile the current project
|
|
Build,
|
|
/// Run the current project
|
|
Run {
|
|
#[clap(value_hint = clap::ValueHint::DirPath)]
|
|
entry_point: Option<PathBuf>,
|
|
|
|
#[clap(flatten)]
|
|
assertions: Assertions,
|
|
},
|
|
/// !!! BORKED !!! Run the tests
|
|
Test {
|
|
#[clap(flatten)]
|
|
assertions: Assertions,
|
|
},
|
|
/// Remove the target directory and caching
|
|
Clean,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Args)]
|
|
pub struct Assertions {
|
|
/// Disable assertions.
|
|
#[arg(short, long = "no-assert", action = ArgAction::SetFalse)]
|
|
assertions: bool,
|
|
}
|
|
|
|
impl Into<bool> for &Assertions {
|
|
fn into(self) -> bool {
|
|
self.assertions
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Args)]
|
|
#[group(multiple = false)]
|
|
pub struct ProjectFlag {
|
|
#[arg(long, action = ArgAction::SetTrue)]
|
|
_nest: (),
|
|
#[arg(long, action = ArgAction::SetTrue)]
|
|
_package: (),
|
|
|
|
#[arg(
|
|
hide = true,
|
|
required = false,
|
|
short,
|
|
long,
|
|
default_value_ifs = [
|
|
("_nest", "true", "nest"),
|
|
("_package", "true", "package"),
|
|
("_nest", "false", "nest"),
|
|
],
|
|
)]
|
|
pub project_type: ProjectType,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum)]
|
|
#[value(rename_all = "kebab-case")]
|
|
pub enum ProjectType {
|
|
#[default]
|
|
Nest,
|
|
Package,
|
|
}
|
|
|
|
impl Display for ProjectType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", Self::to_string(&self))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn args_new_w_arg() {
|
|
let args: CliArgs = Parser::try_parse_from(["raven", "new", "demo"]).unwrap();
|
|
let type_ = match args.command {
|
|
Command::New { type_, .. } => type_,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
assert!(type_.project_type == ProjectType::Nest);
|
|
}
|
|
|
|
#[test]
|
|
fn args_new_nest() {
|
|
let args: CliArgs = Parser::try_parse_from(["raven", "new", "--nest", "demo"]).unwrap();
|
|
let type_ = match args.command {
|
|
Command::New { type_, .. } => type_,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
assert!(type_.project_type == ProjectType::Nest);
|
|
}
|
|
|
|
#[test]
|
|
fn args_new_package() {
|
|
let args: CliArgs = Parser::try_parse_from(["raven", "new", "--package", "demo"]).unwrap();
|
|
let type_ = match args.command {
|
|
Command::New { type_, .. } => type_,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
assert!(type_.project_type == ProjectType::Package);
|
|
}
|
|
|
|
#[test]
|
|
fn args_run_assert() {
|
|
let args: CliArgs = Parser::try_parse_from(["raven", "run", "Main"]).unwrap();
|
|
let assertions: bool = match args.command {
|
|
Command::Run { assertions, .. } => assertions.assertions,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
assert!(assertions == true)
|
|
}
|
|
|
|
#[test]
|
|
fn args_run_no_assert() {
|
|
let args: CliArgs =
|
|
Parser::try_parse_from(["raven", "run", "--no-assert", "Main"]).unwrap();
|
|
let assertions: bool = match args.command {
|
|
Command::Run { assertions, .. } => assertions.assertions,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
assert!(assertions == false)
|
|
}
|
|
}
|