From ab0682153dd63af6185c21ea4ef6e2f1230d25c3 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 29 Sep 2026 23:25:25 +0300 Subject: [PATCH] fix(spellcheck): Linux wordlist flags unknown words; only hunspell counts as CLI - check_word returned "valid" for a word missing from a loaded wordlist (!words.is_empty() && !contains, with contains already false), so the wordlist backend never flagged anything. - aspell on PATH counted as a CLI speller, but only hunspell is invoked, so on a machine with aspell and no hunspell every CLI check silently failed. - A bare wordlist offers no suggestions; the test no longer demands them from the linux_system backend. Unused PathBuf import dropped. Co-Authored-By: Claude Opus 5.5 --- src/app/control/p1_tests.rs | 6 ++++-- src/app/control/spellcheck.rs | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app/control/p1_tests.rs b/src/app/control/p1_tests.rs index 3ad5b8b6a..331142ce6 100644 --- a/src/app/control/p1_tests.rs +++ b/src/app/control/p1_tests.rs @@ -819,7 +819,9 @@ fn text_audit_system_spellcheck_flags_misspelled_words() { flagged ); - // At least one flagged word should have suggestions + // At least one flagged word should have suggestions — except from a + // bare Linux wordlist, which can tell a word is unknown but has no + // way to suggest one without the hunspell CLI. let has_suggestions = words.iter().any(|w| { w["suggestions"] .as_array() @@ -827,7 +829,7 @@ fn text_audit_system_spellcheck_flags_misspelled_words() { .unwrap_or(false) }); assert!( - has_suggestions, + has_suggestions || sp["backend"] == "linux_system", "expected at least one word to have suggestions" ); diff --git a/src/app/control/spellcheck.rs b/src/app/control/spellcheck.rs index 8ab3abb23..704a961be 100644 --- a/src/app/control/spellcheck.rs +++ b/src/app/control/spellcheck.rs @@ -595,7 +595,7 @@ pub(crate) mod linux_impl { use std::collections::HashSet; use std::fs::File; use std::io::{BufRead, BufReader}; - use std::path::{Path, PathBuf}; + use std::path::Path; const LINUX_DICT_DIRS: &[&str] = &[ "/usr/share/hunspell", @@ -645,7 +645,8 @@ pub(crate) mod linux_impl { } } - let has_cli = is_command_in_path("hunspell") || is_command_in_path("aspell"); + // Only hunspell is ever invoked (`check_via_cli`), so only it counts. + let has_cli = is_command_in_path("hunspell"); if !found_any && !has_cli { return None; @@ -683,7 +684,9 @@ pub(crate) mod linux_impl { } } - (!self.words.is_empty() && !self.words.contains(&clean), Vec::new()) + // Not in the wordlist and no CLI answer: misspelled when there is + // a wordlist to judge by, unjudged (accepted) when there is none. + (self.words.is_empty(), Vec::new()) } }