diff --git a/src/cli.rs b/src/cli.rs index 0041a82..35fd6a7 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -38,10 +38,11 @@ fn calculate_complexity(flags: flags::Flags) { builder.filter_entry(move |e| files_filter.matches(e.path())); let results = Arc::new(Mutex::new(vec![])); + let scorer = flags.scorer; builder.build_parallel().run(|| { Box::new(|result| { - let mut scorer: Box = Box::new(scoring::Standard::default()); + let mut scorer = build_scorer(&scorer); if let Some(parsed_file) = parse_dir_entry(&mut scorer, result) { let mut results = results.lock().unwrap(); results.push(parsed_file); @@ -60,6 +61,13 @@ fn calculate_complexity(flags: flags::Flags) { } } +fn build_scorer(algorithm: &flags::ScoringAlgorithm) -> Box { + match algorithm { + flags::ScoringAlgorithm::Standard => Box::new(scoring::Standard::default()), + flags::ScoringAlgorithm::Length => Box::new(scoring::Length::default()), + } +} + fn render_standard(results: &[ParsedFile]) { for parsed_file in results { println!( diff --git a/src/flags.rs b/src/flags.rs index 9a27b27..e21f1aa 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -27,6 +27,24 @@ impl FromStr for Format { } } +#[derive(Debug)] +pub enum ScoringAlgorithm { + Standard, + Length, +} + +impl FromStr for ScoringAlgorithm { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_ref() { + "standard" => Ok(ScoringAlgorithm::Standard), + "length" => Ok(ScoringAlgorithm::Length), + v => Err(format!("Unknown scoring algorithm: {}", v)), + } + } +} + #[derive(Debug, StructOpt)] #[structopt( name = "complexity", @@ -51,4 +69,8 @@ pub struct Flags { /// Format output #[structopt(long, possible_values = &["standard", "csv", "json"], default_value = "standard", case_insensitive = true)] pub format: Format, + + /// Scoring algorithm + #[structopt(short = "s", long, possible_values = &["standard", "length"], default_value = "standard", case_insensitive = true)] + pub scorer: ScoringAlgorithm, } diff --git a/src/scoring.rs b/src/scoring.rs index 05f6288..9340d8a 100644 --- a/src/scoring.rs +++ b/src/scoring.rs @@ -1,5 +1,7 @@ +mod length; mod standard; +pub use length::Length; pub use standard::Standard; pub trait ScoreVisitor { diff --git a/src/scoring/length.rs b/src/scoring/length.rs new file mode 100644 index 0000000..a8a2906 --- /dev/null +++ b/src/scoring/length.rs @@ -0,0 +1,47 @@ +use crate::scoring::ScoreVisitor; + +pub struct Length { + line_length: usize, +} + +impl Default for Length { + fn default() -> Self { + Self { line_length: 0 } + } +} + +impl ScoreVisitor for Length { + fn visit_line_length(&mut self, length: usize) { + self.line_length = length; + } + + fn visit_first_line(&mut self, _: usize) {} + + fn visit_indent(&mut self, _: usize) {} + + fn visit_same(&mut self, _: usize) {} + + fn visit_dedent(&mut self, _: usize) {} + + fn score(&self) -> f32 { + self.line_length as f32 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::scoring::{score, ScoreVisitor}; + use approx::*; + + #[test] + fn length_only_uses_file_length() { + let mut scorer: Box = Box::new(Length::default()); + + assert!(abs_diff_eq!( + score(&mut scorer, &vec![0, 2, 4, 6, 8, 10, 8, 6, 4, 2, 0]), + 11.0, + epsilon = 0.0001 + )); + } +}