1use crate::utils::{
2 cli_result::E, file::is_excel, filename::full_path, row_split::CsvRowSplitter,
3 util::get_valid_sep,
4};
5use clap::Args;
6use std::path::PathBuf;
7
8#[derive(Debug, Args)]
9pub struct Count {
10 pub filename: Option<String>,
12 #[arg(long, default_value_t = false)]
14 pub no_header: bool,
15 #[arg(short = 'S', long, default_value_t = 0)]
17 pub sheet: usize,
18}
19
20#[derive(Debug, Args)]
21pub struct Size {
22 pub filename: Option<String>,
24}
25
26#[derive(Debug, Args)]
27pub struct Estimate {
28 pub filename: Option<String>,
30 #[arg(short = 'S', long, default_value_t = 0)]
32 pub sheet: usize,
33}
34
35#[derive(Debug, Args)]
36pub struct Head {
37 pub filename: Option<String>,
39 #[arg(long, default_value_t = false)]
41 pub no_header: bool,
42 #[arg(short, long, default_value_t = 10)]
44 pub n: usize,
45 #[arg(short = 'S', long, default_value_t = 0)]
47 pub sheet: usize,
48 #[arg(short = 'E', long, default_value_t = false)]
50 pub export: bool,
51 #[arg(long, default_value_t = false)]
53 pub return_result: bool,
54 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
56 pub sep: char,
57 #[arg(short, long, default_value_t = '"')]
59 pub quote: char,
60}
61
62#[derive(Debug, Args)]
63pub struct Tail {
64 pub filename: Option<String>,
66 #[arg(long, default_value_t = false)]
68 pub no_header: bool,
69 #[arg(short, long, default_value_t = 10)]
71 pub n: usize,
72 #[arg(short = 'S', long, default_value_t = 0)]
74 pub sheet: usize,
75 #[arg(short = 'E', long, default_value_t = false)]
77 pub export: bool,
78}
79
80#[derive(Debug, Args)]
81pub struct Headers {
82 pub filename: Option<String>,
84 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
86 pub sep: char,
87 #[arg(short, long, default_value_t = '"')]
89 pub quote: char,
90 #[arg(short = 'S', long, default_value_t = 0)]
92 pub sheet: usize,
93}
94
95#[derive(Debug, Args)]
96pub struct Clean {
97 pub filename: Option<String>,
99 #[arg(short, long, default_value_t = String::from(""), hide_default_value=true)]
101 pub output: String,
102 #[arg(short, long, default_value_t = String::from("\""))]
104 pub escape: String,
105}
106
107#[derive(Debug, Args)]
108pub struct Flatten {
109 pub filename: Option<String>,
111 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
113 pub sep: char,
114 #[arg(short, long, default_value_t = '"')]
116 pub quote: char,
117 #[arg(long, default_value_t = false)]
119 pub no_header: bool,
120 #[arg(short, long, default_value_t = String::from("#"))]
122 pub delimiter: String,
123 #[arg(short, long, default_value_t = 5)]
125 pub n: i32,
126 #[arg(short = 'S', long, default_value_t = 0)]
128 pub sheet: usize,
129}
130
131#[derive(Debug, Args)]
132pub struct Frequency {
133 pub filename: Option<String>,
135 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
137 pub sep: char,
138 #[arg(short, long, default_value_t = '"')]
140 pub quote: char,
141 #[arg(long, default_value_t = false)]
143 pub no_header: bool,
144 #[arg(short, long, default_value_t = String::from("0"), allow_hyphen_values=true)]
146 pub cols: String,
147 #[arg(short, long, default_value_t = false)]
149 pub ascending: bool,
150 #[arg(short = 'E', long, default_value_t = false)]
152 pub export: bool,
153 #[arg(short, long, default_value_t = -1)]
155 pub n: i32,
156 #[arg(short = 'S', long, default_value_t = 0)]
158 pub sheet: usize,
159}
160
161#[derive(Debug, Args)]
162pub struct Split {
163 pub filename: Option<String>,
165 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
167 pub sep: char,
168 #[arg(short, long, default_value_t = '"')]
170 pub quote: char,
171 #[arg(long, default_value_t = false)]
173 pub no_header: bool,
174 #[arg(short, long, default_value_t = 0)]
176 pub col: usize,
177 #[arg(short = 'S', long, default_value_t = 0)]
179 pub sheet: usize,
180 #[arg(long)]
182 pub size: Option<usize>,
183}
184
185#[derive(Debug, Args)]
186pub struct Slice {
187 pub filename: Option<String>,
189 #[arg(short, long, default_value_t = 0)]
191 pub start: usize,
192 #[arg(short, long)]
194 pub end: Option<usize>,
195 #[arg(short, long)]
197 pub length: Option<usize>,
198 #[arg(short, long)]
200 pub index: Option<usize>,
201 #[arg(long, default_value_t = false)]
203 pub no_header: bool,
204 #[arg(short = 'E', long, default_value_t = false)]
206 pub export: bool,
207 #[arg(short = 'S', long, default_value_t = 0)]
209 pub sheet: usize,
210}
211
212#[derive(Debug, Args)]
213pub struct Select {
214 pub filename: Option<String>,
216 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
218 pub sep: char,
219 #[arg(short, long, default_value_t = ',')]
221 pub quote: char,
222 #[arg(long, default_value_t = false)]
224 pub no_header: bool,
225 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
227 pub cols: String,
228 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
230 pub filter: String,
231 #[arg(short = 'E', long, default_value_t = false)]
233 pub export: bool,
234 #[arg(short = 'S', long, default_value_t = 0)]
236 pub sheet: usize,
237}
238
239#[derive(Debug, Args)]
240pub struct Stats {
241 pub filename: Option<String>,
243 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
245 pub sep: char,
246 #[arg(short, long, default_value_t = ',')]
248 pub quote: char,
249 #[arg(long, default_value_t = false)]
251 pub no_header: bool,
252 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
254 pub cols: String,
255 #[arg(short = 'E', long, default_value_t = false)]
257 pub export: bool,
258 #[arg(short = 'S', long, default_value_t = 0)]
260 pub sheet: usize,
261}
262
263#[derive(Debug, Args)]
264pub struct Excel2csv {
265 pub filename: Option<String>,
267 #[arg(short = 'S', long, default_value_t = 0)]
269 pub sheet: usize,
270 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
272 pub sep: char,
273 #[arg(short, long, default_value_t = '"')]
275 pub quote: char,
276}
277
278#[derive(Debug, Args)]
279pub struct Table {
280 pub filename: Option<String>,
282 #[arg(short = 'S', long, default_value_t = 0)]
284 pub sheet: usize,
285 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
287 pub sep: char,
288 #[arg(short, long, default_value_t = '"')]
290 pub quote: char,
291}
292
293#[derive(Debug, Args)]
294pub struct Search {
295 pub pattern: String,
297 pub filename: Option<String>,
299 #[arg(long, default_value_t = false)]
301 pub no_header: bool,
302 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
304 pub sep: char,
305 #[arg(short, long, default_value_t = '"')]
307 pub quote: char,
308 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
310 pub filter: String,
311 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
313 pub cols: String,
314 #[arg(short = 'S', long, default_value_t = String::from("0"), allow_hyphen_values = true)]
316 pub sheet: String,
317 #[arg(short = 'E', long, default_value_t = false)]
319 pub export: bool,
320}
321
322#[derive(Debug, Args)]
323pub struct Sort {
324 pub filename: Option<String>,
326 #[arg(short, long, default_value_t=',', value_parser=get_valid_sep )]
328 pub sep: char,
329 #[arg(short, long, default_value_t = '"')]
331 pub quote: char,
332 #[arg(long, default_value_t = false)]
334 pub no_header: bool,
335 #[arg(short, long, default_value_t = String::from("0"), allow_hyphen_values=true)]
338 pub cols: String,
339 #[arg(short = 'S', long, default_value_t = 0)]
341 pub sheet: usize,
342 #[arg(short = 'E', long, default_value_t = false)]
344 pub export: bool,
345}
346
347#[derive(Debug, Args)]
348pub struct Sample {
349 pub filename: Option<String>,
351 #[arg(long, default_value_t = false)]
353 pub no_header: bool,
354 #[arg(short = 'S', long, default_value_t = 0)]
356 pub sheet: usize,
357 #[arg(short, long, default_value_t = 10)]
359 pub n: usize,
360 #[arg(long)]
362 pub seed: Option<usize>,
363 #[arg(short = 'E', long, default_value_t = false)]
365 pub export: bool,
366 #[arg(long, long, default_value_t = false)]
368 pub show_number: bool,
369 #[arg(short, long, default_value_t = 0.0)]
371 pub time_limit: f32,
372}
373
374#[derive(Debug, Args)]
375pub struct To {
376 pub out: String,
378 pub filename: Option<String>,
380 #[arg(long, default_value_t = false)]
382 pub no_header: bool,
383 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
385 pub sep: char,
386 #[arg(short, long, default_value_t = '"')]
388 pub quote: char,
389 #[arg(short = 'S', long, default_value_t = 0)]
391 pub sheet: usize,
392}
393
394#[derive(Debug, Args)]
395pub struct Unique {
396 pub filename: Option<String>,
398 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
400 pub sep: char,
401 #[arg(short, long, default_value_t = '"')]
403 pub quote: char,
404 #[arg(long, default_value_t = false)]
406 pub no_header: bool,
407 #[arg(short, long, default_value_t = String::from("-1"), allow_hyphen_values=true)]
409 pub cols: String,
410 #[arg(long, default_value_t = false)]
412 pub keep_last: bool,
413 #[arg(short = 'S', long, default_value_t = 0)]
415 pub sheet: usize,
416 #[arg(short = 'E', long, default_value_t = false)]
418 pub export: bool,
419}
420
421macro_rules! command_run {
422 ($method:ident) => {
423 impl $method {
424 pub fn path(&self) -> PathBuf {
425 let p = self.filename.as_ref().unwrap();
426 full_path(p)
427 }
428
429 pub fn run(&self) {
430 match &self.filename {
431 Some(f) => match is_excel(&full_path(f)) {
432 true => self.excel_run(),
433 false => self.csv_run(),
434 },
435 None => self.io_run(),
436 }
437 .handle_err()
438 }
439 }
440 };
441}
442
443command_run!(Count);
444command_run!(Estimate);
445command_run!(Head);
446command_run!(Tail);
447command_run!(Headers);
448command_run!(Clean);
449command_run!(Flatten);
450command_run!(Frequency);
451command_run!(Split);
452command_run!(Slice);
453command_run!(Select);
454command_run!(Stats);
455command_run!(Excel2csv);
456command_run!(Table);
457command_run!(Sort);
458command_run!(Search);
459command_run!(Sample);
460command_run!(To);
461command_run!(Unique);
462command_run!(Size);
463
464macro_rules! impl_row_split {
465 ($cmd:ident) => {
466 impl $cmd {
467 #[allow(dead_code)]
468 pub fn split<'a>(&self, row: &'a str) -> CsvRowSplitter<'a> {
469 CsvRowSplitter::new(row, self.sep, self.quote)
470 }
471
472 #[allow(dead_code)]
473 pub fn split_row_to_vec<'a>(&self, row: &'a str) -> Vec<&'a str> {
474 CsvRowSplitter::new(row, self.sep, self.quote).collect()
475 }
476
477 #[allow(dead_code)]
478 pub fn split_row_to_owned_vec<'a>(&self, row: &'a str) -> Vec<String> {
479 CsvRowSplitter::new(row, self.sep, self.quote)
480 .map(|i| i.to_owned())
481 .collect::<Vec<_>>()
482 }
483
484 #[allow(dead_code)]
485 pub fn row_field_count<'a>(&self, row: &'a str) -> usize {
486 CsvRowSplitter::new(row, self.sep, self.quote).count()
487 }
488 }
489 };
490}
491
492impl_row_split!(Head);
493impl_row_split!(Headers);
494impl_row_split!(Frequency);
495impl_row_split!(Select);
496impl_row_split!(Stats);
497impl_row_split!(To);
498impl_row_split!(Flatten);
499impl_row_split!(Unique);
500impl_row_split!(Search);
501impl_row_split!(Table);
502impl_row_split!(Split);
503impl_row_split!(Excel2csv);