119625d8cSopenharmony_ci// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, 219625d8cSopenharmony_ci// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and 319625d8cSopenharmony_ci// Ana Hobden (@hoverbear) <operator@hoverbear.org> 419625d8cSopenharmony_ci// 519625d8cSopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 619625d8cSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 719625d8cSopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 819625d8cSopenharmony_ci// option. This file may not be copied, modified, or distributed 919625d8cSopenharmony_ci// except according to those terms. 1019625d8cSopenharmony_ci// 1119625d8cSopenharmony_ci// This work was derived from Structopt (https://github.com/TeXitoi/structopt) 1219625d8cSopenharmony_ci// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the 1319625d8cSopenharmony_ci// MIT/Apache 2.0 license. 1419625d8cSopenharmony_ci 1519625d8cSopenharmony_ciuse crate::utils; 1619625d8cSopenharmony_ci 1719625d8cSopenharmony_ciuse clap::{Args, Parser, Subcommand}; 1819625d8cSopenharmony_ci 1919625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 2019625d8cSopenharmony_cienum Opt { 2119625d8cSopenharmony_ci /// Fetch stuff from GitHub 2219625d8cSopenharmony_ci Fetch { 2319625d8cSopenharmony_ci #[arg(long)] 2419625d8cSopenharmony_ci all: bool, 2519625d8cSopenharmony_ci /// Overwrite local branches. 2619625d8cSopenharmony_ci #[arg(short, long)] 2719625d8cSopenharmony_ci force: bool, 2819625d8cSopenharmony_ci 2919625d8cSopenharmony_ci repo: String, 3019625d8cSopenharmony_ci }, 3119625d8cSopenharmony_ci 3219625d8cSopenharmony_ci Add { 3319625d8cSopenharmony_ci #[arg(short, long)] 3419625d8cSopenharmony_ci interactive: bool, 3519625d8cSopenharmony_ci #[arg(short, long)] 3619625d8cSopenharmony_ci verbose: bool, 3719625d8cSopenharmony_ci }, 3819625d8cSopenharmony_ci} 3919625d8cSopenharmony_ci 4019625d8cSopenharmony_ci#[test] 4119625d8cSopenharmony_cifn test_fetch() { 4219625d8cSopenharmony_ci assert_eq!( 4319625d8cSopenharmony_ci Opt::Fetch { 4419625d8cSopenharmony_ci all: true, 4519625d8cSopenharmony_ci force: false, 4619625d8cSopenharmony_ci repo: "origin".to_string() 4719625d8cSopenharmony_ci }, 4819625d8cSopenharmony_ci Opt::try_parse_from(["test", "fetch", "--all", "origin"]).unwrap() 4919625d8cSopenharmony_ci ); 5019625d8cSopenharmony_ci assert_eq!( 5119625d8cSopenharmony_ci Opt::Fetch { 5219625d8cSopenharmony_ci all: false, 5319625d8cSopenharmony_ci force: true, 5419625d8cSopenharmony_ci repo: "origin".to_string() 5519625d8cSopenharmony_ci }, 5619625d8cSopenharmony_ci Opt::try_parse_from(["test", "fetch", "-f", "origin"]).unwrap() 5719625d8cSopenharmony_ci ); 5819625d8cSopenharmony_ci} 5919625d8cSopenharmony_ci 6019625d8cSopenharmony_ci#[test] 6119625d8cSopenharmony_cifn test_add() { 6219625d8cSopenharmony_ci assert_eq!( 6319625d8cSopenharmony_ci Opt::Add { 6419625d8cSopenharmony_ci interactive: false, 6519625d8cSopenharmony_ci verbose: false 6619625d8cSopenharmony_ci }, 6719625d8cSopenharmony_ci Opt::try_parse_from(["test", "add"]).unwrap() 6819625d8cSopenharmony_ci ); 6919625d8cSopenharmony_ci assert_eq!( 7019625d8cSopenharmony_ci Opt::Add { 7119625d8cSopenharmony_ci interactive: true, 7219625d8cSopenharmony_ci verbose: true 7319625d8cSopenharmony_ci }, 7419625d8cSopenharmony_ci Opt::try_parse_from(["test", "add", "-i", "-v"]).unwrap() 7519625d8cSopenharmony_ci ); 7619625d8cSopenharmony_ci} 7719625d8cSopenharmony_ci 7819625d8cSopenharmony_ci#[test] 7919625d8cSopenharmony_cifn test_no_parse() { 8019625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "badcmd", "-i", "-v"]); 8119625d8cSopenharmony_ci assert!(result.is_err()); 8219625d8cSopenharmony_ci 8319625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "add", "--badoption"]); 8419625d8cSopenharmony_ci assert!(result.is_err()); 8519625d8cSopenharmony_ci 8619625d8cSopenharmony_ci let result = Opt::try_parse_from(["test"]); 8719625d8cSopenharmony_ci assert!(result.is_err()); 8819625d8cSopenharmony_ci} 8919625d8cSopenharmony_ci 9019625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 9119625d8cSopenharmony_cienum Opt2 { 9219625d8cSopenharmony_ci DoSomething { arg: String }, 9319625d8cSopenharmony_ci} 9419625d8cSopenharmony_ci 9519625d8cSopenharmony_ci#[test] 9619625d8cSopenharmony_ci/// This test is specifically to make sure that hyphenated subcommands get 9719625d8cSopenharmony_ci/// processed correctly. 9819625d8cSopenharmony_cifn test_hyphenated_subcommands() { 9919625d8cSopenharmony_ci assert_eq!( 10019625d8cSopenharmony_ci Opt2::DoSomething { 10119625d8cSopenharmony_ci arg: "blah".to_string() 10219625d8cSopenharmony_ci }, 10319625d8cSopenharmony_ci Opt2::try_parse_from(["test", "do-something", "blah"]).unwrap() 10419625d8cSopenharmony_ci ); 10519625d8cSopenharmony_ci} 10619625d8cSopenharmony_ci 10719625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 10819625d8cSopenharmony_cienum Opt3 { 10919625d8cSopenharmony_ci Add, 11019625d8cSopenharmony_ci Init, 11119625d8cSopenharmony_ci Fetch, 11219625d8cSopenharmony_ci} 11319625d8cSopenharmony_ci 11419625d8cSopenharmony_ci#[test] 11519625d8cSopenharmony_cifn test_null_commands() { 11619625d8cSopenharmony_ci assert_eq!(Opt3::Add, Opt3::try_parse_from(["test", "add"]).unwrap()); 11719625d8cSopenharmony_ci assert_eq!(Opt3::Init, Opt3::try_parse_from(["test", "init"]).unwrap()); 11819625d8cSopenharmony_ci assert_eq!( 11919625d8cSopenharmony_ci Opt3::Fetch, 12019625d8cSopenharmony_ci Opt3::try_parse_from(["test", "fetch"]).unwrap() 12119625d8cSopenharmony_ci ); 12219625d8cSopenharmony_ci} 12319625d8cSopenharmony_ci 12419625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 12519625d8cSopenharmony_ci#[command(about = "Not shown")] 12619625d8cSopenharmony_cistruct Add { 12719625d8cSopenharmony_ci file: String, 12819625d8cSopenharmony_ci} 12919625d8cSopenharmony_ci/// Not shown 13019625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 13119625d8cSopenharmony_cistruct Fetch { 13219625d8cSopenharmony_ci remote: String, 13319625d8cSopenharmony_ci} 13419625d8cSopenharmony_ci#[derive(Parser, PartialEq, Eq, Debug)] 13519625d8cSopenharmony_cienum Opt4 { 13619625d8cSopenharmony_ci // Not shown 13719625d8cSopenharmony_ci /// Add a file 13819625d8cSopenharmony_ci Add(Add), 13919625d8cSopenharmony_ci Init, 14019625d8cSopenharmony_ci /// download history from remote 14119625d8cSopenharmony_ci Fetch(Fetch), 14219625d8cSopenharmony_ci} 14319625d8cSopenharmony_ci 14419625d8cSopenharmony_ci#[test] 14519625d8cSopenharmony_cifn test_tuple_commands() { 14619625d8cSopenharmony_ci assert_eq!( 14719625d8cSopenharmony_ci Opt4::Add(Add { 14819625d8cSopenharmony_ci file: "f".to_string() 14919625d8cSopenharmony_ci }), 15019625d8cSopenharmony_ci Opt4::try_parse_from(["test", "add", "f"]).unwrap() 15119625d8cSopenharmony_ci ); 15219625d8cSopenharmony_ci assert_eq!(Opt4::Init, Opt4::try_parse_from(["test", "init"]).unwrap()); 15319625d8cSopenharmony_ci assert_eq!( 15419625d8cSopenharmony_ci Opt4::Fetch(Fetch { 15519625d8cSopenharmony_ci remote: "origin".to_string() 15619625d8cSopenharmony_ci }), 15719625d8cSopenharmony_ci Opt4::try_parse_from(["test", "fetch", "origin"]).unwrap() 15819625d8cSopenharmony_ci ); 15919625d8cSopenharmony_ci 16019625d8cSopenharmony_ci let output = utils::get_long_help::<Opt4>(); 16119625d8cSopenharmony_ci 16219625d8cSopenharmony_ci assert!(output.contains("download history from remote")); 16319625d8cSopenharmony_ci assert!(output.contains("Add a file")); 16419625d8cSopenharmony_ci assert!(!output.contains("Not shown")); 16519625d8cSopenharmony_ci} 16619625d8cSopenharmony_ci 16719625d8cSopenharmony_ci#[test] 16819625d8cSopenharmony_cifn global_passed_down() { 16919625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 17019625d8cSopenharmony_ci struct Opt { 17119625d8cSopenharmony_ci #[arg(global = true, long)] 17219625d8cSopenharmony_ci other: bool, 17319625d8cSopenharmony_ci #[command(subcommand)] 17419625d8cSopenharmony_ci sub: Subcommands, 17519625d8cSopenharmony_ci } 17619625d8cSopenharmony_ci 17719625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Subcommand)] 17819625d8cSopenharmony_ci enum Subcommands { 17919625d8cSopenharmony_ci Add, 18019625d8cSopenharmony_ci Global(GlobalCmd), 18119625d8cSopenharmony_ci } 18219625d8cSopenharmony_ci 18319625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Args)] 18419625d8cSopenharmony_ci struct GlobalCmd { 18519625d8cSopenharmony_ci #[arg(from_global)] 18619625d8cSopenharmony_ci other: bool, 18719625d8cSopenharmony_ci } 18819625d8cSopenharmony_ci 18919625d8cSopenharmony_ci assert_eq!( 19019625d8cSopenharmony_ci Opt::try_parse_from(["test", "global"]).unwrap(), 19119625d8cSopenharmony_ci Opt { 19219625d8cSopenharmony_ci other: false, 19319625d8cSopenharmony_ci sub: Subcommands::Global(GlobalCmd { other: false }) 19419625d8cSopenharmony_ci } 19519625d8cSopenharmony_ci ); 19619625d8cSopenharmony_ci 19719625d8cSopenharmony_ci assert_eq!( 19819625d8cSopenharmony_ci Opt::try_parse_from(["test", "global", "--other"]).unwrap(), 19919625d8cSopenharmony_ci Opt { 20019625d8cSopenharmony_ci other: true, 20119625d8cSopenharmony_ci sub: Subcommands::Global(GlobalCmd { other: true }) 20219625d8cSopenharmony_ci } 20319625d8cSopenharmony_ci ); 20419625d8cSopenharmony_ci} 20519625d8cSopenharmony_ci 20619625d8cSopenharmony_ci#[test] 20719625d8cSopenharmony_cifn external_subcommand() { 20819625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 20919625d8cSopenharmony_ci struct Opt { 21019625d8cSopenharmony_ci #[command(subcommand)] 21119625d8cSopenharmony_ci sub: Subcommands, 21219625d8cSopenharmony_ci } 21319625d8cSopenharmony_ci 21419625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Subcommand)] 21519625d8cSopenharmony_ci enum Subcommands { 21619625d8cSopenharmony_ci Add, 21719625d8cSopenharmony_ci Remove, 21819625d8cSopenharmony_ci #[command(external_subcommand)] 21919625d8cSopenharmony_ci Other(Vec<String>), 22019625d8cSopenharmony_ci } 22119625d8cSopenharmony_ci 22219625d8cSopenharmony_ci assert_eq!( 22319625d8cSopenharmony_ci Opt::try_parse_from(["test", "add"]).unwrap(), 22419625d8cSopenharmony_ci Opt { 22519625d8cSopenharmony_ci sub: Subcommands::Add 22619625d8cSopenharmony_ci } 22719625d8cSopenharmony_ci ); 22819625d8cSopenharmony_ci 22919625d8cSopenharmony_ci assert_eq!( 23019625d8cSopenharmony_ci Opt::try_parse_from(["test", "remove"]).unwrap(), 23119625d8cSopenharmony_ci Opt { 23219625d8cSopenharmony_ci sub: Subcommands::Remove 23319625d8cSopenharmony_ci } 23419625d8cSopenharmony_ci ); 23519625d8cSopenharmony_ci 23619625d8cSopenharmony_ci assert!(Opt::try_parse_from(["test"]).is_err()); 23719625d8cSopenharmony_ci 23819625d8cSopenharmony_ci assert_eq!( 23919625d8cSopenharmony_ci Opt::try_parse_from(["test", "git", "status"]).unwrap(), 24019625d8cSopenharmony_ci Opt { 24119625d8cSopenharmony_ci sub: Subcommands::Other(vec!["git".into(), "status".into()]) 24219625d8cSopenharmony_ci } 24319625d8cSopenharmony_ci ); 24419625d8cSopenharmony_ci} 24519625d8cSopenharmony_ci 24619625d8cSopenharmony_ci#[test] 24719625d8cSopenharmony_cifn external_subcommand_os_string() { 24819625d8cSopenharmony_ci use std::ffi::OsString; 24919625d8cSopenharmony_ci 25019625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 25119625d8cSopenharmony_ci struct Opt { 25219625d8cSopenharmony_ci #[command(subcommand)] 25319625d8cSopenharmony_ci sub: Subcommands, 25419625d8cSopenharmony_ci } 25519625d8cSopenharmony_ci 25619625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Subcommand)] 25719625d8cSopenharmony_ci enum Subcommands { 25819625d8cSopenharmony_ci #[command(external_subcommand)] 25919625d8cSopenharmony_ci Other(Vec<OsString>), 26019625d8cSopenharmony_ci } 26119625d8cSopenharmony_ci 26219625d8cSopenharmony_ci assert_eq!( 26319625d8cSopenharmony_ci Opt::try_parse_from(["test", "git", "status"]).unwrap(), 26419625d8cSopenharmony_ci Opt { 26519625d8cSopenharmony_ci sub: Subcommands::Other(vec!["git".into(), "status".into()]) 26619625d8cSopenharmony_ci } 26719625d8cSopenharmony_ci ); 26819625d8cSopenharmony_ci 26919625d8cSopenharmony_ci assert!(Opt::try_parse_from(["test"]).is_err()); 27019625d8cSopenharmony_ci} 27119625d8cSopenharmony_ci 27219625d8cSopenharmony_ci#[test] 27319625d8cSopenharmony_cifn external_subcommand_optional() { 27419625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 27519625d8cSopenharmony_ci struct Opt { 27619625d8cSopenharmony_ci #[command(subcommand)] 27719625d8cSopenharmony_ci sub: Option<Subcommands>, 27819625d8cSopenharmony_ci } 27919625d8cSopenharmony_ci 28019625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Subcommand)] 28119625d8cSopenharmony_ci enum Subcommands { 28219625d8cSopenharmony_ci #[command(external_subcommand)] 28319625d8cSopenharmony_ci Other(Vec<String>), 28419625d8cSopenharmony_ci } 28519625d8cSopenharmony_ci 28619625d8cSopenharmony_ci assert_eq!( 28719625d8cSopenharmony_ci Opt::try_parse_from(["test", "git", "status"]).unwrap(), 28819625d8cSopenharmony_ci Opt { 28919625d8cSopenharmony_ci sub: Some(Subcommands::Other(vec!["git".into(), "status".into()])) 29019625d8cSopenharmony_ci } 29119625d8cSopenharmony_ci ); 29219625d8cSopenharmony_ci 29319625d8cSopenharmony_ci assert_eq!(Opt::try_parse_from(["test"]).unwrap(), Opt { sub: None }); 29419625d8cSopenharmony_ci} 29519625d8cSopenharmony_ci 29619625d8cSopenharmony_ci#[test] 29719625d8cSopenharmony_cifn enum_in_enum_subsubcommand() { 29819625d8cSopenharmony_ci #[derive(Parser, Debug, PartialEq, Eq)] 29919625d8cSopenharmony_ci pub enum Opt { 30019625d8cSopenharmony_ci #[command(alias = "l")] 30119625d8cSopenharmony_ci List, 30219625d8cSopenharmony_ci #[command(subcommand, alias = "d")] 30319625d8cSopenharmony_ci Daemon(DaemonCommand), 30419625d8cSopenharmony_ci } 30519625d8cSopenharmony_ci 30619625d8cSopenharmony_ci #[derive(Subcommand, Debug, PartialEq, Eq)] 30719625d8cSopenharmony_ci pub enum DaemonCommand { 30819625d8cSopenharmony_ci Start, 30919625d8cSopenharmony_ci Stop, 31019625d8cSopenharmony_ci } 31119625d8cSopenharmony_ci 31219625d8cSopenharmony_ci let result = Opt::try_parse_from(["test"]); 31319625d8cSopenharmony_ci assert!(result.is_err()); 31419625d8cSopenharmony_ci 31519625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "list"]).unwrap(); 31619625d8cSopenharmony_ci assert_eq!(Opt::List, result); 31719625d8cSopenharmony_ci 31819625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "l"]).unwrap(); 31919625d8cSopenharmony_ci assert_eq!(Opt::List, result); 32019625d8cSopenharmony_ci 32119625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "daemon"]); 32219625d8cSopenharmony_ci assert!(result.is_err()); 32319625d8cSopenharmony_ci 32419625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "daemon", "start"]).unwrap(); 32519625d8cSopenharmony_ci assert_eq!(Opt::Daemon(DaemonCommand::Start), result); 32619625d8cSopenharmony_ci 32719625d8cSopenharmony_ci let result = Opt::try_parse_from(["test", "d", "start"]).unwrap(); 32819625d8cSopenharmony_ci assert_eq!(Opt::Daemon(DaemonCommand::Start), result); 32919625d8cSopenharmony_ci} 33019625d8cSopenharmony_ci 33119625d8cSopenharmony_ci#[test] 33219625d8cSopenharmony_cifn update_subcommands() { 33319625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 33419625d8cSopenharmony_ci enum Opt { 33519625d8cSopenharmony_ci Command1(Command1), 33619625d8cSopenharmony_ci Command2(Command2), 33719625d8cSopenharmony_ci } 33819625d8cSopenharmony_ci 33919625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 34019625d8cSopenharmony_ci struct Command1 { 34119625d8cSopenharmony_ci arg1: i32, 34219625d8cSopenharmony_ci 34319625d8cSopenharmony_ci arg2: i32, 34419625d8cSopenharmony_ci } 34519625d8cSopenharmony_ci 34619625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 34719625d8cSopenharmony_ci struct Command2 { 34819625d8cSopenharmony_ci arg2: i32, 34919625d8cSopenharmony_ci } 35019625d8cSopenharmony_ci 35119625d8cSopenharmony_ci // Full subcommand update 35219625d8cSopenharmony_ci let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 }); 35319625d8cSopenharmony_ci opt.try_update_from(["test", "command1", "42", "44"]) 35419625d8cSopenharmony_ci .unwrap(); 35519625d8cSopenharmony_ci assert_eq!( 35619625d8cSopenharmony_ci Opt::try_parse_from(["test", "command1", "42", "44"]).unwrap(), 35719625d8cSopenharmony_ci opt 35819625d8cSopenharmony_ci ); 35919625d8cSopenharmony_ci 36019625d8cSopenharmony_ci // Partial subcommand update 36119625d8cSopenharmony_ci let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 }); 36219625d8cSopenharmony_ci opt.try_update_from(["test", "command1", "42"]).unwrap(); 36319625d8cSopenharmony_ci assert_eq!( 36419625d8cSopenharmony_ci Opt::try_parse_from(["test", "command1", "42", "14"]).unwrap(), 36519625d8cSopenharmony_ci opt 36619625d8cSopenharmony_ci ); 36719625d8cSopenharmony_ci 36819625d8cSopenharmony_ci // Change subcommand 36919625d8cSopenharmony_ci let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 }); 37019625d8cSopenharmony_ci opt.try_update_from(["test", "command2", "43"]).unwrap(); 37119625d8cSopenharmony_ci assert_eq!( 37219625d8cSopenharmony_ci Opt::try_parse_from(["test", "command2", "43"]).unwrap(), 37319625d8cSopenharmony_ci opt 37419625d8cSopenharmony_ci ); 37519625d8cSopenharmony_ci} 37619625d8cSopenharmony_ci 37719625d8cSopenharmony_ci#[test] 37819625d8cSopenharmony_cifn update_subcommands_explicit_required() { 37919625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 38019625d8cSopenharmony_ci #[command(subcommand_required = true)] 38119625d8cSopenharmony_ci enum Opt { 38219625d8cSopenharmony_ci Command1(Command1), 38319625d8cSopenharmony_ci Command2(Command2), 38419625d8cSopenharmony_ci } 38519625d8cSopenharmony_ci 38619625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 38719625d8cSopenharmony_ci struct Command1 { 38819625d8cSopenharmony_ci arg1: i32, 38919625d8cSopenharmony_ci 39019625d8cSopenharmony_ci arg2: i32, 39119625d8cSopenharmony_ci } 39219625d8cSopenharmony_ci 39319625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 39419625d8cSopenharmony_ci struct Command2 { 39519625d8cSopenharmony_ci arg2: i32, 39619625d8cSopenharmony_ci } 39719625d8cSopenharmony_ci 39819625d8cSopenharmony_ci // Full subcommand update 39919625d8cSopenharmony_ci let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 }); 40019625d8cSopenharmony_ci opt.try_update_from(["test"]).unwrap(); 40119625d8cSopenharmony_ci assert_eq!(Opt::Command1(Command1 { arg1: 12, arg2: 14 }), opt); 40219625d8cSopenharmony_ci} 40319625d8cSopenharmony_ci 40419625d8cSopenharmony_ci#[test] 40519625d8cSopenharmony_cifn update_sub_subcommands() { 40619625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 40719625d8cSopenharmony_ci enum Opt { 40819625d8cSopenharmony_ci #[command(subcommand)] 40919625d8cSopenharmony_ci Child1(Child1), 41019625d8cSopenharmony_ci #[command(subcommand)] 41119625d8cSopenharmony_ci Child2(Child2), 41219625d8cSopenharmony_ci } 41319625d8cSopenharmony_ci 41419625d8cSopenharmony_ci #[derive(Subcommand, PartialEq, Eq, Debug)] 41519625d8cSopenharmony_ci enum Child1 { 41619625d8cSopenharmony_ci Command1(Command1), 41719625d8cSopenharmony_ci Command2(Command2), 41819625d8cSopenharmony_ci } 41919625d8cSopenharmony_ci 42019625d8cSopenharmony_ci #[derive(Subcommand, PartialEq, Eq, Debug)] 42119625d8cSopenharmony_ci enum Child2 { 42219625d8cSopenharmony_ci Command1(Command1), 42319625d8cSopenharmony_ci Command2(Command2), 42419625d8cSopenharmony_ci } 42519625d8cSopenharmony_ci 42619625d8cSopenharmony_ci #[derive(Args, PartialEq, Eq, Debug)] 42719625d8cSopenharmony_ci struct Command1 { 42819625d8cSopenharmony_ci arg1: i32, 42919625d8cSopenharmony_ci 43019625d8cSopenharmony_ci arg2: i32, 43119625d8cSopenharmony_ci } 43219625d8cSopenharmony_ci 43319625d8cSopenharmony_ci #[derive(Args, PartialEq, Eq, Debug)] 43419625d8cSopenharmony_ci struct Command2 { 43519625d8cSopenharmony_ci arg2: i32, 43619625d8cSopenharmony_ci } 43719625d8cSopenharmony_ci 43819625d8cSopenharmony_ci // Full subcommand update 43919625d8cSopenharmony_ci let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); 44019625d8cSopenharmony_ci opt.try_update_from(["test", "child1", "command1", "42", "44"]) 44119625d8cSopenharmony_ci .unwrap(); 44219625d8cSopenharmony_ci assert_eq!( 44319625d8cSopenharmony_ci Opt::try_parse_from(["test", "child1", "command1", "42", "44"]).unwrap(), 44419625d8cSopenharmony_ci opt 44519625d8cSopenharmony_ci ); 44619625d8cSopenharmony_ci 44719625d8cSopenharmony_ci // Partial subcommand update 44819625d8cSopenharmony_ci let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); 44919625d8cSopenharmony_ci opt.try_update_from(["test", "child1", "command1", "42"]) 45019625d8cSopenharmony_ci .unwrap(); 45119625d8cSopenharmony_ci assert_eq!( 45219625d8cSopenharmony_ci Opt::try_parse_from(["test", "child1", "command1", "42", "14"]).unwrap(), 45319625d8cSopenharmony_ci opt 45419625d8cSopenharmony_ci ); 45519625d8cSopenharmony_ci 45619625d8cSopenharmony_ci // Partial subcommand update 45719625d8cSopenharmony_ci let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); 45819625d8cSopenharmony_ci opt.try_update_from(["test", "child1", "command2", "43"]) 45919625d8cSopenharmony_ci .unwrap(); 46019625d8cSopenharmony_ci assert_eq!( 46119625d8cSopenharmony_ci Opt::try_parse_from(["test", "child1", "command2", "43"]).unwrap(), 46219625d8cSopenharmony_ci opt 46319625d8cSopenharmony_ci ); 46419625d8cSopenharmony_ci 46519625d8cSopenharmony_ci // Change subcommand 46619625d8cSopenharmony_ci let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); 46719625d8cSopenharmony_ci opt.try_update_from(["test", "child2", "command2", "43"]) 46819625d8cSopenharmony_ci .unwrap(); 46919625d8cSopenharmony_ci assert_eq!( 47019625d8cSopenharmony_ci Opt::try_parse_from(["test", "child2", "command2", "43"]).unwrap(), 47119625d8cSopenharmony_ci opt 47219625d8cSopenharmony_ci ); 47319625d8cSopenharmony_ci} 47419625d8cSopenharmony_ci 47519625d8cSopenharmony_ci#[test] 47619625d8cSopenharmony_cifn update_ext_subcommand() { 47719625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 47819625d8cSopenharmony_ci enum Opt { 47919625d8cSopenharmony_ci Command1(Command1), 48019625d8cSopenharmony_ci Command2(Command2), 48119625d8cSopenharmony_ci #[command(external_subcommand)] 48219625d8cSopenharmony_ci Ext(Vec<String>), 48319625d8cSopenharmony_ci } 48419625d8cSopenharmony_ci 48519625d8cSopenharmony_ci #[derive(Args, PartialEq, Eq, Debug)] 48619625d8cSopenharmony_ci struct Command1 { 48719625d8cSopenharmony_ci arg1: i32, 48819625d8cSopenharmony_ci 48919625d8cSopenharmony_ci arg2: i32, 49019625d8cSopenharmony_ci } 49119625d8cSopenharmony_ci 49219625d8cSopenharmony_ci #[derive(Args, PartialEq, Eq, Debug)] 49319625d8cSopenharmony_ci struct Command2 { 49419625d8cSopenharmony_ci arg2: i32, 49519625d8cSopenharmony_ci } 49619625d8cSopenharmony_ci 49719625d8cSopenharmony_ci // Full subcommand update 49819625d8cSopenharmony_ci let mut opt = Opt::Ext(vec!["12".into(), "14".into()]); 49919625d8cSopenharmony_ci opt.try_update_from(["test", "ext", "42", "44"]).unwrap(); 50019625d8cSopenharmony_ci assert_eq!( 50119625d8cSopenharmony_ci Opt::try_parse_from(["test", "ext", "42", "44"]).unwrap(), 50219625d8cSopenharmony_ci opt 50319625d8cSopenharmony_ci ); 50419625d8cSopenharmony_ci 50519625d8cSopenharmony_ci // No partial subcommand update 50619625d8cSopenharmony_ci let mut opt = Opt::Ext(vec!["12".into(), "14".into()]); 50719625d8cSopenharmony_ci opt.try_update_from(["test", "ext", "42"]).unwrap(); 50819625d8cSopenharmony_ci assert_eq!(Opt::try_parse_from(["test", "ext", "42"]).unwrap(), opt); 50919625d8cSopenharmony_ci 51019625d8cSopenharmony_ci // Change subcommand 51119625d8cSopenharmony_ci let mut opt = Opt::Ext(vec!["12".into(), "14".into()]); 51219625d8cSopenharmony_ci opt.try_update_from(["test", "command2", "43"]).unwrap(); 51319625d8cSopenharmony_ci assert_eq!( 51419625d8cSopenharmony_ci Opt::try_parse_from(["test", "command2", "43"]).unwrap(), 51519625d8cSopenharmony_ci opt 51619625d8cSopenharmony_ci ); 51719625d8cSopenharmony_ci 51819625d8cSopenharmony_ci let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 }); 51919625d8cSopenharmony_ci opt.try_update_from(["test", "ext", "42", "44"]).unwrap(); 52019625d8cSopenharmony_ci assert_eq!( 52119625d8cSopenharmony_ci Opt::try_parse_from(["test", "ext", "42", "44"]).unwrap(), 52219625d8cSopenharmony_ci opt 52319625d8cSopenharmony_ci ); 52419625d8cSopenharmony_ci} 52519625d8cSopenharmony_ci#[test] 52619625d8cSopenharmony_cifn subcommand_name_not_literal() { 52719625d8cSopenharmony_ci fn get_name() -> &'static str { 52819625d8cSopenharmony_ci "renamed" 52919625d8cSopenharmony_ci } 53019625d8cSopenharmony_ci 53119625d8cSopenharmony_ci #[derive(Parser, PartialEq, Eq, Debug)] 53219625d8cSopenharmony_ci struct Opt { 53319625d8cSopenharmony_ci #[command(subcommand)] 53419625d8cSopenharmony_ci subcmd: SubCmd, 53519625d8cSopenharmony_ci } 53619625d8cSopenharmony_ci 53719625d8cSopenharmony_ci #[derive(Subcommand, PartialEq, Eq, Debug)] 53819625d8cSopenharmony_ci enum SubCmd { 53919625d8cSopenharmony_ci #[command(name = get_name())] 54019625d8cSopenharmony_ci SubCmd1, 54119625d8cSopenharmony_ci } 54219625d8cSopenharmony_ci 54319625d8cSopenharmony_ci assert!(Opt::try_parse_from(["test", "renamed"]).is_ok()); 54419625d8cSopenharmony_ci} 54519625d8cSopenharmony_ci 54619625d8cSopenharmony_ci#[test] 54719625d8cSopenharmony_cifn skip_subcommand() { 54819625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 54919625d8cSopenharmony_ci struct Opt { 55019625d8cSopenharmony_ci #[command(subcommand)] 55119625d8cSopenharmony_ci sub: Subcommands, 55219625d8cSopenharmony_ci } 55319625d8cSopenharmony_ci 55419625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Subcommand)] 55519625d8cSopenharmony_ci enum Subcommands { 55619625d8cSopenharmony_ci Add, 55719625d8cSopenharmony_ci Remove, 55819625d8cSopenharmony_ci 55919625d8cSopenharmony_ci #[allow(dead_code)] 56019625d8cSopenharmony_ci #[command(skip)] 56119625d8cSopenharmony_ci Skip, 56219625d8cSopenharmony_ci 56319625d8cSopenharmony_ci #[allow(dead_code)] 56419625d8cSopenharmony_ci #[command(skip)] 56519625d8cSopenharmony_ci Other(Other), 56619625d8cSopenharmony_ci } 56719625d8cSopenharmony_ci 56819625d8cSopenharmony_ci #[allow(dead_code)] 56919625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq)] 57019625d8cSopenharmony_ci enum Other { 57119625d8cSopenharmony_ci One, 57219625d8cSopenharmony_ci Twp, 57319625d8cSopenharmony_ci } 57419625d8cSopenharmony_ci 57519625d8cSopenharmony_ci assert!(Subcommands::has_subcommand("add")); 57619625d8cSopenharmony_ci assert!(Subcommands::has_subcommand("remove")); 57719625d8cSopenharmony_ci assert!(!Subcommands::has_subcommand("skip")); 57819625d8cSopenharmony_ci assert!(!Subcommands::has_subcommand("other")); 57919625d8cSopenharmony_ci 58019625d8cSopenharmony_ci assert_eq!( 58119625d8cSopenharmony_ci Opt::try_parse_from(["test", "add"]).unwrap(), 58219625d8cSopenharmony_ci Opt { 58319625d8cSopenharmony_ci sub: Subcommands::Add 58419625d8cSopenharmony_ci } 58519625d8cSopenharmony_ci ); 58619625d8cSopenharmony_ci 58719625d8cSopenharmony_ci assert_eq!( 58819625d8cSopenharmony_ci Opt::try_parse_from(["test", "remove"]).unwrap(), 58919625d8cSopenharmony_ci Opt { 59019625d8cSopenharmony_ci sub: Subcommands::Remove 59119625d8cSopenharmony_ci } 59219625d8cSopenharmony_ci ); 59319625d8cSopenharmony_ci 59419625d8cSopenharmony_ci let res = Opt::try_parse_from(["test", "skip"]); 59519625d8cSopenharmony_ci assert_eq!( 59619625d8cSopenharmony_ci res.unwrap_err().kind(), 59719625d8cSopenharmony_ci clap::error::ErrorKind::InvalidSubcommand, 59819625d8cSopenharmony_ci ); 59919625d8cSopenharmony_ci 60019625d8cSopenharmony_ci let res = Opt::try_parse_from(["test", "other"]); 60119625d8cSopenharmony_ci assert_eq!( 60219625d8cSopenharmony_ci res.unwrap_err().kind(), 60319625d8cSopenharmony_ci clap::error::ErrorKind::InvalidSubcommand, 60419625d8cSopenharmony_ci ); 60519625d8cSopenharmony_ci} 60619625d8cSopenharmony_ci 60719625d8cSopenharmony_ci#[test] 60819625d8cSopenharmony_cifn built_in_subcommand_escaped() { 60919625d8cSopenharmony_ci #[derive(Debug, PartialEq, Eq, Parser)] 61019625d8cSopenharmony_ci enum Command { 61119625d8cSopenharmony_ci Install { 61219625d8cSopenharmony_ci arg: Option<String>, 61319625d8cSopenharmony_ci }, 61419625d8cSopenharmony_ci #[command(external_subcommand)] 61519625d8cSopenharmony_ci Custom(Vec<String>), 61619625d8cSopenharmony_ci } 61719625d8cSopenharmony_ci 61819625d8cSopenharmony_ci assert_eq!( 61919625d8cSopenharmony_ci Command::try_parse_from(["test", "install", "arg"]).unwrap(), 62019625d8cSopenharmony_ci Command::Install { 62119625d8cSopenharmony_ci arg: Some(String::from("arg")) 62219625d8cSopenharmony_ci } 62319625d8cSopenharmony_ci ); 62419625d8cSopenharmony_ci assert_eq!( 62519625d8cSopenharmony_ci Command::try_parse_from(["test", "--", "install"]).unwrap(), 62619625d8cSopenharmony_ci Command::Custom(vec![String::from("install")]) 62719625d8cSopenharmony_ci ); 62819625d8cSopenharmony_ci assert_eq!( 62919625d8cSopenharmony_ci Command::try_parse_from(["test", "--", "install", "arg"]).unwrap(), 63019625d8cSopenharmony_ci Command::Custom(vec![String::from("install"), String::from("arg")]) 63119625d8cSopenharmony_ci ); 63219625d8cSopenharmony_ci} 633