Quick sketch adding derived cmd line arg parsing to veilid-cli
Quick sketch showing cmd line args via clap-derive (same underlying parser, but simplifies cmd line parsing logic and reduces surface area for potential bugs)
This commit is contained in:
parent
2d2983e16e
commit
5bc1410bd6
117
Cargo.lock
generated
117
Cargo.lock
generated
@ -154,6 +154,55 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||||
|
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.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.72"
|
version = "1.0.72"
|
||||||
@ -966,13 +1015,48 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"clap_lex",
|
"clap_lex 0.2.4",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"strsim 0.10.0",
|
"strsim 0.10.0",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"textwrap 0.16.0",
|
"textwrap 0.16.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex 0.5.0",
|
||||||
|
"strsim 0.10.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.3.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.27",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
@ -982,6 +1066,12 @@ dependencies = [
|
|||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "4.5.0"
|
version = "4.5.0"
|
||||||
@ -1021,6 +1111,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.6"
|
version = "4.6.6"
|
||||||
@ -2552,6 +2648,17 @@ version = "2.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.2",
|
||||||
|
"rustix 0.38.4",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
@ -5622,6 +5729,12 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -5655,7 +5768,7 @@ dependencies = [
|
|||||||
"async-tungstenite 0.8.0",
|
"async-tungstenite 0.8.0",
|
||||||
"bugsalot",
|
"bugsalot",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"clap 3.2.25",
|
"clap 4.3.21",
|
||||||
"config",
|
"config",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"cursive",
|
"cursive",
|
||||||
|
@ -27,7 +27,7 @@ cursive_buffered_backend = { path = "../external/cursive_buffered_backend" }
|
|||||||
cursive_table_view = "0.14.0"
|
cursive_table_view = "0.14.0"
|
||||||
arboard = "3.2.0"
|
arboard = "3.2.0"
|
||||||
# cursive-tabs = "0.5.0"
|
# cursive-tabs = "0.5.0"
|
||||||
clap = "^3"
|
clap = {version= "4", features = ["derive"]}
|
||||||
directories = "^4"
|
directories = "^4"
|
||||||
log = "^0"
|
log = "^0"
|
||||||
futures = "^0"
|
futures = "^0"
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
|
|
||||||
use crate::tools::*;
|
use crate::tools::*;
|
||||||
|
|
||||||
use clap::{Arg, ColorChoice, Command};
|
use clap::{Parser, ValueEnum};
|
||||||
use flexi_logger::*;
|
use flexi_logger::*;
|
||||||
use std::ffi::OsStr;
|
use std::{net::ToSocketAddrs, path::PathBuf};
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
mod client_api_connection;
|
mod client_api_connection;
|
||||||
mod command_processor;
|
mod command_processor;
|
||||||
@ -17,62 +15,45 @@ mod settings;
|
|||||||
mod tools;
|
mod tools;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
fn parse_command_line(default_config_path: &OsStr) -> Result<clap::ArgMatches, String> {
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
||||||
let matches = Command::new("veilid-cli")
|
enum LogLevel {
|
||||||
.version("0.1")
|
/// Turn on debug logging
|
||||||
.color(ColorChoice::Auto)
|
Debug,
|
||||||
.about("Veilid Console Client")
|
/// Turn on trace logging
|
||||||
.arg(
|
Trace,
|
||||||
Arg::new("address")
|
}
|
||||||
.required(false)
|
|
||||||
.help("Address to connect to"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("debug")
|
|
||||||
.long("debug")
|
|
||||||
.help("Turn on debug logging"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("wait-for-debug")
|
|
||||||
.long("wait-for-debug")
|
|
||||||
.help("Wait for debugger to attach"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("trace")
|
|
||||||
.long("trace")
|
|
||||||
.conflicts_with("debug")
|
|
||||||
.help("Turn on trace logging"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new("config-file")
|
|
||||||
.short('c')
|
|
||||||
.takes_value(true)
|
|
||||||
.value_name("FILE")
|
|
||||||
.default_value_os(default_config_path)
|
|
||||||
.allow_invalid_utf8(true)
|
|
||||||
.help("Specify a configuration file to use"),
|
|
||||||
)
|
|
||||||
.get_matches();
|
|
||||||
|
|
||||||
Ok(matches)
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about = "Veilid Console Client")]
|
||||||
|
struct CmdlineArgs {
|
||||||
|
/// Address to connect to
|
||||||
|
#[arg(long)]
|
||||||
|
address: Option<String>,
|
||||||
|
/// Wait for debugger to attach
|
||||||
|
#[arg(long)]
|
||||||
|
wait_for_debug: bool,
|
||||||
|
/// Specify a configuration file to use
|
||||||
|
#[arg(short, long, value_name = "FILE", /*allow_invalid_utf8 = true*/)]
|
||||||
|
config_file: Option<PathBuf>,
|
||||||
|
/// log level
|
||||||
|
#[arg(value_enum)]
|
||||||
|
log_level: Option<LogLevel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
// Get command line options
|
// Get command line options
|
||||||
let default_config_path = settings::Settings::get_default_config_path();
|
let default_config_path = settings::Settings::get_default_config_path();
|
||||||
let matches = parse_command_line(default_config_path.as_os_str())?;
|
let args = CmdlineArgs::parse();
|
||||||
if matches.occurrences_of("wait-for-debug") != 0 {
|
|
||||||
|
if args.wait_for_debug {
|
||||||
use bugsalot::debugger;
|
use bugsalot::debugger;
|
||||||
debugger::wait_until_attached(None).expect("state() not implemented on this platform");
|
debugger::wait_until_attached(None).expect("state() not implemented on this platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to load configuration
|
// Attempt to load configuration
|
||||||
let settings_path = if let Some(config_file) = matches.value_of_os("config-file") {
|
let settings_path = args.config_file.unwrap_or(default_config_path);
|
||||||
if Path::new(config_file).exists() {
|
let settings_path = if settings_path.exists() {
|
||||||
Some(config_file)
|
Some(settings_path.into_os_string())
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -81,11 +62,11 @@ fn main() -> Result<(), String> {
|
|||||||
.map_err(|e| format!("configuration is invalid: {}", e))?;
|
.map_err(|e| format!("configuration is invalid: {}", e))?;
|
||||||
|
|
||||||
// Set config from command line
|
// Set config from command line
|
||||||
if matches.occurrences_of("debug") != 0 {
|
if let Some(LogLevel::Debug) = args.log_level {
|
||||||
settings.logging.level = settings::LogLevel::Debug;
|
settings.logging.level = settings::LogLevel::Debug;
|
||||||
settings.logging.terminal.enabled = true;
|
settings.logging.terminal.enabled = true;
|
||||||
}
|
}
|
||||||
if matches.occurrences_of("trace") != 0 {
|
if let Some(LogLevel::Trace) = args.log_level {
|
||||||
settings.logging.level = settings::LogLevel::Trace;
|
settings.logging.level = settings::LogLevel::Trace;
|
||||||
settings.logging.terminal.enabled = true;
|
settings.logging.terminal.enabled = true;
|
||||||
}
|
}
|
||||||
@ -142,7 +123,7 @@ fn main() -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get client address
|
// Get client address
|
||||||
let server_addrs = if let Some(address_arg) = matches.value_of("address") {
|
let server_addrs = if let Some(address_arg) = args.address {
|
||||||
address_arg
|
address_arg
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.map_err(|e| format!("Invalid server address '{}'", e))?
|
.map_err(|e| format!("Invalid server address '{}'", e))?
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use directories::*;
|
use directories::*;
|
||||||
|
|
||||||
use serde_derive::*;
|
use serde_derive::*;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsString;
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -234,13 +234,13 @@ impl Settings {
|
|||||||
default_log_directory
|
default_log_directory
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(config_file: Option<&OsStr>) -> Result<Self, config::ConfigError> {
|
pub fn new(config_file: Option<OsString>) -> Result<Self, config::ConfigError> {
|
||||||
// Load the default config
|
// Load the default config
|
||||||
let mut cfg = load_default_config()?;
|
let mut cfg = load_default_config()?;
|
||||||
|
|
||||||
// Merge in the config file if we have one
|
// Merge in the config file if we have one
|
||||||
if let Some(config_file) = config_file {
|
if let Some(config_file) = config_file {
|
||||||
let config_file_path = Path::new(config_file);
|
let config_file_path = Path::new(&config_file);
|
||||||
// If the user specifies a config file on the command line then it must exist
|
// If the user specifies a config file on the command line then it must exist
|
||||||
cfg = load_config(cfg, config_file_path)?;
|
cfg = load_config(cfg, config_file_path)?;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user