Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions harper-core/src/expr/sequence_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ impl SequenceExpr {

gen_then_from_is!(determiner);
gen_then_from_is!(demonstrative_determiner);
gen_then_from_is!(possessive_determiner);
gen_then_from_is!(quantifier);
gen_then_from_is!(non_quantifier_determiner);

Expand Down
204 changes: 204 additions & 0 deletions harper-core/src/linting/change_tack.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::patterns::Word;

pub struct ChangeTack {
expr: Box<dyn Expr>,
}

impl Default for ChangeTack {
fn default() -> Self {
let verb_forms = &["change", "changes", "changing", "changed"];
let noun_forms = &verb_forms[..3];
let eggcorns = &["tact", "tacks", "tacts"];

Self {
expr: Box::new(
SequenceExpr::default()
.then_longest_of(vec![
Box::new(SequenceExpr::word_set(verb_forms).then_optional(
SequenceExpr::default().t_ws().then_any_of(vec![
Box::new(SequenceExpr::default().then_possessive_determiner()),
Box::new(Word::new("it's")),
]),
)),
Box::new(SequenceExpr::word_set(noun_forms).t_ws().t_aco("of")),
])
.t_ws()
.then_word_set(eggcorns),
),
}
}
}

impl ExprLinter for ChangeTack {
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
let tact_tok = toks.last()?;
let tact_span = tact_tok.span;
let tact_chars = tact_span.get_content(src);

Some(Lint {
span: tact_span,
lint_kind: LintKind::Eggcorn,
suggestions: vec![Suggestion::replace_with_match_case(
['t', 'a', 'c', 'k'].to_vec(),
tact_chars,
)],
message: "A change in direction or approach is a change of `tack`. Not `tact` (or `tacks` or `tacts`).".to_owned(),
priority: 32,
})
}

fn description(&self) -> &'static str {
"Locates errors in the idioms `to change tack` and `change of tack` to convey the correct meaning of altering one's course or strategy."
}
}

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

// Verbs: change tack

#[test]
fn change_tact_atomic() {
assert_suggestion_result("change tact", ChangeTack::default(), "change tack");
}

#[test]
fn changed_tacks_atomic() {
assert_suggestion_result("changed tacks", ChangeTack::default(), "changed tack");
}

#[test]
fn changes_tacts_atomic() {
assert_suggestion_result("changes tacts", ChangeTack::default(), "changes tack");
}

#[test]
fn changing_tact_atomic() {
assert_suggestion_result("changing tact", ChangeTack::default(), "changing tack");
}

// Nouns: change of tack

#[test]
fn change_of_tacks_atomic() {
assert_suggestion_result("change of tacks", ChangeTack::default(), "change of tack");
}

#[test]
fn change_of_tact_real_world() {
assert_suggestion_result(
"Change of tact : come give your concerns - Death Knight",
ChangeTack::default(),
"Change of tack : come give your concerns - Death Knight",
);
}

#[test]
fn change_of_tacts_real_world() {
assert_suggestion_result(
"2013.08.15 - A Change of Tacts | Hero MUX Wiki | Fandom",
ChangeTack::default(),
"2013.08.15 - A Change of Tack | Hero MUX Wiki | Fandom",
);
}

#[test]
fn changing_of_tacks_real_world() {
assert_suggestion_result(
"Duffy's changing of tacks hidden in her poetry collection ...",
ChangeTack::default(),
"Duffy's changing of tack hidden in her poetry collection ...",
);
}

#[test]
fn changes_of_tact_real_world() {
assert_suggestion_result(
"While the notes and the changes of tact started to ...",
ChangeTack::default(),
"While the notes and the changes of tack started to ...",
);
}

// With possessive determiners

#[test]
fn changed_my_tact() {
assert_suggestion_result(
"I have changed my tact this year, and have two second dates in the next week.",
ChangeTack::default(),
"I have changed my tack this year, and have two second dates in the next week.",
);
}

#[test]
fn changed_our_tact() {
assert_suggestion_result(
"That being said we have changed our tact slightly and gone for making all UI elements lazy.",
ChangeTack::default(),
"That being said we have changed our tack slightly and gone for making all UI elements lazy.",
);
}

#[test]
fn change_your_tact() {
assert_suggestion_result(
"If you've ever heard the phrase “you've got to change your tact”, this is probably where it comes from.",
ChangeTack::default(),
"If you've ever heard the phrase “you've got to change your tack”, this is probably where it comes from.",
);
}

#[test]
fn change_his_tact() {
assert_suggestion_result(
"Why did Sephiroth change his tact with Cloud midway through the game?",
ChangeTack::default(),
"Why did Sephiroth change his tack with Cloud midway through the game?",
);
}

#[test]
fn changed_her_tact() {
assert_suggestion_result(
"Only the last commitment ceremony I think she changed her tact and went on about George needing to be the real George.",
ChangeTack::default(),
"Only the last commitment ceremony I think she changed her tack and went on about George needing to be the real George.",
);
}

#[test]
fn change_its_tact() {
assert_suggestion_result(
"The show seems to change its tact depending on the episode.",
ChangeTack::default(),
"The show seems to change its tack depending on the episode.",
);
}

