1use clap::{builder::styling::Style, Arg};
13
14pub fn clap() -> crate::app::args::Args {
15 let matches = matches();
16 crate::app::args::Args {
17 test: matches.get_flag("test"),
18 log_level: crate::app::log::u8_to_log_level(matches.get_count("verbose")),
19 style: style(&matches),
20 }
21}
22
23fn matches() -> clap::ArgMatches {
24 clap::command!()
25 .name(env!("CARGO_PKG_NAME"))
26 .version(env!("CARGO_PKG_VERSION"))
27 .author(env!("CARGO_PKG_AUTHORS"))
28 .about(env!("CARGO_PKG_DESCRIPTION"))
29 .arg(Arg::new("test")
30 .long("test")
31 .help("Print test output for debugging, verifying, tracing, and the like.\nExample: --test")
32 .action(clap::ArgAction::SetTrue))
33 .arg(Arg::new("verbose")
34 .short('v')
35 .long("verbose")
36 .help("Set the verbosity level: 0=none, 1=error, 2=warn, 3=info, 4=debug, 5=trace.\nExample: --verbose …")
37 .action(clap::ArgAction::Count))
38 .arg(Arg::new("unit-separator")
39 .help("Set the unit separator (US) string")
40 .short('u')
41 .long("unit-separator")
42 .action(clap::ArgAction::Set))
43 .arg(Arg::new("record-separator")
44 .help("Set the record separator (RS) string.")
45 .short('r')
46 .long("record-separator")
47 .action(clap::ArgAction::Set))
48 .arg(Arg::new("group-separator")
49 .help("Set the group separator (GS) string.")
50 .short('g')
51 .long("group-separator")
52 .action(clap::ArgAction::Set))
53 .arg(Arg::new("file-separator")
54 .help("Set the file separator (FS) string.")
55 .short('f')
56 .long("file-separator")
57 .action(clap::ArgAction::Set))
58 .arg(Arg::new("escape")
59 .help("Set the escape (ESC) string.")
60 .short('e')
61 .long("escape")
62 .action(clap::ArgAction::Set))
63 .arg(Arg::new("end-of-transmission")
64 .help("Set the end of transmission (EOT) string.")
65 .short('z')
66 .long("end-of-transmission")
67 .action(clap::ArgAction::Set))
68 .arg(Arg::new("style-symbols")
69 .help(r#"Show marks as symbols, such as "␟" for Unit Separator."#)
70 .long("style-symbols")
71 .conflicts_with_all([
72 "style-braces",
73 "style-controls"
74 ])
75 .action(clap::ArgAction::SetTrue))
76 .arg(Arg::new("style-controls")
77 .help(r#"Show marks as controls, such as "\u001F" for Unit Separator."#)
78 .long("style-controls")
79 .conflicts_with_all([
80 "style-braces",
81 "style-symbols",
82 ])
83 .action(clap::ArgAction::SetTrue))
84 .arg(Arg::new("style-braces")
85 .help(r#"Show marks as braces, such as "{US}" for Unit Separator. This is to help plain text readers, and is not USV output."#)
86 .long("style-braces")
87 .conflicts_with_all([
88 "style-controls",
89 "style-symbols",
90 ])
91 .action(clap::ArgAction::SetTrue))
92 .arg(Arg::new("layout-units")
93 .help(r#"Show each unit on one line. This can be helpful for line-oriented tools."#)
94 .long("layout-units")
95 .conflicts_with_all([
96 "layout-records",
97 "layout-groups",
98 "layout-files",
99 "layout-0",
100 "layout-1",
101 "layout-2",
102 ])
103 .action(clap::ArgAction::SetTrue))
104 .arg(Arg::new("layout-records")
105 .help(r#"Show each record on one line. This is like a typical spreadsheet sheet export."#)
106 .long("layout-records")
107 .conflicts_with_all([
108 "layout-units",
109 "layout-groups",
110 "layout-files",
111 "layout-0",
112 "layout-1",
113 "layout-2",
114 ])
115 .action(clap::ArgAction::SetTrue))
116 .arg(Arg::new("layout-groups")
117 .help(r#"Show each group on one line. This can be helpful for folio-oriented tools."#)
118 .long("layout-groups")
119 .conflicts_with_all([
120 "layout-units",
121 "layout-records",
122 "layout-files",
123 "layout-0",
124 "layout-1",
125 "layout-2",
126 ])
127 .action(clap::ArgAction::SetTrue))
128 .arg(Arg::new("layout-files")
129 .help(r#"Show each file on one line. This can be helpful for archive-oriented tools."#)
130 .long("layout-files")
131 .conflicts_with_all([
132 "layout-units",
133 "layout-records",
134 "layout-groups",
135 "layout-0",
136 "layout-1",
137 "layout-2",
138 ])
139 .action(clap::ArgAction::SetTrue))
140 .arg(Arg::new("layout-0")
141 .help(r#"Show each item with no line around it. This is no layout, in other words one long line."#)
142 .long("layout-0")
143 .conflicts_with_all([
144 "layout-units",
145 "layout-records",
146 "layout-groups",
147 "layout-files",
148 "layout-1",
149 "layout-2",
150 ])
151 .action(clap::ArgAction::SetTrue))
152 .arg(Arg::new("layout-1")
153 .help(r#"Show each item with one line around it. This is like single-space lines for long form text."#)
154 .long("layout-1")
155 .conflicts_with_all([
156 "layout-units",
157 "layout-records",
158 "layout-groups",
159 "layout-files",
160 "layout-0",
161 "layout-2",
162 ])
163 .action(clap::ArgAction::SetTrue))
164 .arg(Arg::new("layout-2")
165 .help(r#"Show each item with two lines around it. This is like double-space lines for long form text."#)
166 .long("layout-2")
167 .conflicts_with_all([
168 "layout-units",
169 "layout-records",
170 "layout-groups",
171 "layout-files",
172 "layout-0",
173 "layout-1",
174 ])
175 .action(clap::ArgAction::SetTrue))
176 .get_matches()
177}
178
179fn style(matches: &clap::ArgMatches) -> usv::style::Style {
180 let style = if matches.get_flag("style-symbols") {
181 usv::style::style_symbols()
182 } else
183 if matches.get_flag("style-controls") {
184 usv::style::style_controls()
185 } else
186 if matches.get_flag("style-braces") {
187 usv::style::style_braces()
188 } else {
189 usv::style::style_symbols()
190 };
191 let mut style = layout(matches).map_style(&style);
192 if let Some(x) = matches.get_one::<String>("unit-separator") {
193 style.unit_separator = String::from(x)
194 }
195 if let Some(x) = matches.get_one::<String>("record-separator") {
196 style.record_separator = String::from(x)
197 }
198 if let Some(x) = matches.get_one::<String>("group-separator") {
199 style.group_separator = String::from(x)
200 }
201 if let Some(x) = matches.get_one::<String>("file-separator") {
202 style.file_separator = String::from(x)
203 }
204 if let Some(x) = matches.get_one::<String>("escape") {
205 style.escape = String::from(x)
206 }
207 if let Some(x) = matches.get_one::<String>("end-of-transmission") {
208 style.end_of_transmission = String::from(x)
209 }
210 style
211}
212
213fn layout(matches: &clap::ArgMatches) -> Box<dyn usv::style::MapStyle> {
214 if matches.get_flag("layout-0") {
215 Box::new(usv::layout::layout_0::Layout0)
216 } else
217 if matches.get_flag("layout-1") {
218 Box::new(usv::layout::layout_1::Layout1)
219 } else
220 if matches.get_flag("layout-2") {
221 Box::new(usv::layout::layout_2::Layout2)
222 } else
223 if matches.get_flag("layout-units") {
224 Box::new(usv::layout::layout_units::LayoutUnits)
225 } else
226 if matches.get_flag("layout-records") {
227 Box::new(usv::layout::layout_records::LayoutRecords)
228 } else
229 if matches.get_flag("layout-groups") {
230 Box::new(usv::layout::layout_groups::LayoutGroups)
231 } else
232 if matches.get_flag("layout-files") {
233 Box::new(usv::layout::layout_files::LayoutFiles)
234 } else {
235 Box::new(usv::layout::layout_records::LayoutRecords)
236 }
237}