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#[test] 2019625d8cSopenharmony_cifn flatten() { 2119625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 2219625d8cSopenharmony_ci struct Common { 2319625d8cSopenharmony_ci arg: i32, 2419625d8cSopenharmony_ci } 2519625d8cSopenharmony_ci 2619625d8cSopenharmony_ci #[derive(Parser, PartialEq, Debug)] 2719625d8cSopenharmony_ci struct Opt { 2819625d8cSopenharmony_ci #[command(flatten)] 2919625d8cSopenharmony_ci common: Common, 3019625d8cSopenharmony_ci } 3119625d8cSopenharmony_ci assert_eq!( 3219625d8cSopenharmony_ci Opt { 3319625d8cSopenharmony_ci common: Common { arg: 42 } 3419625d8cSopenharmony_ci }, 3519625d8cSopenharmony_ci Opt::try_parse_from(["test", "42"]).unwrap() 3619625d8cSopenharmony_ci ); 3719625d8cSopenharmony_ci assert!(Opt::try_parse_from(["test"]).is_err()); 3819625d8cSopenharmony_ci assert!(Opt::try_parse_from(["test", "42", "24"]).is_err()); 3919625d8cSopenharmony_ci} 4019625d8cSopenharmony_ci 4119625d8cSopenharmony_ci#[cfg(debug_assertions)] 4219625d8cSopenharmony_ci#[test] 4319625d8cSopenharmony_ci#[should_panic] 4419625d8cSopenharmony_cifn flatten_twice() { 4519625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 4619625d8cSopenharmony_ci struct Common { 4719625d8cSopenharmony_ci arg: i32, 4819625d8cSopenharmony_ci } 4919625d8cSopenharmony_ci 5019625d8cSopenharmony_ci #[derive(Parser, PartialEq, Debug)] 5119625d8cSopenharmony_ci struct Opt { 5219625d8cSopenharmony_ci #[command(flatten)] 5319625d8cSopenharmony_ci c1: Common, 5419625d8cSopenharmony_ci // Defines "arg" twice, so this should not work. 5519625d8cSopenharmony_ci #[command(flatten)] 5619625d8cSopenharmony_ci c2: Common, 5719625d8cSopenharmony_ci } 5819625d8cSopenharmony_ci Opt::try_parse_from(["test", "42", "43"]).unwrap(); 5919625d8cSopenharmony_ci} 6019625d8cSopenharmony_ci 6119625d8cSopenharmony_ci#[test] 6219625d8cSopenharmony_cifn flatten_in_subcommand() { 6319625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 6419625d8cSopenharmony_ci struct Common { 6519625d8cSopenharmony_ci arg: i32, 6619625d8cSopenharmony_ci } 6719625d8cSopenharmony_ci 6819625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 6919625d8cSopenharmony_ci struct Add { 7019625d8cSopenharmony_ci #[arg(short)] 7119625d8cSopenharmony_ci interactive: bool, 7219625d8cSopenharmony_ci #[command(flatten)] 7319625d8cSopenharmony_ci common: Common, 7419625d8cSopenharmony_ci } 7519625d8cSopenharmony_ci 7619625d8cSopenharmony_ci #[derive(Parser, PartialEq, Debug)] 7719625d8cSopenharmony_ci enum Opt { 7819625d8cSopenharmony_ci Fetch { 7919625d8cSopenharmony_ci #[arg(short)] 8019625d8cSopenharmony_ci all: bool, 8119625d8cSopenharmony_ci #[command(flatten)] 8219625d8cSopenharmony_ci common: Common, 8319625d8cSopenharmony_ci }, 8419625d8cSopenharmony_ci 8519625d8cSopenharmony_ci Add(Add), 8619625d8cSopenharmony_ci } 8719625d8cSopenharmony_ci 8819625d8cSopenharmony_ci assert_eq!( 8919625d8cSopenharmony_ci Opt::Fetch { 9019625d8cSopenharmony_ci all: false, 9119625d8cSopenharmony_ci common: Common { arg: 42 } 9219625d8cSopenharmony_ci }, 9319625d8cSopenharmony_ci Opt::try_parse_from(["test", "fetch", "42"]).unwrap() 9419625d8cSopenharmony_ci ); 9519625d8cSopenharmony_ci assert_eq!( 9619625d8cSopenharmony_ci Opt::Add(Add { 9719625d8cSopenharmony_ci interactive: true, 9819625d8cSopenharmony_ci common: Common { arg: 43 } 9919625d8cSopenharmony_ci }), 10019625d8cSopenharmony_ci Opt::try_parse_from(["test", "add", "-i", "43"]).unwrap() 10119625d8cSopenharmony_ci ); 10219625d8cSopenharmony_ci} 10319625d8cSopenharmony_ci 10419625d8cSopenharmony_ci#[test] 10519625d8cSopenharmony_cifn update_args_with_flatten() { 10619625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 10719625d8cSopenharmony_ci struct Common { 10819625d8cSopenharmony_ci arg: i32, 10919625d8cSopenharmony_ci } 11019625d8cSopenharmony_ci 11119625d8cSopenharmony_ci #[derive(Parser, PartialEq, Debug)] 11219625d8cSopenharmony_ci struct Opt { 11319625d8cSopenharmony_ci #[command(flatten)] 11419625d8cSopenharmony_ci common: Common, 11519625d8cSopenharmony_ci } 11619625d8cSopenharmony_ci 11719625d8cSopenharmony_ci let mut opt = Opt { 11819625d8cSopenharmony_ci common: Common { arg: 42 }, 11919625d8cSopenharmony_ci }; 12019625d8cSopenharmony_ci opt.try_update_from(["test"]).unwrap(); 12119625d8cSopenharmony_ci assert_eq!(Opt::try_parse_from(["test", "42"]).unwrap(), opt); 12219625d8cSopenharmony_ci 12319625d8cSopenharmony_ci let mut opt = Opt { 12419625d8cSopenharmony_ci common: Common { arg: 42 }, 12519625d8cSopenharmony_ci }; 12619625d8cSopenharmony_ci opt.try_update_from(["test", "52"]).unwrap(); 12719625d8cSopenharmony_ci assert_eq!(Opt::try_parse_from(["test", "52"]).unwrap(), opt); 12819625d8cSopenharmony_ci} 12919625d8cSopenharmony_ci 13019625d8cSopenharmony_ci#[derive(Subcommand, PartialEq, Debug)] 13119625d8cSopenharmony_cienum BaseCli { 13219625d8cSopenharmony_ci Command1(Command1), 13319625d8cSopenharmony_ci} 13419625d8cSopenharmony_ci 13519625d8cSopenharmony_ci#[derive(Args, PartialEq, Debug)] 13619625d8cSopenharmony_cistruct Command1 { 13719625d8cSopenharmony_ci arg1: i32, 13819625d8cSopenharmony_ci 13919625d8cSopenharmony_ci arg2: i32, 14019625d8cSopenharmony_ci} 14119625d8cSopenharmony_ci 14219625d8cSopenharmony_ci#[derive(Args, PartialEq, Debug)] 14319625d8cSopenharmony_cistruct Command2 { 14419625d8cSopenharmony_ci arg2: i32, 14519625d8cSopenharmony_ci} 14619625d8cSopenharmony_ci 14719625d8cSopenharmony_ci#[derive(Parser, PartialEq, Debug)] 14819625d8cSopenharmony_cienum Opt { 14919625d8cSopenharmony_ci #[command(flatten)] 15019625d8cSopenharmony_ci BaseCli(BaseCli), 15119625d8cSopenharmony_ci Command2(Command2), 15219625d8cSopenharmony_ci} 15319625d8cSopenharmony_ci 15419625d8cSopenharmony_ci#[test] 15519625d8cSopenharmony_cifn merge_subcommands_with_flatten() { 15619625d8cSopenharmony_ci assert_eq!( 15719625d8cSopenharmony_ci Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 42, arg2: 44 })), 15819625d8cSopenharmony_ci Opt::try_parse_from(["test", "command1", "42", "44"]).unwrap() 15919625d8cSopenharmony_ci ); 16019625d8cSopenharmony_ci assert_eq!( 16119625d8cSopenharmony_ci Opt::Command2(Command2 { arg2: 43 }), 16219625d8cSopenharmony_ci Opt::try_parse_from(["test", "command2", "43"]).unwrap() 16319625d8cSopenharmony_ci ); 16419625d8cSopenharmony_ci} 16519625d8cSopenharmony_ci 16619625d8cSopenharmony_ci#[test] 16719625d8cSopenharmony_cifn update_subcommands_with_flatten() { 16819625d8cSopenharmony_ci let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 })); 16919625d8cSopenharmony_ci opt.try_update_from(["test", "command1", "42", "44"]) 17019625d8cSopenharmony_ci .unwrap(); 17119625d8cSopenharmony_ci assert_eq!( 17219625d8cSopenharmony_ci Opt::try_parse_from(["test", "command1", "42", "44"]).unwrap(), 17319625d8cSopenharmony_ci opt 17419625d8cSopenharmony_ci ); 17519625d8cSopenharmony_ci 17619625d8cSopenharmony_ci let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 })); 17719625d8cSopenharmony_ci opt.try_update_from(["test", "command1", "42"]).unwrap(); 17819625d8cSopenharmony_ci assert_eq!( 17919625d8cSopenharmony_ci Opt::try_parse_from(["test", "command1", "42", "14"]).unwrap(), 18019625d8cSopenharmony_ci opt 18119625d8cSopenharmony_ci ); 18219625d8cSopenharmony_ci 18319625d8cSopenharmony_ci let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 })); 18419625d8cSopenharmony_ci opt.try_update_from(["test", "command2", "43"]).unwrap(); 18519625d8cSopenharmony_ci assert_eq!( 18619625d8cSopenharmony_ci Opt::try_parse_from(["test", "command2", "43"]).unwrap(), 18719625d8cSopenharmony_ci opt 18819625d8cSopenharmony_ci ); 18919625d8cSopenharmony_ci} 19019625d8cSopenharmony_ci 19119625d8cSopenharmony_ci#[test] 19219625d8cSopenharmony_cifn flatten_with_doc_comment() { 19319625d8cSopenharmony_ci #[derive(Args, PartialEq, Debug)] 19419625d8cSopenharmony_ci struct Common { 19519625d8cSopenharmony_ci /// This is an arg. Arg means "argument". Command line argument. 19619625d8cSopenharmony_ci arg: i32, 19719625d8cSopenharmony_ci } 19819625d8cSopenharmony_ci 19919625d8cSopenharmony_ci #[derive(Parser, PartialEq, Debug)] 20019625d8cSopenharmony_ci struct Opt { 20119625d8cSopenharmony_ci /// The very important comment that clippy had me put here. 20219625d8cSopenharmony_ci /// It knows better. 20319625d8cSopenharmony_ci #[command(flatten)] 20419625d8cSopenharmony_ci common: Common, 20519625d8cSopenharmony_ci } 20619625d8cSopenharmony_ci assert_eq!( 20719625d8cSopenharmony_ci Opt { 20819625d8cSopenharmony_ci common: Common { arg: 42 } 20919625d8cSopenharmony_ci }, 21019625d8cSopenharmony_ci Opt::try_parse_from(["test", "42"]).unwrap() 21119625d8cSopenharmony_ci ); 21219625d8cSopenharmony_ci 21319625d8cSopenharmony_ci let help = utils::get_help::<Opt>(); 21419625d8cSopenharmony_ci assert!(help.contains("This is an arg.")); 21519625d8cSopenharmony_ci assert!(!help.contains("The very important")); 21619625d8cSopenharmony_ci} 21719625d8cSopenharmony_ci 21819625d8cSopenharmony_ci#[test] 21919625d8cSopenharmony_cifn docstrings_ordering_with_multiple_command() { 22019625d8cSopenharmony_ci /// This is the docstring for Flattened 22119625d8cSopenharmony_ci #[derive(Args)] 22219625d8cSopenharmony_ci struct Flattened { 22319625d8cSopenharmony_ci #[arg(long)] 22419625d8cSopenharmony_ci foo: bool, 22519625d8cSopenharmony_ci } 22619625d8cSopenharmony_ci 22719625d8cSopenharmony_ci /// This is the docstring for Command 22819625d8cSopenharmony_ci #[derive(Parser)] 22919625d8cSopenharmony_ci struct Command { 23019625d8cSopenharmony_ci #[command(flatten)] 23119625d8cSopenharmony_ci flattened: Flattened, 23219625d8cSopenharmony_ci } 23319625d8cSopenharmony_ci 23419625d8cSopenharmony_ci let short_help = utils::get_help::<Command>(); 23519625d8cSopenharmony_ci 23619625d8cSopenharmony_ci assert!(short_help.contains("This is the docstring for Command")); 23719625d8cSopenharmony_ci} 23819625d8cSopenharmony_ci 23919625d8cSopenharmony_ci#[test] 24019625d8cSopenharmony_cifn docstrings_ordering_with_multiple_clap_partial() { 24119625d8cSopenharmony_ci /// This is the docstring for Flattened 24219625d8cSopenharmony_ci #[derive(Args)] 24319625d8cSopenharmony_ci struct Flattened { 24419625d8cSopenharmony_ci #[arg(long)] 24519625d8cSopenharmony_ci foo: bool, 24619625d8cSopenharmony_ci } 24719625d8cSopenharmony_ci 24819625d8cSopenharmony_ci #[derive(Parser)] 24919625d8cSopenharmony_ci struct Command { 25019625d8cSopenharmony_ci #[command(flatten)] 25119625d8cSopenharmony_ci flattened: Flattened, 25219625d8cSopenharmony_ci } 25319625d8cSopenharmony_ci 25419625d8cSopenharmony_ci let short_help = utils::get_help::<Command>(); 25519625d8cSopenharmony_ci 25619625d8cSopenharmony_ci assert!(short_help.contains("This is the docstring for Flattened")); 25719625d8cSopenharmony_ci} 25819625d8cSopenharmony_ci 25919625d8cSopenharmony_ci#[test] 26019625d8cSopenharmony_cifn optional_flatten() { 26119625d8cSopenharmony_ci #[derive(Parser, Debug, PartialEq, Eq)] 26219625d8cSopenharmony_ci struct Opt { 26319625d8cSopenharmony_ci #[command(flatten)] 26419625d8cSopenharmony_ci source: Option<Source>, 26519625d8cSopenharmony_ci } 26619625d8cSopenharmony_ci 26719625d8cSopenharmony_ci #[derive(clap::Args, Debug, PartialEq, Eq)] 26819625d8cSopenharmony_ci struct Source { 26919625d8cSopenharmony_ci crates: Vec<String>, 27019625d8cSopenharmony_ci #[arg(long)] 27119625d8cSopenharmony_ci path: Option<std::path::PathBuf>, 27219625d8cSopenharmony_ci #[arg(long)] 27319625d8cSopenharmony_ci git: Option<String>, 27419625d8cSopenharmony_ci } 27519625d8cSopenharmony_ci 27619625d8cSopenharmony_ci assert_eq!(Opt { source: None }, Opt::try_parse_from(["test"]).unwrap()); 27719625d8cSopenharmony_ci assert_eq!( 27819625d8cSopenharmony_ci Opt { 27919625d8cSopenharmony_ci source: Some(Source { 28019625d8cSopenharmony_ci crates: vec!["serde".to_owned()], 28119625d8cSopenharmony_ci path: None, 28219625d8cSopenharmony_ci git: None, 28319625d8cSopenharmony_ci }), 28419625d8cSopenharmony_ci }, 28519625d8cSopenharmony_ci Opt::try_parse_from(["test", "serde"]).unwrap() 28619625d8cSopenharmony_ci ); 28719625d8cSopenharmony_ci assert_eq!( 28819625d8cSopenharmony_ci Opt { 28919625d8cSopenharmony_ci source: Some(Source { 29019625d8cSopenharmony_ci crates: Vec::new(), 29119625d8cSopenharmony_ci path: Some("./".into()), 29219625d8cSopenharmony_ci git: None, 29319625d8cSopenharmony_ci }), 29419625d8cSopenharmony_ci }, 29519625d8cSopenharmony_ci Opt::try_parse_from(["test", "--path=./"]).unwrap() 29619625d8cSopenharmony_ci ); 29719625d8cSopenharmony_ci} 298