From c5b570e387cd9df7dec1713f49d7d29d69cba4fe Mon Sep 17 00:00:00 2001 From: Elijah Potter Date: Mon, 6 Jan 2025 11:22:42 -0700 Subject: [PATCH] feat(core): make proper nouns important to the `SpellCheck` rule --- harper-core/dictionary.dict | 3 ++- harper-core/src/linting/spell_check.rs | 28 +++++++++++++++++++++++++ harper-core/src/spell/fst_dictionary.rs | 2 +- harper-core/src/spell/mod.rs | 11 +++++++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/harper-core/dictionary.dict b/harper-core/dictionary.dict index d3753e0b..02fc35f0 100644 --- a/harper-core/dictionary.dict +++ b/harper-core/dictionary.dict @@ -31305,7 +31305,7 @@ marital/5Y maritime/5 marjoram/1M mark/14AMDSG -markdown/12SM +Markdown/12SM marked/54U markedly/ marker/14MS @@ -49768,3 +49768,4 @@ uncheck/SM upsample/SMG organoid/SM centric/SM +Harper/SM diff --git a/harper-core/src/linting/spell_check.rs b/harper-core/src/linting/spell_check.rs index 3f5f7c6a..60c16d58 100644 --- a/harper-core/src/linting/spell_check.rs +++ b/harper-core/src/linting/spell_check.rs @@ -98,3 +98,31 @@ impl Linter for SpellCheck { "Looks and provides corrections for misspelled words." } } + +#[cfg(test)] +mod tests { + use crate::{ + linting::tests::{assert_lint_count, assert_suggestion_result}, + FstDictionary, + }; + + use super::SpellCheck; + + #[test] + fn markdown_capitalized() { + assert_suggestion_result( + "The word markdown should be capitalized.", + SpellCheck::new(FstDictionary::curated()), + "The word Markdown should be capitalized.", + ); + } + + #[test] + fn harper_automattic_capitalized() { + assert_lint_count( + "So should harper and automattic.", + SpellCheck::new(FstDictionary::curated()), + 2, + ); + } +} diff --git a/harper-core/src/spell/fst_dictionary.rs b/harper-core/src/spell/fst_dictionary.rs index 574b1115..d9d688bd 100644 --- a/harper-core/src/spell/fst_dictionary.rs +++ b/harper-core/src/spell/fst_dictionary.rs @@ -45,7 +45,7 @@ lazy_static! { thread_local! { // Builders are computationally expensive and do not depend on the word, so we store a // collection of builders and the associated edit distance here. - // Currently, the edit distance we use is 3, but a value that does not exist in this + // Currently, the edit distance we use is three, but a value that does not exist in this // collection will create a new builder of that distance and push it to the collection. static AUTOMATON_BUILDERS: RefCell> = RefCell::new(vec![( EXPECTED_DISTANCE, diff --git a/harper-core/src/spell/mod.rs b/harper-core/src/spell/mod.rs index 91124f2d..5d5c75c7 100644 --- a/harper-core/src/spell/mod.rs +++ b/harper-core/src/spell/mod.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::ops::Index; use itertools::{Itertools, MinMaxResult}; @@ -15,7 +16,7 @@ mod full_dictionary; mod hunspell; mod merged_dictionary; -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] pub struct FuzzyMatchResult<'a> { word: &'a [char], edit_distance: u8, @@ -59,6 +60,14 @@ fn order_suggestions(matches: Vec) -> Vec<&[char]> { found.swap(0, 2); } + if let Some(noun_index) = found + .iter() + .skip(3) + .position(|i| i.metadata.is_proper_noun()) + { + found.swap(2, noun_index + 3); + } + // Make commonality relevant found.sort_by_key(|fmr| if fmr.metadata.common { 0 } else { 1 });