diff --git a/.gitignore b/.gitignore index 65f1105..572aa44 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # ---> Rust # Generated by Cargo # will have compiled files and executables -/target/ +target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/README.md b/README.md index dd93979..24b75f0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # clap-template -Clap template \ No newline at end of file +Clap template + +This is a kickstart ( https://github.com/Keats/kickstart ) template + diff --git a/template.toml b/template.toml new file mode 100644 index 0000000..6cb8ee4 --- /dev/null +++ b/template.toml @@ -0,0 +1,28 @@ +name = "Rust Clap CLI template" +description = "Hatter's Rust Clap CLI template" +kickstart_version = 1 +ignore = [ + ".gitignore", + "README.md", + "LICENSE", +] + +cleanup = [ +] + +[[variables]] +name = "project_name" +default = "My-CLI" +prompt = "What's the name of the project?" +validation = "^([a-zA-Z][a-zA-Z0-9_-]+)$" + +[[variables]] +name = "bin" +default = "my-cli" +prompt = "What's the name of the executable?" +validation = "^([a-zA-Z][a-zA-Z-_]+)$" + +[[variables]] +name = "description" +default = "A CLI application" +prompt = "A short description of the app?" diff --git a/{{project_name}}/Cargo.toml b/{{project_name}}/Cargo.toml new file mode 100644 index 0000000..30e9446 --- /dev/null +++ b/{{project_name}}/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "{{project_name}}" +version = "0.0.1" +authors = ["Hatter Jiang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = "2.33" +toml = "0.5" +rust_util = "0.6" + diff --git a/{{project_name}}/src/cmd.rs b/{{project_name}}/src/cmd.rs new file mode 100644 index 0000000..6ec2e12 --- /dev/null +++ b/{{project_name}}/src/cmd.rs @@ -0,0 +1,13 @@ +use clap::{ArgMatches, App}; +use rust_util::XResult; + +pub type CommandError = XResult<()>; + +pub trait Command { + + fn name(&self) -> &str; + + fn subcommand<'a>(&self) -> App<'a, 'a>; + + fn run(&self, arg_matches: &ArgMatches, _: &ArgMatches) -> CommandError; +} diff --git a/{{project_name}}/src/cmd_default.rs b/{{project_name}}/src/cmd_default.rs new file mode 100644 index 0000000..33ac253 --- /dev/null +++ b/{{project_name}}/src/cmd_default.rs @@ -0,0 +1,19 @@ +use clap::{App, Arg, ArgMatches}; +use crate::cmd::CommandError; + +pub struct CommandImpl; + +impl CommandImpl { + + pub fn process_command<'a>(app: App<'a, 'a>) -> App<'a, 'a> { + app.arg(Arg::with_name("verbose").long("verbose").short("v").multiple(true).help("Show verbose info")) + } + + pub fn run(arg_matches: &ArgMatches) -> CommandError { + let verbose_count = arg_matches.occurrences_of("verbose"); + information!("Verbose count: {}", verbose_count); + information!("This is default command cli ..."); + // TODO ... + Ok(()) + } +} \ No newline at end of file diff --git a/{{project_name}}/src/cmd_sample.rs b/{{project_name}}/src/cmd_sample.rs new file mode 100644 index 0000000..10d6282 --- /dev/null +++ b/{{project_name}}/src/cmd_sample.rs @@ -0,0 +1,17 @@ +use clap::{ArgMatches, SubCommand, App}; +use crate::cmd::{Command, CommandError}; + +pub struct CommandImpl; + +impl Command for CommandImpl { + + fn name(&self) -> &str { "sample" } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()).about("Sample subcommand") + } + + fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError { + Ok(()) + } +} \ No newline at end of file diff --git a/{{project_name}}/src/main.rs b/{{project_name}}/src/main.rs new file mode 100644 index 0000000..8b3c043 --- /dev/null +++ b/{{project_name}}/src/main.rs @@ -0,0 +1,30 @@ +#[macro_use] extern crate rust_util; + +mod cmd; +mod cmd_default; +mod cmd_sample; + +use clap::App; +use cmd::{Command, CommandError}; + +fn main() -> CommandError { + let commands: Vec> = vec![ + Box::new(cmd_test::CommandImpl) + ]; + let mut app = App::new(env!("CARGO_PKG_NAME")) + .version(env!("CARGO_PKG_VERSION")) + .about(env!("CARGO_PKG_DESCRIPTION")); + app = cmd_default::CommandImpl::process_command(app); + for command in &commands { + app = app.subcommand(command.subcommand()); + } + + let matches = app.get_matches(); + for command in &commands { + if let Some(sub_cmd_matches) = matches.subcommand_matches(command.name()) { + return command.run(&matches, sub_cmd_matches); + } + } + + cmd_default::CommandImpl::run(&matches) +}