1// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, 2// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and 3// Ana Hobden (@hoverbear) <operator@hoverbear.org> 4// 5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8// option. This file may not be copied, modified, or distributed 9// except according to those terms. 10// 11// This work was derived from Structopt (https://github.com/TeXitoi/structopt) 12// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the 13// MIT/Apache 2.0 license. 14 15use clap::Parser; 16 17use std::num::ParseIntError; 18use std::path::PathBuf; 19 20#[derive(Parser, PartialEq, Debug)] 21struct PathOpt { 22 #[arg(short, long)] 23 path: PathBuf, 24 25 #[arg(short, default_value = "../")] 26 default_path: PathBuf, 27 28 #[arg(short)] 29 vector_path: Vec<PathBuf>, 30 31 #[arg(short)] 32 option_path_1: Option<PathBuf>, 33 34 #[arg(short = 'q')] 35 option_path_2: Option<PathBuf>, 36} 37 38#[test] 39fn test_path_opt_simple() { 40 assert_eq!( 41 PathOpt { 42 path: PathBuf::from("/usr/bin"), 43 default_path: PathBuf::from("../"), 44 vector_path: vec![ 45 PathBuf::from("/a/b/c"), 46 PathBuf::from("/d/e/f"), 47 PathBuf::from("/g/h/i"), 48 ], 49 option_path_1: None, 50 option_path_2: Some(PathBuf::from("j.zip")), 51 }, 52 PathOpt::try_parse_from([ 53 "test", "-p", "/usr/bin", "-v", "/a/b/c", "-v", "/d/e/f", "-v", "/g/h/i", "-q", 54 "j.zip", 55 ]) 56 .unwrap() 57 ); 58} 59 60fn parse_hex(input: &str) -> Result<u64, ParseIntError> { 61 u64::from_str_radix(input, 16) 62} 63 64#[derive(Parser, PartialEq, Debug)] 65struct HexOpt { 66 #[arg(short, value_parser = parse_hex)] 67 number: u64, 68} 69 70#[test] 71#[cfg(feature = "error-context")] 72fn test_parse_hex() { 73 assert_eq!( 74 HexOpt { number: 5 }, 75 HexOpt::try_parse_from(["test", "-n", "5"]).unwrap() 76 ); 77 assert_eq!( 78 HexOpt { 79 number: 0x00ab_cdef 80 }, 81 HexOpt::try_parse_from(["test", "-n", "abcdef"]).unwrap() 82 ); 83 84 let err = HexOpt::try_parse_from(["test", "-n", "gg"]).unwrap_err(); 85 assert!( 86 err.to_string().contains("invalid digit found in string"), 87 "{}", 88 err 89 ); 90} 91 92#[derive(Debug)] 93struct ErrCode(u32); 94impl std::error::Error for ErrCode {} 95impl std::fmt::Display for ErrCode { 96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 97 std::fmt::Display::fmt(&self.0, f) 98 } 99} 100fn custom_parser_2(_: &str) -> Result<&'static str, ErrCode> { 101 Ok("B") 102} 103 104#[derive(Parser, PartialEq, Debug)] 105struct NoOpOpt { 106 #[arg(short, value_parser = custom_parser_2)] 107 b: &'static str, 108} 109 110#[test] 111fn test_every_custom_parser() { 112 assert_eq!( 113 NoOpOpt { b: "B" }, 114 NoOpOpt::try_parse_from(["test", "-b=?"]).unwrap() 115 ); 116} 117 118#[test] 119fn update_every_custom_parser() { 120 let mut opt = NoOpOpt { b: "0" }; 121 122 opt.try_update_from(["test", "-b=?"]).unwrap(); 123 124 assert_eq!(NoOpOpt { b: "B" }, opt); 125} 126 127#[derive(Parser, PartialEq, Debug)] 128struct DefaultedOpt { 129 #[arg(short)] 130 integer: u64, 131 132 #[arg(short)] 133 path: PathBuf, 134} 135 136#[test] 137fn test_parser_with_default_value() { 138 assert_eq!( 139 DefaultedOpt { 140 integer: 9000, 141 path: PathBuf::from("src/lib.rs"), 142 }, 143 DefaultedOpt::try_parse_from(["test", "-i", "9000", "-p", "src/lib.rs",]).unwrap() 144 ); 145} 146