mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-03 08:50:02 -06:00
Merge origin/main
This commit is contained in:
@@ -98,18 +98,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Czech dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -233,4 +245,22 @@ mod tests {
|
||||
let opts = crate::Options { ignore_uppercase: false, ..Default::default() };
|
||||
assert!(!crate::is_correct_in_with("ZQZAKÁZANÉ", crate::ProofLang::Cs, &opts));
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Czech checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_czech_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::Cs;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("ŠKULA", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("ŠKULA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("ŠKOLA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("škula2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("škula2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("ŠKULA"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,18 +85,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Croatian dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -147,4 +159,22 @@ mod tests {
|
||||
fn missing_dictionary_is_silent() {
|
||||
assert!(is_correct_with(&AffixDict::default(), "nepostojećariječ"));
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Croatian checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_croatian_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::Hr;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("ŠKOLLA", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("ŠKOLLA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("ŠKOLA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("školla2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("školla2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("ŠKOLLA"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,18 +91,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Indonesian dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -113,7 +125,7 @@ pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
|| w.split('-').all(|p| {
|
||||
p.chars().count() <= 1
|
||||
|| CLITICS.iter().any(|c| p.eq_ignore_ascii_case(c))
|
||||
|| (p.chars().all(|c| !c.is_lowercase()) && p.chars().count() <= 6)
|
||||
|| (opts.ignore_uppercase && p.chars().all(|c| !c.is_lowercase()) && p.chars().count() <= 6)
|
||||
|| known(d, p)
|
||||
});
|
||||
}
|
||||
@@ -224,4 +236,24 @@ mod tests {
|
||||
let opts = crate::Options { ignore_uppercase: false, ..Default::default() };
|
||||
assert!(!crate::is_correct_in_with("ZQTERLARANG", crate::ProofLang::Id, &opts));
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Indonesian checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_indonesian_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::Id;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("RUMHA", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("RUMHA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("RUMAH", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("RUMHA-nya", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("RUMHA-nya", lang, &check_caps), "a part in capitals is checked too");
|
||||
assert!(crate::is_correct_in_with("rumha2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("rumha2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("RUMHA"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,18 +111,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Italian dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -229,4 +241,22 @@ mod tests {
|
||||
crate::add_word("Zxqitalianaparola");
|
||||
assert!(is_correct("zxqitalianaparola"));
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Italian checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_italian_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::It;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("LIBRRO", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("LIBRRO", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("LIBRO", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("librro2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("librro2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("LIBRRO"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,17 +774,17 @@ pub fn is_correct_in_with(word: &str, lang: ProofLang, opts: &Options) -> bool {
|
||||
let word = &*composed(word);
|
||||
match lang {
|
||||
ProofLang::En | ProofLang::EnGb | ProofLang::EnCa => is_correct_english(word, lang, opts),
|
||||
ProofLang::Pl => accepted_by_options(word, opts) || pl::is_correct(word),
|
||||
ProofLang::Hr => accepted_by_options(word, opts) || hr::is_correct(word),
|
||||
ProofLang::Pt => accepted_by_options(word, opts) || pt::is_correct(word),
|
||||
ProofLang::It => accepted_by_options(word, opts) || it::is_correct(word),
|
||||
ProofLang::Pl => accepted_by_options(word, opts) || pl::is_correct_with_options(word, opts),
|
||||
ProofLang::Hr => accepted_by_options(word, opts) || hr::is_correct_with_options(word, opts),
|
||||
ProofLang::Pt => accepted_by_options(word, opts) || pt::is_correct_with_options(word, opts),
|
||||
ProofLang::It => accepted_by_options(word, opts) || it::is_correct_with_options(word, opts),
|
||||
ProofLang::Tr => accepted_by_options(word, opts) || tr::is_correct(word),
|
||||
ProofLang::Ru => accepted_by_options(word, opts) || ru::is_correct(word),
|
||||
ProofLang::Cs => accepted_by_options(word, opts) || cs::is_correct(word),
|
||||
ProofLang::Id => accepted_by_options(word, opts) || id::is_correct(word),
|
||||
ProofLang::Es | ProofLang::EsMx | ProofLang::Es419 | ProofLang::EsUy => {
|
||||
accepted_by_options(word, opts) || es::is_correct_with_options(word, lang, opts)
|
||||
}
|
||||
ProofLang::Cs => accepted_by_options(word, opts) || cs::is_correct_with_options(word, opts),
|
||||
ProofLang::Id => accepted_by_options(word, opts) || id::is_correct_with_options(word, opts),
|
||||
ProofLang::Bg | ProofLang::De | ProofLang::Other => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,18 +96,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Polish dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -209,4 +221,22 @@ mod tests {
|
||||
crate::add_word("Zxqpolskisłowo");
|
||||
assert!(is_correct("zxqpolskisłowo"));
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Polish checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_polish_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::Pl;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("ŻEKA", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("ŻEKA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("RZEKA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("żeka2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("żeka2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("ŻEKA"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,18 +91,30 @@ pub fn is_correct(word: &str) -> bool {
|
||||
is_correct_with(&dictionary(), word)
|
||||
}
|
||||
|
||||
/// [`is_correct`] with the File › Options › Proofing choices: with Ignore words in UPPERCASE off,
|
||||
/// short words in capitals are checked against the dictionary too, and with Ignore words that
|
||||
/// contain numbers off, so are words with digits.
|
||||
pub fn is_correct_with_options(word: &str, opts: &crate::Options) -> bool {
|
||||
check(&dictionary(), word, opts)
|
||||
}
|
||||
|
||||
/// [`is_correct`] against a given dictionary (an empty one accepts everything).
|
||||
pub fn is_correct_with(d: &AffixDict, word: &str) -> bool {
|
||||
check(d, word, &crate::Options::default())
|
||||
}
|
||||
|
||||
/// [`is_correct_with_options`] against a given dictionary.
|
||||
fn check(d: &AffixDict, word: &str, opts: &crate::Options) -> bool {
|
||||
if d.is_empty() {
|
||||
return true; // no Portuguese dictionary installed: no spelling marks
|
||||
}
|
||||
let w = word.trim_matches(|c: char| !c.is_alphanumeric() && c != '\'' && c != '’');
|
||||
let w = w.trim_matches(['\'', '’']);
|
||||
let n = w.chars().count();
|
||||
if n <= 1 || w.chars().any(|c| c.is_ascii_digit()) || !w.chars().any(char::is_alphabetic) {
|
||||
if n <= 1 || (opts.ignore_numbers && w.chars().any(|c| c.is_ascii_digit())) || !w.chars().any(char::is_alphabetic) {
|
||||
return true;
|
||||
}
|
||||
if w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
if opts.ignore_uppercase && w.chars().all(|c| !c.is_lowercase()) && n <= 6 {
|
||||
return true;
|
||||
}
|
||||
if !w.chars().any(is_latin_letter) {
|
||||
@@ -217,4 +229,22 @@ mod tests {
|
||||
crate::add_word("Unigranrio-RJ");
|
||||
assert!(crate::check_spelling_in(text, crate::ProofLang::Pt).is_empty());
|
||||
}
|
||||
|
||||
/// With Ignore words in UPPERCASE or Ignore words that contain numbers off, Portuguese checks
|
||||
/// those words against the dictionary instead of accepting them.
|
||||
#[test]
|
||||
fn proofing_options_reach_the_portuguese_check() {
|
||||
test_dict::install();
|
||||
let lang = crate::ProofLang::Pt;
|
||||
let defaults = crate::Options::default();
|
||||
let check_caps = crate::Options { ignore_uppercase: false, ..defaults };
|
||||
let check_digits = crate::Options { ignore_numbers: false, ..defaults };
|
||||
assert!(crate::is_correct_in_with("PRAYA", lang, &defaults), "short capitals are acronyms by default");
|
||||
assert!(!crate::is_correct_in_with("PRAYA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("PRAIA", lang, &check_caps));
|
||||
assert!(crate::is_correct_in_with("praya2", lang, &defaults));
|
||||
assert!(!crate::is_correct_in_with("praya2", lang, &check_digits));
|
||||
assert!(crate::is_correct_in_with("2026", lang, &check_digits), "numbers alone stay correct");
|
||||
assert!(is_correct("PRAYA"), "direct checks keep the defaults");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user