diff --git a/Cargo.toml b/Cargo.toml index 12743a5..f3750e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ anyhow = "1.0" clap = { version = "4.3", features = ["derive"] } colored = "2.0" loop_lib = { path = "../loop_lib" } +# Any 0.x, as for loop_lib +meta_core = { path = "../meta_core", version = "<1" } rayon = "1.7" serde_json = "1.0" walkdir = "2.3" diff --git a/src/main.rs b/src/main.rs index 8f70bb7..e6dcd82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,7 +41,7 @@ struct Cli { } fn main() -> Result<()> { - let cli = Cli::parse(); + let cli = parse_cli(); let config_path = cli.config.unwrap_or_else(|| PathBuf::from(".looprc")); @@ -50,13 +50,19 @@ fn main() -> Result<()> { std::process::exit(0); } - // Parse the .meta file + // Parse the .looprc file let absolute_path = std::env::current_dir()?.join(&config_path); if cli.verbose { println!("{}", "Verbose mode enabled".green()); - println!("\nResolved config file path: {}", absolute_path.display()); - println!("Executing command: {}", display_command(&cli.command)); + println!( + "\nResolved config file path: {}", + meta_core::display::escape_path(&absolute_path) + ); + println!( + "Executing command: {}", + meta_core::display::escape(&display_command(&cli.command)) + ); } let mut config = if config_path.exists() { @@ -87,3 +93,30 @@ fn main() -> Result<()> { Ok(()) } + +/// Parse the command line. Clap quotes rejected values as given, so an error +/// is shown from the escaped arguments: the same error, with values that +/// can't move the cursor or forge a line. +fn parse_cli() -> Cli { + use clap::error::ErrorKind; + Cli::try_parse().unwrap_or_else(|e| match e.kind() { + // clap's invalid UTF-8 error doesn't echo the value + ErrorKind::DisplayHelp + | ErrorKind::DisplayVersion + | ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand + | ErrorKind::InvalidUtf8 => e.exit(), + _ => { + let shown = std::env::args_os() + .map(|arg| meta_core::display::escape(&arg.to_string_lossy()).into_owned()); + match Cli::try_parse_from(shown) { + Err(shown) => shown.exit(), + Ok(_) => Cli::command() + .error( + ErrorKind::InvalidValue, + "an argument contains a control character", + ) + .exit(), + } + } + }) +}