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
15 use clap::Parser;
16
17 use std::num::ParseIntError;
18 use std::path::PathBuf;
19
20 #[derive(Parser, PartialEq, Debug)]
21 struct 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]
test_path_opt_simple()39 fn 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
parse_hex(input: &str) -> Result<u64, ParseIntError>60 fn parse_hex(input: &str) -> Result<u64, ParseIntError> {
61 u64::from_str_radix(input, 16)
62 }
63
64 #[derive(Parser, PartialEq, Debug)]
65 struct HexOpt {
66 #[arg(short, value_parser = parse_hex)]
67 number: u64,
68 }
69
70 #[test]
71 #[cfg(feature = "error-context")]
test_parse_hex()72 fn 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)]
93 struct ErrCode(u32);
94 impl std::error::Error for ErrCode {}
95 impl std::fmt::Display for ErrCode {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 std::fmt::Display::fmt(&self.0, f)
98 }
99 }
custom_parser_2(_: &str) -> Result<&'static str, ErrCode>100 fn custom_parser_2(_: &str) -> Result<&'static str, ErrCode> {
101 Ok("B")
102 }
103
104 #[derive(Parser, PartialEq, Debug)]
105 struct NoOpOpt {
106 #[arg(short, value_parser = custom_parser_2)]
107 b: &'static str,
108 }
109
110 #[test]
test_every_custom_parser()111 fn test_every_custom_parser() {
112 assert_eq!(
113 NoOpOpt { b: "B" },
114 NoOpOpt::try_parse_from(["test", "-b=?"]).unwrap()
115 );
116 }
117
118 #[test]
update_every_custom_parser()119 fn 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)]
128 struct DefaultedOpt {
129 #[arg(short)]
130 integer: u64,
131
132 #[arg(short)]
133 path: PathBuf,
134 }
135
136 #[test]
test_parser_with_default_value()137 fn 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