#[test]
fn changing_its_tact_apostrophe() {
assert_suggestion_result(
"FYI, USL is changing it's tact internally about MLS II teams.",
ChangeTack::default(),
"FYI, USL is changing it's tack internally about MLS II teams.",
);
}

#[test]
fn changes_their_tact() {
assert_suggestion_result(
"As we become inoculated to attention grifts, the grifter changes their tact.",
ChangeTack::default(),
"As we become inoculated to attention grifts, the grifter changes their tack.",
);
}
}
2 changes: 2 additions & 0 deletions harper-core/src/linting/lint_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use super::boring_words::BoringWords;
use super::cant::Cant;
use super::capitalize_personal_pronouns::CapitalizePersonalPronouns;
use super::cautionary_tale::CautionaryTale;
use super::change_tack::ChangeTack;
use super::chock_full::ChockFull;
use super::comma_fixes::CommaFixes;
use super::compound_nouns::CompoundNouns;
Expand Down Expand Up @@ -450,6 +451,7 @@ impl LintGroup {
insert_expr_rule!(Cant, true);
insert_struct_rule!(CapitalizePersonalPronouns, true);
insert_expr_rule!(CautionaryTale, true);
insert_expr_rule!(ChangeTack, true);
insert_expr_rule!(ChockFull, true);
insert_struct_rule!(CommaFixes, true);
insert_struct_rule!(CompoundNouns, true);
Expand Down
2 changes: 2 additions & 0 deletions harper-core/src/linting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod boring_words;
mod cant;
mod capitalize_personal_pronouns;
mod cautionary_tale;
mod change_tack;
mod chock_full;
mod closed_compounds;
mod comma_fixes;
Expand Down Expand Up @@ -185,6 +186,7 @@ pub use boring_words::BoringWords;
pub use cant::Cant;
pub use capitalize_personal_pronouns::CapitalizePersonalPronouns;
pub use cautionary_tale::CautionaryTale;
pub use change_tack::ChangeTack;
pub use chock_full::ChockFull;
pub use comma_fixes::CommaFixes;
pub use compound_nouns::CompoundNouns;
Expand Down
16 changes: 0 additions & 16 deletions harper-core/src/linting/phrase_set_corrections/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,22 +332,6 @@ pub fn lint_group() -> LintGroup {
});

add_many_to_many_mappings!(group, {
"ChangeTack" => (
&[
// verb
(&["change tact", "change tacks", "change tacts"], &["change tack"]),
(&["changed tact", "changed tacks", "changed tacts"], &["changed tack"]),
(&["changes tact", "changes tacks", "changes tacts"], &["changes tack"]),
(&["changing tact", "changing tacks", "changing tacts"], &["changing tack"]),
// noun
(&["change of tact", "change of tacks", "change of tacts"], &["change of tack"]),
(&["changes of tact", "changes of tacks", "changes of tacts"], &["changes of tack"]),
(&["changing of tact", "changing of tacks", "changing of tacts"], &["changing of tack"])
],
"A change in direction or approach is a change of `tack`. Not `tact` (or `tacks` or `tacts`).",
"Locates errors in the idioms `to change tack` and `change of tack` to convey the correct meaning of altering one's course or strategy.",
LintKind::Eggcorn
),
"GetRidOf" => (
&[
(&["get rid off", "get ride of", "get ride off"], &["get rid of"]),
Expand Down
65 changes: 0 additions & 65 deletions harper-core/src/linting/phrase_set_corrections/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,71 +814,6 @@ fn operative_systems() {

// Many to many tests

// ChangeTack

// -change_tack-
#[test]
fn change_tact_atomic() {
assert_suggestion_result("change tact", lint_group(), "change tack");
}

#[test]
fn changed_tacks_atomic() {
assert_suggestion_result("changed tacks", lint_group(), "changed tack");
}

#[test]
fn changes_tacts_atomic() {
assert_suggestion_result("changes tacts", lint_group(), "changes tack");
}

#[test]
fn changing_tact_atomic() {
assert_suggestion_result("changing tact", lint_group(), "changing tack");
}

// -change_of_tack-
#[test]
fn change_of_tacks_atomic() {
assert_suggestion_result("change of tacks", lint_group(), "change of tack");
}

#[test]
fn change_of_tact_real_world() {
assert_suggestion_result(
"Change of tact : come give your concerns - Death Knight",
lint_group(),
"Change of tack : come give your concerns - Death Knight",
);
}

#[test]
fn change_of_tacts_real_world() {
assert_suggestion_result(
"2013.08.15 - A Change of Tacts | Hero MUX Wiki | Fandom",
lint_group(),
"2013.08.15 - A Change of Tack | Hero MUX Wiki | Fandom",
);
}

#[test]
fn changing_of_tacks_real_world() {
assert_suggestion_result(
"Duffy's changing of tacks hidden in her poetry collection ...",
lint_group(),
"Duffy's changing of tack hidden in her poetry collection ...",
);
}

#[test]
fn changes_of_tact_real_world() {
assert_suggestion_result(
"While the notes and the changes of tact started to ...",
lint_group(),
"While the notes and the changes of tack started to ...",
);
}

// GetRidOf

#[test]
Expand Down
Loading