1use crate::{
2 args::flag,
3 commands::{self, RapidCommand},
4};
5use clap::{command, crate_version, ArgMatches, Command};
6use colorful::Colorful;
7use std::{
8 env::{current_dir, current_exe},
9 path::PathBuf,
10 process::exit,
11};
12
13pub type App = Command;
14
15pub const RAPID_LATEST_VERSION: &str = "v0.4.3";
19
20pub fn current_directory() -> PathBuf {
22 current_dir().expect("Error: Could not determine the current wrking directory")
23}
24
25pub fn binary_dir() -> PathBuf {
27 current_exe().expect("Error: Could not determine binary dir.")
28}
29
30pub struct Config {}
32
33pub struct RapidCLI {
34 pub config: Config,
36}
37
38impl RapidCLI {
39 pub fn new(config: Config) -> Self {
40 Self { config }
41 }
42 pub fn parse() -> App {
43 let usage = "rapid [SUBCAMMAND] [OPTIONS]";
44 command!()
45 .allow_external_subcommands(true)
46 .disable_colored_help(false)
47 .override_usage(usage)
48 .long_version(crate_version!())
49 .help_template(get_help_template())
50 .arg(flag("help", "List command(s)"))
51 .subcommands(RapidCLI::commands())
52 }
53
54 pub fn commands() -> Vec<Command> {
55 vec![
56 commands::new::New::cmd(),
57 commands::init::Init::cmd(),
58 commands::run::Run::cmd(),
59 commands::templates::Templates::cmd(),
60 commands::routes::Routes::cmd(),
61 ]
62 }
63
64 pub fn execute_cammand(cmd: &str) -> Option<fn(&Config, &ArgMatches) -> Result<(), crate::cli::CliError<'static>>> {
65 let command_resolver = match cmd {
66 "new" => commands::new::New::execute,
67 "init" => commands::init::Init::execute,
68 "run" => commands::run::Run::execute,
69 "templates" => commands::templates::Templates::execute,
70 "routes" => commands::routes::Routes::execute,
71 _ => return None,
72 };
73
74 Some(command_resolver)
75 }
76
77 pub fn run(&self, args: ArgMatches) -> Result<(), CliError<'static>> {
78 if let Some((cmd, args)) = args.subcommand() {
79 if let Some(cm) = RapidCLI::execute_cammand(cmd) {
81 let _ = cm(&self.config, args);
82 } else {
83 println!("{}", get_help_template());
85 exit(64); }
87 } else {
88 println!("{}", get_help_template());
90 exit(64);
91 }
92
93 Ok(())
95 }
96}
97
98fn get_help_template() -> String {
101 format!(
102 "RAPID -- Build type-safe applications with Rust and Typescript
103
104Commands:
105 {init} Initialize Rapid functionality in an existing app
106 {run} Run Rapid applications with a single command
107 {new} Create a new rapid app
108
109Options:
110 -V --version Print version info and exit
111
112",
113 init = "init".bold(),
114 run = "run".bold(),
115 new = "new".bold()
116 )
117}
118
119#[derive(Debug)]
120pub struct CliError<'a> {
121 pub error: Option<&'a str>,
122 pub exit_code: i32,
123}
124
125impl<'a> CliError<'a> {
126 pub fn new(error: &'a str, code: i32) -> CliError<'a> {
127 CliError {
128 error: Some(error),
129 exit_code: code,
130 }
131 }
132}