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(short, long, default_value_t = ',', value_parser=get_valid_sep)]
53 pub sep: char,
54 #[arg(short, long, default_value_t = '"')]
56 pub quote: char,
57}
58
59#[derive(Debug, Args)]
60pub struct Tail {
61 pub filename: Option<String>,
63 #[arg(long, default_value_t = false)]
65 pub no_header: bool,
66 #[arg(short, long, default_value_t = 10)]
68 pub n: usize,
69 #[arg(short = 'S', long, default_value_t = 0)]
71 pub sheet: usize,
72 #[arg(short = 'E', long, default_value_t = false)]
74 pub export: bool,
75}
76
77#[derive(Debug, Args)]
78pub struct Headers {
79 pub filename: Option<String>,
81 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
83 pub sep: char,
84 #[arg(short, long, default_value_t = '"')]
86 pub quote: char,
87 #[arg(short = 'S', long, default_value_t = 0)]
89 pub sheet: usize,
90}
91
92#[derive(Debug, Args)]
93pub struct Clean {
94 pub filename: Option<String>,
96 #[arg(short, long, default_value_t = String::from(""), hide_default_value=true)]
98 pub output: String,
99 #[arg(short, long, default_value_t = String::from("\""))]
101 pub escape: String,
102}
103
104#[derive(Debug, Args)]
105pub struct Flatten {
106 pub filename: Option<String>,
108 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
110 pub sep: char,
111 #[arg(short, long, default_value_t = '"')]
113 pub quote: char,
114 #[arg(long, default_value_t = false)]
116 pub no_header: bool,
117 #[arg(short, long, default_value_t = String::from("#"))]
119 pub delimiter: String,
120 #[arg(short, long, default_value_t = 5)]
122 pub n: i32,
123 #[arg(short = 'S', long, default_value_t = 0)]
125 pub sheet: usize,
126}
127
128#[derive(Debug, Args)]
129pub struct Frequency {
130 pub filename: Option<String>,
132 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
134 pub sep: char,
135 #[arg(short, long, default_value_t = '"')]
137 pub quote: char,
138 #[arg(long, default_value_t = false)]
140 pub no_header: bool,
141 #[arg(short, long, default_value_t = String::from("0"), allow_hyphen_values=true)]
143 pub cols: String,
144 #[arg(short, long, default_value_t = false)]
146 pub ascending: bool,
147 #[arg(short = 'E', long, default_value_t = false)]
149 pub export: bool,
150 #[arg(short, long, default_value_t = -1)]
152 pub n: i32,
153 #[arg(short = 'S', long, default_value_t = 0)]
155 pub sheet: usize,
156}
157
158#[derive(Debug, Args)]
159pub struct Split {
160 pub filename: Option<String>,
162 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
164 pub sep: char,
165 #[arg(short, long, default_value_t = '"')]
167 pub quote: char,
168 #[arg(long, default_value_t = false)]
170 pub no_header: bool,
171 #[arg(short, long, default_value_t = 0)]
173 pub col: usize,
174 #[arg(short = 'S', long, default_value_t = 0)]
176 pub sheet: usize,
177 #[arg(long)]
179 pub size: Option<usize>,
180}
181
182#[derive(Debug, Args)]
183pub struct Slice {
184 pub filename: Option<String>,
186 #[arg(short, long, default_value_t = 0)]
188 pub start: usize,
189 #[arg(short, long)]
191 pub end: Option<usize>,
192 #[arg(short, long)]
194 pub length: Option<usize>,
195 #[arg(short, long)]
197 pub index: Option<usize>,
198 #[arg(long, default_value_t = false)]
200 pub no_header: bool,
201 #[arg(short = 'E', long, default_value_t = false)]
203 pub export: bool,
204 #[arg(short = 'S', long, default_value_t = 0)]
206 pub sheet: usize,
207}
208
209#[derive(Debug, Args)]
210pub struct Select {
211 pub filename: Option<String>,
213 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
215 pub sep: char,
216 #[arg(short, long, default_value_t = ',')]
218 pub quote: char,
219 #[arg(long, default_value_t = false)]
221 pub no_header: bool,
222 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
224 pub cols: String,
225 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
227 pub filter: String,
228 #[arg(short = 'E', long, default_value_t = false)]
230 pub export: bool,
231 #[arg(short = 'S', long, default_value_t = 0)]
233 pub sheet: usize,
234}
235
236#[derive(Debug, Args)]
237pub struct Stats {
238 pub filename: Option<String>,
240 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
242 pub sep: char,
243 #[arg(short, long, default_value_t = ',')]
245 pub quote: char,
246 #[arg(long, default_value_t = false)]
248 pub no_header: bool,
249 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
251 pub cols: String,
252 #[arg(short = 'E', long, default_value_t = false)]
254 pub export: bool,
255 #[arg(short = 'S', long, default_value_t = 0)]
257 pub sheet: usize,
258}
259
260#[derive(Debug, Args)]
261pub struct Excel2csv {
262 pub filename: Option<String>,
264 #[arg(short = 'S', long, default_value_t = 0)]
266 pub sheet: usize,
267 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
269 pub sep: char,
270 #[arg(short, long, default_value_t = '"')]
272 pub quote: char,
273}
274
275#[derive(Debug, Args)]
276pub struct Table {
277 pub filename: Option<String>,
279 #[arg(short = 'S', long, default_value_t = 0)]
281 pub sheet: usize,
282 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
284 pub sep: char,
285 #[arg(short, long, default_value_t = '"')]
287 pub quote: char,
288}
289
290#[derive(Debug, Args)]
291pub struct Search {
292 pub pattern: String,
294 pub filename: Option<String>,
296 #[arg(long, default_value_t = false)]
298 pub no_header: bool,
299 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
301 pub sep: char,
302 #[arg(short, long, default_value_t = '"')]
304 pub quote: char,
305 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
307 pub filter: String,
308 #[arg(short, long, default_value_t = String::from(""), allow_hyphen_values=true)]
310 pub cols: String,
311 #[arg(short = 'S', long, default_value_t = String::from("0"), allow_hyphen_values = true)]
313 pub sheet: String,
314 #[arg(short = 'E', long, default_value_t = false)]
316 pub export: bool,
317}
318
319#[derive(Debug, Args)]
320pub struct Sort {
321 pub filename: Option<String>,
323 #[arg(short, long, default_value_t=',', value_parser=get_valid_sep )]
325 pub sep: char,
326 #[arg(short, long, default_value_t = '"')]
328 pub quote: char,
329 #[arg(long, default_value_t = false)]
331 pub no_header: bool,
332 #[arg(short, long, default_value_t = String::from("0"), allow_hyphen_values=true)]
335 pub cols: String,
336 #[arg(short = 'S', long, default_value_t = 0)]
338 pub sheet: usize,
339 #[arg(short = 'E', long, default_value_t = false)]
341 pub export: bool,
342}
343
344#[derive(Debug, Args)]
345pub struct Sample {
346 pub filename: Option<String>,
348 #[arg(long, default_value_t = false)]
350 pub no_header: bool,
351 #[arg(short = 'S', long, default_value_t = 0)]
353 pub sheet: usize,
354 #[arg(short, long, default_value_t = 10)]
356 pub n: usize,
357 #[arg(long)]
359 pub seed: Option<usize>,
360 #[arg(short = 'E', long, default_value_t = false)]
362 pub export: bool,
363 #[arg(long, long, default_value_t = false)]
365 pub show_number: bool,
366 #[arg(short, long, default_value_t = 0.0)]
368 pub time_limit: f32,
369}
370
371#[derive(Debug, Args)]
372pub struct To {
373 pub out: String,
375 pub filename: Option<String>,
377 #[arg(long, default_value_t = false)]
379 pub no_header: bool,
380 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
382 pub sep: char,
383 #[arg(short, long, default_value_t = '"')]
385 pub quote: char,
386 #[arg(short = 'S', long, default_value_t = 0)]
388 pub sheet: usize,
389}
390
391#[derive(Debug, Args)]
392pub struct Unique {
393 pub filename: Option<String>,
395 #[arg(short, long, default_value_t = ',', value_parser=get_valid_sep)]
397 pub sep: char,
398 #[arg(short, long, default_value_t = '"')]
400 pub quote: char,
401 #[arg(long, default_value_t = false)]
403 pub no_header: bool,
404 #[arg(short, long, default_value_t = String::from("-1"), allow_hyphen_values=true)]
406 pub cols: String,
407 #[arg(long, default_value_t = false)]
409 pub keep_last: bool,
410 #[arg(short = 'S', long, default_value_t = 0)]
412 pub sheet: usize,
413 #[arg(short = 'E', long, default_value_t = false)]
415 pub export: bool,
416}
417
418macro_rules! command_run {
419 ($method:ident) => {
420 impl $method {
421 pub fn path(&self) -> PathBuf {
422 let p = self.filename.as_ref().unwrap();
423 full_path(p)
424 }
425
426 pub fn run(&self) {
427 match &self.filename {
428 Some(f) => match is_excel(&full_path(f)) {
429 true => self.excel_run(),
430 false => self.csv_run(),
431 },
432 None => self.io_run(),
433 }
434 .handle_err()
435 }
436 }
437 };
438}
439
440command_run!(Count);
441command_run!(Estimate);
442command_run!(Head);
443command_run!(Tail);
444command_run!(Headers);
445command_run!(Clean);
446command_run!(Flatten);
447command_run!(Frequency);
448command_run!(Split);
449command_run!(Slice);
450command_run!(Select);
451command_run!(Stats);
452command_run!(Excel2csv);
453command_run!(Table);
454command_run!(Sort);
455command_run!(Search);
456command_run!(Sample);
457command_run!(To);
458command_run!(Unique);
459command_run!(Size);
460
461macro_rules! impl_row_split {
462 ($cmd:ident) => {
463 impl $cmd {
464 #[allow(dead_code)]
465 pub fn split<'a>(&self, row: &'a str) -> CsvRowSplitter<'a> {
466 CsvRowSplitter::new(row, self.sep, self.quote)
467 }
468
469 #[allow(dead_code)]
470 pub fn split_row_to_vec<'a>(&self, row: &'a str) -> Vec<&'a str> {
471 CsvRowSplitter::new(row, self.sep, self.quote).collect()
472 }
473
474 #[allow(dead_code)]
475 pub fn split_row_to_owned_vec<'a>(&self, row: &'a str) -> Vec<String> {
476 CsvRowSplitter::new(row, self.sep, self.quote)
477 .map(|i| i.to_owned())
478 .collect::<Vec<_>>()
479 }
480
481 #[allow(dead_code)]
482 pub fn row_field_count<'a>(&self, row: &'a str) -> usize {
483 CsvRowSplitter::new(row, self.sep, self.quote).count()
484 }
485 }
486 };
487}
488
489impl_row_split!(Head);
490impl_row_split!(Headers);
491impl_row_split!(Frequency);
492impl_row_split!(Select);
493impl_row_split!(Stats);
494impl_row_split!(To);
495impl_row_split!(Flatten);
496impl_row_split!(Unique);
497impl_row_split!(Search);
498impl_row_split!(Table);
499impl_row_split!(Split);
500impl_row_split!(Excel2csv);