1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use clap::{Parser, ValueEnum};
use std::io;
use std::path::PathBuf;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Default)]
pub enum ReportingMode {
#[default]
Text,
Json,
}
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
#[arg(short = 't', long, default_value_t = 0)]
pub lev_threshold: usize,
#[arg(short, long, default_value_t = 1)]
pub line_threshold: usize,
#[arg(short, long, default_value_t = 10)]
pub block_threshold: usize,
#[arg(short, long, default_value_t = false)]
pub verbose: bool,
pub files: Vec<PathBuf>,
#[arg(value_enum, long, default_value_t = ReportingMode::Text)]
pub reporting_mode: ReportingMode,
}
impl Cli {
pub fn populate_files_from_stdin(&mut self) {
let mut files: Vec<PathBuf> = Vec::new();
for line in io::stdin().lines() {
match line {
Ok(f) => files.push(f.into()),
Err(e) => panic!("{e}"),
}
}
self.files = files;
}
pub fn files_from_stdin(&self) -> bool {
self.files.is_empty()
}
pub fn print(&self) {
if !self.verbose {
return;
}
if self.reporting_mode != ReportingMode::Text {
return;
}
eprint!("{} file(s)", self.files.len());
if self.files.len() <= 10 {
eprintln!(" {:?}", &self.files);
} else {
eprintln!(" {:?}...", &self.files[..10]);
}
eprintln!("Verbosity (-v): {}", self.verbose);
eprintln!(
"Comparison threshold (-t): {} ({})",
self.lev_threshold,
if self.lev_threshold > 0 {
"Levenshtein distance"
} else {
"Strict equality"
}
);
eprintln!(
"Minimum length of first line before block consideration (-l): {}",
self.line_threshold
);
eprintln!(
"Minimum length of block before consideration (-b): {}",
self.block_threshold
);
}
}