Minimal CLI command & options parsing

master
Araozu 2023-12-12 20:49:34 -05:00
parent 6399bd338c
commit f6c1664816
5 changed files with 128 additions and 7 deletions

7
src/cli/help.rs Normal file
View File

@ -0,0 +1,7 @@
use crate::cli::HELP_TEXT;
pub fn help_command(options: &Vec<String>) {
println!("{}", HELP_TEXT);
}

86
src/cli/mod.rs Normal file
View File

@ -0,0 +1,86 @@
mod help;
mod types;
use types::{Command, CommandType};
pub const HELP_TEXT: &str = r#"
Usage: `thp [command] [options]`
Commands
c _file_ Compiles `file` in-place
f _file_ Formats `file`
r Starts the REPL
init Initializes a new project in the current directory
build Builds the project
fmt Formats all files in the project
watch, w Starts compilation of the project in watch mode
help, h Print this message & exit
General options
-h, --help Print command-specific usage
"#;
fn get_copyright() -> String {
let crate_version = env!("CARGO_PKG_VERSION");
format!("The THP compiler, linter & formatter, v{}", crate_version)
}
pub fn run_cli() {
let command = match parse_args() {
Ok(c) => c,
Err(reason) => {
println!("{}", HELP_TEXT);
println!("Error: {}", reason);
return;
},
};
command.run();
}
fn parse_args() -> Result<Command, String> {
let mut args = std::env::args().collect::<Vec<String>>();
args.remove(0);
let mut args = args.into_iter();
let command = match args.next() {
Some(command) if !command.starts_with('-') => Some(command),
_ => None,
};
let mut options = Vec::new();
for arg in args {
if arg.starts_with('-') {
options.push(arg);
} else {
return Err(format!(
"Unexpected command `{}` after the options",
arg
));
}
}
let command = match command {
Some(command) => match command.as_str() {
"c" | "compile" => CommandType::Compile,
"f" | "format" => CommandType::Format,
"r" | "repl" => CommandType::Repl,
"init" => CommandType::Init,
"build" => CommandType::Build,
"fmt" => CommandType::Fmt,
"watch" | "w" => CommandType::Watch,
"help" | "h" => CommandType::Help,
_ => return Err(format!("Unknown command: {}", command)),
},
None => CommandType::None,
};
Ok(Command { command, options })
}

32
src/cli/types.rs Normal file
View File

@ -0,0 +1,32 @@
#[derive(Debug)]
pub struct Command {
pub command: CommandType,
pub options: Vec<String>,
}
#[derive(Debug)]
pub enum CommandType {
Compile,
Format,
Repl,
Init,
Build,
Fmt,
Watch,
Help,
None,
}
impl Command {
pub fn run(&self) {
println!("Running command! {:?}", self);
self.command.run(&self.options);
}
}
impl CommandType {
pub fn run(&self, options: &Vec<String>) {
println!("Running command! {:?}", self)
}
}

View File

@ -1,3 +1,5 @@
// Module to handle the CLI
mod cli;
// Module to handle the repl and its compilation // Module to handle the repl and its compilation
mod repl; mod repl;
@ -13,12 +15,6 @@ mod utils;
mod error_handling; mod error_handling;
fn get_copyright() -> String {
let crate_version = env!("CARGO_PKG_VERSION");
format!("The THP compiler, linter & formatter, v{}", crate_version,)
}
fn main() { fn main() {
println!("{}", get_copyright()); cli::run_cli();
println!("Rewriting CLI...");
} }