CLI Definition in Rust
Writing CLIs in Rust is an absolute pleasure. Using a crate like structopt, you can define the structure of your CLI and it handles cleaning the input and converting it to an appropriate type.
#[derive(Debug, StructOpt)]
#[structopt(name = "TGit", about = "HedonHermDev's implementation of Git")]
pub enum CLI {
#[structopt(
name = "init",
about = "Initialize an empty git repository"
)]
Init { git_dir: Option<PathBuf> },
#[structopt(name = "cat-file", about = "Cat the contents of a git object")]
CatFile {
#[structopt(
name = "pretty_print",
short = "p",
about = "Pretty print the contents"
)]
pretty_print: bool,
#[structopt(name = "OBJECT SHA")]
object_sha: String,
},
// -- snip --
}
impl CLI {
pub async fn run() -> Result<()> {
let args: Self = Self::from_args();
match args {
CLI::Init { git_dir } => commands::init(git_dir).await,
CLI::CatFile {
pretty_print,
object_sha,
} => commands::cat_file(pretty_print, object_sha).await,
}
}
}
The above code should be fairly legible even if you don’t understand Rust. It defines the CLI as a set of subcommands with each command getting its arguments as a struct. This leverages the power of Rust’s enums. Now, we can write functions that ex ecute the above subcommands in the commands.rs file. For the init and the cat-file command, the implementation looks something like this:
pub async fn init(git_dir: Option<PathBuf>) -> Result<()> {
// -- snip --
}
pub async fn cat_file(pretty_print: bool, object_sha: String)
-> Result<()> {
// -- snip --
}
Similar functions are defined for the other commands.
Next
Move on to [[git/implementation]] to read about the implementation of the object storage of git.