use crate::{
args::flag,
commands::{self, RapidCommand},
};
use clap::{command, crate_version, ArgMatches, Command};
use colorful::Colorful;
use std::{
env::{current_dir, current_exe},
path::PathBuf,
process::exit,
};
pub type App = Command;
pub const RAPID_LATEST_VERSION: &str = "v0.4.3";
pub fn current_directory() -> PathBuf {
current_dir().expect("Error: Could not determine the current wrking directory")
}
pub fn binary_dir() -> PathBuf {
current_exe().expect("Error: Could not determine binary dir.")
}
pub struct Config {}
pub struct RapidCLI {
pub config: Config,
}
impl RapidCLI {
pub fn new(config: Config) -> Self {
Self { config }
}
pub fn parse() -> App {
let usage = "rapid [SUBCAMMAND] [OPTIONS]";
command!()
.allow_external_subcommands(true)
.disable_colored_help(false)
.override_usage(usage)
.long_version(crate_version!())
.help_template(get_help_template())
.arg(flag("help", "List command(s)"))
.subcommands(RapidCLI::commands())
}
pub fn commands() -> Vec<Command> {
vec![
commands::new::New::cmd(),
commands::init::Init::cmd(),
commands::run::Run::cmd(),
commands::templates::Templates::cmd(),
]
}
pub fn execute_cammand(cmd: &str) -> Option<fn(&Config, &ArgMatches) -> Result<(), crate::cli::CliError<'static>>> {
let command_resolver = match cmd {
"new" => commands::new::New::execute,
"init" => commands::init::Init::execute,
"run" => commands::run::Run::execute,
"templates" => commands::templates::Templates::execute,
_ => return None,
};
Some(command_resolver)
}
pub fn run(&self, args: ArgMatches) -> Result<(), CliError<'static>> {
if let Some((cmd, args)) = args.subcommand() {
if let Some(cm) = RapidCLI::execute_cammand(cmd) {
let _ = cm(&self.config, args);
} else {
println!("{}", get_help_template());
exit(64); }
} else {
println!("{}", get_help_template());
exit(64);
}
Ok(())
}
}
fn get_help_template() -> String {
format!(
"RAPID -- The modern software toolkit built on React and Rust
Commands:
{init} Initialize Rapid functionality in an existing app
{run} Run Rapid applications with a single command
{new} Create a new rapid app
Options:
-V --version Print version info and exit
",
init = "init".bold(),
run = "run".bold(),
new = "new".bold()
)
}
#[derive(Debug)]
pub struct CliError<'a> {
pub error: Option<&'a str>,
pub exit_code: i32,
}
impl<'a> CliError<'a> {
pub fn new(error: &'a str, code: i32) -> CliError<'a> {
CliError {
error: Some(error),
exit_code: code,
}
}
}