Skip to content

Commit

Permalink
refactor(core): move em and en dash rules to their own linter
Browse files Browse the repository at this point in the history
  • Loading branch information
elijah-potter committed Jan 6, 2025
1 parent 7bdc753 commit 91adb6e
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 13 deletions.
89 changes: 89 additions & 0 deletions harper-core/src/linting/dashes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use crate::{
patterns::{EitherPattern, Pattern, SequencePattern},
Token, TokenStringExt,
};

use super::{Lint, LintKind, PatternLinter, Suggestion};

pub struct Dashes {
pattern: Box<dyn Pattern>,
}

impl Default for Dashes {
fn default() -> Self {
let en_dash = SequencePattern::default().then_hyphen().then_hyphen();
let em_dash = SequencePattern::default()
.then_hyphen()
.then_hyphen()
.then_hyphen();

let pattern = EitherPattern::new(vec![Box::new(em_dash), Box::new(en_dash)]);

Self {
pattern: Box::new(pattern),
}
}
}

impl PatternLinter for Dashes {
fn pattern(&self) -> &dyn Pattern {
self.pattern.as_ref()
}

fn match_to_lint(&self, matched_tokens: &[Token], _source: &[char]) -> Lint {
let span = matched_tokens.span().unwrap();
let lint_kind = LintKind::Formatting;

match matched_tokens.len() {
2 => Lint {
span,
lint_kind,
suggestions: vec![Suggestion::ReplaceWith(vec!['–'])],
message: "A sequence of hyphens is not an en dash.".to_owned(),
priority: 63,
},
3 => Lint {
span,
lint_kind,
suggestions: vec![Suggestion::ReplaceWith(vec!['—'])],
message: "A sequence of hyphens is not an em dash.".to_owned(),
priority: 63,
},
_ => panic!("Received unexpected number of tokens."),
}
}

fn description(&self) -> &'static str {
"Rather than outright using an em dash or en dash, authors often use a sequence of hyphens, expecting them to be condensed.\nThis rule does so."
}
}

#[cfg(test)]
mod tests {
use crate::linting::tests::{assert_suggestion_count, assert_suggestion_result};

use super::Dashes;

#[test]
fn catches_en_dash() {
assert_suggestion_result(
"pre--Industrial Revolution",
Dashes::default(),
"pre–Industrial Revolution",
);
}

#[test]
fn catches_em_dash() {
assert_suggestion_result(
"'There is no box' --- Scott",
Dashes::default(),
"'There is no box' — Scott",
);
}

#[test]
fn no_overlaps() {
assert_suggestion_count("'There is no box' --- Scott", Dashes::default(), 1);
}
}
13 changes: 0 additions & 13 deletions harper-core/src/linting/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,6 @@ impl Matcher {
"take", "a", "decision" => "make a decision"
};

// TODO: Improve the description for this lint specifically.
// We need to be more explicit that we are replacing with an Em dash
triggers.push(Rule {
pattern: vec![pt!(Hyphen), pt!(Hyphen), pt!(Hyphen)],
replace_with: vecword!("—"),
});

// Same goes for this En dash
triggers.push(Rule {
pattern: vec![pt!(Hyphen), pt!(Hyphen)],
replace_with: vecword!("–"),
});

triggers.push(Rule {
pattern: vec![pt!("L"), pt!(Period), pt!("L"), pt!(Period), pt!("M")],
replace_with: vecword!("large language model"),
Expand Down
1 change: 1 addition & 0 deletions harper-core/src/linting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod boring_words;
mod capitalize_personal_pronouns;
mod compound_words;
mod correct_number_suffix;
mod dashes;
mod dot_initialisms;
mod ellipsis_length;
mod linking_verbs;
Expand Down

0 comments on commit 91adb6e

Please sign in to comment.