diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 45724de..f9dd655 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -53,5 +53,8 @@ jobs: - name: Build run: cargo build --verbose + - name: Build binary + run: cargo build --features build-binary --verbose + - name: Run tests run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index 3ff40e0..d3c50c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,12 +17,65 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -45,6 +98,8 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" name = "casbab" version = "0.1.0" dependencies = [ + "atty", + "clap", "criterion", ] @@ -102,8 +157,10 @@ version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim", ] [[package]] @@ -112,6 +169,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "criterion" version = "0.5.1" @@ -201,6 +264,15 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.3" @@ -213,7 +285,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.3", "rustix", "windows-sys", ] @@ -441,6 +513,12 @@ dependencies = [ "serde", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "2.0.48" @@ -468,6 +546,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "walkdir" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index a1acb07..a607858 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ authors = ["Janos Guljas "] keywords = ["camel", "snake", "kebab", "pascal"] [dependencies] +atty = { version = "0.2.14", optional = true } +clap = { version = "4.4.13", optional = true } [dev-dependencies] criterion = "0.5.1" @@ -16,3 +18,13 @@ criterion = "0.5.1" [[bench]] name = "benchmark" harness = false + +[lib] +name = "casbab" + +[features] +build-binary = ["atty", "clap"] + +[[bin]] +name = "casbab" +required-features = ["build-binary"] diff --git a/src/bin/casbab.rs b/src/bin/casbab.rs new file mode 100644 index 0000000..d0c5c2c --- /dev/null +++ b/src/bin/casbab.rs @@ -0,0 +1,86 @@ +// Copyright (c) 2024, Janoš Guljaš +// All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +use atty::Stream; +use clap::{arg, error::ErrorKind, Command}; +use std::io; + +fn main() { + let cmd = Command::new("casbab") + .about("Camel Snake Kebab (https://github.com/janos/casbab-rs)") + .disable_version_flag(true) + .arg_required_else_help(true) + .author("Janos Guljas ") + .arg(arg!( "Convert into dialect. Possible values: +- camel `camelSnakeKebab` +- pascal `CamelSnakeKebab` +- snake `camel_snake_kebab` +- camel-snake `Camel_Snake_Kebab` +- screaming-snake `CAMEL_SNAKE_KEBAB` +- kebab `camel-snake-kebab` +- camel-kebab `Camel-Snake-Kebab` +- screaming-kebab `CAMEL-SNAKE-KEBAB` +- lower `camel snake kebab` +- title `Camel Snake Kebab` +- screaming `CAMEL SNAKE KEBAB` + +If no phrases are provided as arguments, arguments will be read from the +Stdin as the new-line separated list. +")) + .arg( + arg!( ... "phrases to convert") + .trailing_var_arg(true) + .required(false), + ); + + let matches = cmd.clone().get_matches(); + + let dialect: &str = matches + .get_one::("dialect") + .expect("`dialect` is required") + .as_str(); + + let func = match dialect { + "camel" => casbab::camel, + "pascal" => casbab::pascal, + "snake" => casbab::snake, + "camel-snake" => casbab::camel_snake, + "screaming-snake" => casbab::screaming_snake, + "kebab" => casbab::kebab, + "camel-kebab" => casbab::camel_kebab, + "screaming-kebab" => casbab::screaming_kebab, + "lower" => casbab::lower, + "title " => casbab::title, + "screaming" => casbab::screaming, + _ => { + cmd.clone() + .error(ErrorKind::InvalidSubcommand, "Invalid dialect") + .exit(); + } + }; + + let phrases: Vec = match matches.get_many("phrases") { + None => { + if atty::is(Stream::Stdin) { + cmd.clone() + .error( + ErrorKind::InvalidValue, + "Missing phases either from arguments or stdin", + ) + .exit(); + } + let mut phrases: Vec = Vec::new(); + for line in io::stdin().lines() { + phrases.push(line.unwrap()) + } + phrases + } + Some(o) => o.cloned().collect(), + }; + + for p in phrases { + println!("{}", func(p.as_str())); + } +}