diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index 020cf366b..aa85c3df1 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -71,6 +71,55 @@ dependencies = [ "yansi-term", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -317,15 +366,34 @@ version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ - "atty", "bitflags", - "clap_lex", + "clap_lex 0.2.4", "indexmap", - "strsim", - "termcolor", "textwrap 0.16.0", ] +[[package]] +name = "clap" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex 0.5.0", + "strsim", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -335,6 +403,18 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "compiler_base_error" version = "0.0.8" @@ -1415,7 +1495,7 @@ name = "kclvm-cmd" version = "0.5.0" dependencies = [ "anyhow", - "clap 3.2.25", + "clap 4.3.0", "compiler_base_session", "kclvm-api", "kclvm-config", @@ -3656,6 +3736,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "vergen" version = "8.1.3" diff --git a/kclvm/cmd/Cargo.toml b/kclvm/cmd/Cargo.toml index a23f8e39c..6a9e24eaf 100644 --- a/kclvm/cmd/Cargo.toml +++ b/kclvm/cmd/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] anyhow = "1.0" -clap = "3.2.22" +clap = "4.3.0" compiler_base_session = {path = "../../compiler_base/session"} kclvm-api = {path = "../api"} diff --git a/kclvm/cmd/src/fmt.rs b/kclvm/cmd/src/fmt.rs index aabf676c7..78f2d3a83 100644 --- a/kclvm/cmd/src/fmt.rs +++ b/kclvm/cmd/src/fmt.rs @@ -5,7 +5,7 @@ use kclvm_tools::format::{format, FormatOptions}; /// Run the KCL fmt command. pub fn fmt_command(matches: &ArgMatches) -> Result<()> { - let input = matches.value_of("input"); + let input = matches.get_one::("input").map(|f| f.as_str()); match input { Some(input) => { format( diff --git a/kclvm/cmd/src/lib.rs b/kclvm/cmd/src/lib.rs index be24b246f..17b469160 100644 --- a/kclvm/cmd/src/lib.rs +++ b/kclvm/cmd/src/lib.rs @@ -13,6 +13,8 @@ pub mod vet; #[cfg(test)] mod tests; +use clap::{ArgAction, Command}; + use std::io; use anyhow::Result; @@ -25,71 +27,66 @@ use vet::vet_command; pub fn main(args: &[&str]) -> Result<()> { let matches = app().arg_required_else_help(true).get_matches_from(args); // Sub commands - if let Some(matches) = matches.subcommand_matches("run") { - run_command(matches, &mut io::stdout()) - } else if let Some(matches) = matches.subcommand_matches("lint") { - lint_command(matches) - } else if let Some(matches) = matches.subcommand_matches("fmt") { - fmt_command(matches) - } else if let Some(matches) = matches.subcommand_matches("vet") { - vet_command(matches) - } else if matches.subcommand_matches("server").is_some() { - kclvm_api::service::jsonrpc::start_stdio_server() - } else if matches.subcommand_matches("version").is_some() { - println!("{}", kclvm_version::get_version_info()); - Ok(()) - } else { - Ok(()) + match matches.subcommand() { + Some(("run", sub_matches)) => run_command(sub_matches, &mut io::stdout()), + Some(("lint", sub_matches)) => lint_command(sub_matches), + Some(("fmt", sub_matches)) => fmt_command(sub_matches), + Some(("vet", sub_matches)) => vet_command(sub_matches), + Some(("server", _)) => kclvm_api::service::jsonrpc::start_stdio_server(), + Some(("version", _)) => { + println!("{}", kclvm_version::get_version_info()); + Ok(()) + } + _ => Ok(()), } } /// Get the KCLVM CLI application. -pub fn app() -> clap::App<'static> { - clap_app!(kclvm_cli => - (version: kclvm_version::VERSION) - (about: "KCL main CLI") - (@subcommand run => - (about: "Run KCL files") - (@arg input: ... "Specify the input files to run") - (@arg output: -o --output +takes_value "Specify the YAML output file path") - (@arg setting: ... -Y --setting +takes_value "Specify the input setting file") - (@arg verbose: -v --verbose "Print test information verbosely") - (@arg disable_none: -n --disable_none "Disable dumping None values") - (@arg strict_range_check: -r --strict_range_check "Do perform strict numeric range checks") - (@arg debug: -d --debug "Run in debug mode (for developers only)") - (@arg sort_keys: -k --sort_keys "Sort result keys") - (@arg arguments: ... -D --argument +takes_value "Specify the top-level argument") - (@arg path_selector: ... -S --path_selector "Specify the path selector") - (@arg overrides: ... -O --overrides +takes_value "Specify the configuration override path and value") - (@arg target: --target +takes_value "Specify the target type") - (@arg package_map: ... -E --external +takes_value "Mapping of package name and path where the package is located") - ) - (@subcommand lint => - (about: "Lint KCL files") - (@arg input: ... "Sets the input file to use") - (@arg setting: ... -Y --setting +takes_value "Sets the input file to use") - (@arg verbose: -v --verbose "Print test information verbosely") - (@arg emit_warning: --emit_warning "Emit warning message") - ) - (@subcommand fmt => - (about: "Format KCL files") - (@arg input: "Input file or path name for formatting") - (@arg recursive: -R --recursive "Iterate through subdirectories recursively") - (@arg std_output: -w --std_output "Whether to output format to stdout") +pub fn app() -> Command { + Command::new("kclvm_cli") + .version(kclvm_version::VERSION) + .about("KCL main CLI.") + .subcommand( + Command::new("run") + .about("run") + .arg(arg!([input] ... "Specify the input files to run").num_args(0..)) + .arg(arg!(output: -o --output "Specify the YAML output file path")) + .arg(arg!(setting: -Y --setting ... "Specify the input setting file").num_args(1..)) + .arg(arg!(verbose: -v --verbose "Print test information verbosely").action(ArgAction::Count)) + .arg(arg!(disable_none: -n --disable_none "Disable dumping None values")) + .arg(arg!(strict_range_check: -r --strict_range_check "Do perform strict numeric range checks")) + .arg(arg!(debug: -d --debug "Run in debug mode (for developers only)")) + .arg(arg!(sort_keys: -k --sort_keys "Sort result keys")) + .arg(arg!(arguments: -D --argument ... "Specify the top-level argument").num_args(1..)) + .arg(arg!(path_selector: -S --path_selector ... "Specify the path selector").num_args(1..)) + .arg(arg!(overrides: -O --overrides ... "Specify the configuration override path and value").num_args(1..)) + .arg(arg!(target: --target "Specify the target type")) + .arg(arg!(package_map: -E --external ... "Mapping of package name and path where the package is located").num_args(1..)), ) - (@subcommand vet => - (about: "Validate data files with KCL files") - (@arg data_file: "Validation data file") - (@arg kcl_file: "KCL file") - (@arg schema: -d --schema +takes_value "Iterate through subdirectories recursively") - (@arg attribute_name: -n --attribute_name +takes_value "The attribute name for the data loading") - (@arg format: --format +takes_value "Validation data file format, support YAML and JSON, default is JSON") + .subcommand( + Command::new("lint") + .about("lint") + .arg(arg!([input] ... "Sets the input file to use").num_args(0..)) + .arg(arg!(setting: -Y --setting ... "Sets the input file to use").num_args(1..)) + .arg(arg!(verbose: -v --verbose "Print test information verbosely").action(ArgAction::Count)) + .arg(arg!(emit_warning: --emit_warning "Emit warning message")), ) - (@subcommand server => - (about: "Start a rpc server for APIs") + .subcommand( + Command::new("fmt") + .about("Format KCL files") + .arg(arg!( "Input file or path name for formatting")) + .arg(arg!(recursive: -R --recursive "Iterate through subdirectories recursively")) + .arg(arg!(std_output: -w --std_output "Whether to output format to stdout")), ) - (@subcommand version => - (about: "Show the KCL version") + .subcommand( + Command::new("vet") + .about("Validate data files witch KCL files") + .arg(arg!( "Validation data file")) + .arg(arg!( "KCL file")) + .arg(arg!(schema: -d --schema "Iterate through subdirectories recursively").num_args(1..)) + .arg(arg!(attribute_name: -n --attribute_name "The attribute name for the data loading")) + .arg(arg!(format: --format "Validation data file format, support YAML and JSON, default is JSON")), ) - ) + .subcommand(Command::new("server").about("Start a rpc server for APIs")) + .subcommand(Command::new("version").about("Show the KCL version")) } diff --git a/kclvm/cmd/src/lint.rs b/kclvm/cmd/src/lint.rs index 8f5286c8b..f6a8bb36e 100644 --- a/kclvm/cmd/src/lint.rs +++ b/kclvm/cmd/src/lint.rs @@ -8,8 +8,8 @@ use crate::settings::must_build_settings; /// Run the KCL lint command. pub fn lint_command(matches: &ArgMatches) -> Result<()> { - let mut files: Vec<&str> = match matches.values_of("input") { - Some(files) => files.into_iter().collect::>(), + let mut files = match matches.get_many::("input") { + Some(files) => files.into_iter().map(|f| f.as_str()).collect::>(), None => vec![], }; // Config settings building @@ -24,7 +24,7 @@ pub fn lint_command(matches: &ArgMatches) -> Result<()> { let (mut err_handler, mut warning_handler) = (Handler::default(), Handler::default()); (err_handler.diagnostics, warning_handler.diagnostics) = lint_files(&files, Some(args.get_load_program_options())); - if matches.occurrences_of("emit_warning") > 0 { + if matches.get_count("emit_warning") > 0 { warning_handler.emit()?; } err_handler.abort_if_any_errors(); diff --git a/kclvm/cmd/src/settings.rs b/kclvm/cmd/src/settings.rs index ec969c787..3a8d27928 100644 --- a/kclvm/cmd/src/settings.rs +++ b/kclvm/cmd/src/settings.rs @@ -26,14 +26,15 @@ pub(crate) fn must_build_settings(matches: &ArgMatches) -> SettingsPathBuf { /// Build settings from arg matches. pub(crate) fn build_settings(matches: &ArgMatches) -> Result { - let files: Vec<&str> = match matches.values_of("input") { - Some(files) => files.into_iter().collect::>(), + let files: Vec<&str> = match matches.get_many::("input") { + Some(files) => files.into_iter().map(|f| f.as_str()).collect::>(), None => vec![], }; let setting_files = matches - .values_of("setting") - .map(|files| files.into_iter().collect::>()); + .get_many::("setting") + .map(|files| files.into_iter().map(|f| f.as_str()).collect::>()); + let arguments = strings_from_matches(matches, "arguments"); let package_maps = hashmaps_from_matches(matches, "package_map").transpose()?; @@ -43,7 +44,7 @@ pub(crate) fn build_settings(matches: &ArgMatches) -> Result { setting_files, Some(SettingsFile { kcl_cli_configs: Some(Config { - output: matches.value_of("output").map(|v| v.to_string()), + output: matches.get_one::("output").map(|v| v.to_string()), overrides: strings_from_matches(matches, "overrides"), path_selector: strings_from_matches(matches, "path_selector"), strict_range_check: bool_from_matches(matches, "strict_range_check"), diff --git a/kclvm/cmd/src/util.rs b/kclvm/cmd/src/util.rs index 7bdfa7732..c6f53040d 100644 --- a/kclvm/cmd/src/util.rs +++ b/kclvm/cmd/src/util.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; #[inline] pub(crate) fn strings_from_matches(matches: &ArgMatches, key: &str) -> Option> { - matches.values_of(key).map(|files| { + matches.get_many::(key).map(|files| { files .into_iter() .map(|v| v.to_string()) @@ -17,7 +17,7 @@ pub(crate) fn hashmaps_from_matches( matches: &ArgMatches, key: &str, ) -> Option>> { - matches.values_of(key).map(|files| { + matches.get_many::(key).map(|files| { files .into_iter() .map(|s| { @@ -37,13 +37,12 @@ pub(crate) fn hashmaps_from_matches( #[inline] pub(crate) fn string_from_matches(matches: &ArgMatches, key: &str) -> Option { - matches.value_of(key).map(|v| v.to_string()) + matches.get_one::(key).map(|v| v.to_string()) } #[inline] pub(crate) fn bool_from_matches(matches: &ArgMatches, key: &str) -> Option { - let occurrences = matches.occurrences_of(key); - if occurrences > 0 { + if matches.get_flag(key) == true { Some(true) } else { None @@ -52,7 +51,7 @@ pub(crate) fn bool_from_matches(matches: &ArgMatches, key: &str) -> Option #[inline] pub(crate) fn u32_from_matches(matches: &ArgMatches, key: &str) -> Option { - let occurrences = matches.occurrences_of(key); + let occurrences = matches.get_count(key); if occurrences > 0 { Some(occurrences as u32) } else { diff --git a/kclvm/cmd/src/vet.rs b/kclvm/cmd/src/vet.rs index 65683b160..86a1d2950 100644 --- a/kclvm/cmd/src/vet.rs +++ b/kclvm/cmd/src/vet.rs @@ -6,8 +6,8 @@ use crate::util::string_from_matches; /// Run the KCL vet command. pub fn vet_command(matches: &ArgMatches) -> Result<()> { - let data_file = matches.value_of("data_file"); - let kcl_file = matches.value_of("kcl_file"); + let data_file = matches.get_one::("data_file").map(|f| f.as_str()); + let kcl_file = matches.get_one::("kcl_file").map(|f| f.as_str()); match (data_file, kcl_file) { (Some(data_file), Some(kcl_file)) => { validate(ValidateOption::new(