diff --git a/Cargo.lock b/Cargo.lock index 3461dde..e1e04df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -474,6 +474,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunch" version = "0.1.0" @@ -502,6 +527,8 @@ dependencies = [ "clap", "crunch-codegen", "crunch-file", + "inquire", + "regex", "thiserror", "tokio", "tracing", @@ -654,6 +681,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dyn-clone" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" + [[package]] name = "ed25519" version = "1.5.3" @@ -956,6 +989,22 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inquire" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33e7c1ddeb15c9abcbfef6029d8e29f69b52b6d6c891031b88ed91b5065803b" +dependencies = [ + "bitflags 1.3.2", + "crossterm", + "dyn-clone", + "lazy_static", + "newline-converter", + "thiserror", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "instant" version = "0.1.12" @@ -1080,6 +1129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", + "log", "wasi", "windows-sys", ] @@ -1126,6 +1176,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "newline-converter" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f71d09d5c87634207f894c6b31b6a2b2c64ea3bdcf71bd5599fdbbe1600c00f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "nkeys" version = "0.2.0" @@ -1736,6 +1795,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2096,6 +2176,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "untrusted" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index d1510fc..3f67b69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,5 +32,6 @@ tempfile = {version = "3.8.0"} genco = {version = "0.17.5"} walkdir = {version = "2.4.0"} regex = {version = "1.9.5"} +inquire = {version = "0.6.2"} pretty_assertions = "1.4.0" \ No newline at end of file diff --git a/crates/crunch-cli/Cargo.toml b/crates/crunch-cli/Cargo.toml index 427951f..b7f9879 100644 --- a/crates/crunch-cli/Cargo.toml +++ b/crates/crunch-cli/Cargo.toml @@ -5,6 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "crunch" +path = "src/main.rs" + [dependencies] crunch-file.workspace = true crunch-codegen.workspace = true @@ -16,3 +20,5 @@ thiserror.workspace = true async-trait.workspace = true tracing-subscriber.workspace = true clap.workspace = true +inquire.workspace = true +regex.workspace = true diff --git a/crates/crunch-cli/src/main.rs b/crates/crunch-cli/src/main.rs index 4176468..8427e62 100644 --- a/crates/crunch-cli/src/main.rs +++ b/crates/crunch-cli/src/main.rs @@ -4,7 +4,10 @@ use std::path::PathBuf; use anyhow::anyhow; use clap::{Args, Parser, Subcommand}; +use inquire::validator::Validation; use logging::LogArg; +use regex::Regex; +use tokio::io::AsyncWriteExt; #[derive(Parser, Clone)] #[command(author, version, about, long_about = None, subcommand_required = true)] @@ -19,6 +22,7 @@ struct Cli { #[derive(Subcommand, Clone)] enum Commands { Generate {}, + Init {}, } #[derive(Args, Clone)] @@ -69,6 +73,72 @@ async fn main() -> anyhow::Result<()> { } } } + Commands::Init {} => { + match config::get_file(&cli.global_args.crunch_file).await { + Ok(_) => anyhow::bail!("config file already exists"), + Err(_) => {} + } + + let path = &cli.global_args.crunch_file; + let file_name = path + .file_name() + .ok_or(anyhow::anyhow!("not a valid file name"))?; + if file_name != ".crunch.toml" { + anyhow::bail!("--crunch-file always has to end with file: .crunch.toml"); + } + if let Some(dir) = path.parent() { + if !dir.exists() { + tokio::fs::create_dir_all(dir).await?; + } + } + + fn validate_text( + text: &str, + ) -> Result> + { + let regex = Regex::new("^[a-z0-9-_]+$").expect("is required to be valid regex"); + if regex.is_match(text) { + Ok(Validation::Valid) + } else { + Ok(Validation::Invalid( + "a service name can only contain lowercase letter, numbers, - and _".into(), + )) + } + } + + let service = inquire::Text::new("service") + .with_help_message("please insert your service name") + .with_validator(validate_text) + .prompt()?; + let domain = inquire::Text::new("domain") + .with_help_message("please insert your domain") + .with_validator(validate_text) + .prompt()?; + let codegen = inquire::MultiSelect::new("codegen", vec!["rust", "go"]) + .with_help_message("which types of client code should be generated for you?") + .prompt()?; + + let mut crunch_file = tokio::fs::File::create(path).await?; + crunch_file + .write_all( + format!( + r#"[service] +service = "{service}" +domain = "{domain}" +codegen = [{}] +"#, + codegen + .iter() + .map(|c| format!(r#""{c}""#)) + .collect::>() + .join(", ") + ) + .as_bytes(), + ) + .await?; + + println!("Success! generated file at: {}", path.display()); + } } Ok(())