Skip to content

Commit

Permalink
Better Go query and check uppercase and all cap words
Browse files Browse the repository at this point in the history
  • Loading branch information
blopker committed Jan 28, 2025
1 parent 2605fb7 commit e329e41
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 15 deletions.
13 changes: 11 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion codebook/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
lazy_static = "1.5.0"
regex = "1.11.1"
spellbook = "0.2.0"
spellbook = { git = "https://github.com/helix-editor/spellbook.git#b6c31ea" }
tree-sitter = "<0.25.0"
tree-sitter-css = "<0.25.0"
tree-sitter-rust = "<0.25.0"
Expand Down
69 changes: 66 additions & 3 deletions codebook/src/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ pub struct TextRange {
pub end_line: u32,
}

enum WordCase {
AllCaps,
AllLower,
TitleCase,
Unknown,
}

#[derive(Debug)]
pub struct CodeDictionary {
custom_dictionary: Arc<RwLock<HashSet<String>>>,
Expand Down Expand Up @@ -74,7 +81,26 @@ impl CodeDictionary {
if self.config.is_allowed_word(&lower_word) {
return true;
}
self.dictionary.check(word)
if self.dictionary.check(word) {
return true;
}
if self
.dictionary
.checker()
.check_lower_as_title(true)
.check(word)
{
return true;
}
if self
.dictionary
.checker()
.check_lower_as_upper(true)
.check(word)
{
return true;
}
false
}

pub fn add_to_dictionary(&self, strings: &str) {
Expand All @@ -99,6 +125,24 @@ impl CodeDictionary {
self.dictionary.suggest(word, &mut suggestions);
suggestions.truncate(5);
if !suggestions.is_empty() {
let word_case = self.get_word_case(&word);
// mutate suggestions in place to match case

for suggestion in &mut suggestions {
match word_case {
WordCase::AllCaps => {
suggestion.make_ascii_uppercase();
}
WordCase::AllLower => {
suggestion.make_ascii_lowercase();
}
WordCase::TitleCase => {
// Leave it alone if it's a title case
}
WordCase::Unknown => {}
}
}

self.suggestion_cache
.write()
.unwrap()
Expand All @@ -107,6 +151,19 @@ impl CodeDictionary {
suggestions
}

fn get_word_case(&self, word: &str) -> WordCase {
if word.chars().all(char::is_uppercase) {
return WordCase::AllCaps;
}
if word.chars().all(char::is_lowercase) {
return WordCase::AllLower;
}
if word.chars().next().unwrap().is_uppercase() {
return WordCase::TitleCase;
}
WordCase::Unknown
}

pub fn spell_check(
&self,
text: &str,
Expand Down Expand Up @@ -328,7 +385,6 @@ mod dictionary_tests {
#[test]
fn test_spell_checking() {
let processor = get_dict();

let text = "HelloWorld calc_wrld";
let misspelled = processor.spell_check_type(text, LanguageType::Text);
println!("{:?}", misspelled);
Expand Down Expand Up @@ -413,8 +469,15 @@ mod dictionary_tests {
let suggestions = dict.suggest("wrld");
println!("{:?}", suggestions);
assert!(suggestions.contains(&"world".to_string()));
}

#[test]
fn test_ignore_case() {
let dict = get_dict();
let check = dict.check("alice");
assert!(check);
let suggestions = dict.suggest("alice");
println!("{:?}", suggestions);
assert!(suggestions.contains(&"Alice".to_string()));
assert!(suggestions.contains(&"alice".to_string()));
}
}
4 changes: 4 additions & 0 deletions codebook/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ pub static LANGUAGE_SETTINGS: &[LanguageSetting] = &[
(argument_list (interpreted_string_literal) @string)
(function_declaration (identifier) @identifier)
(raw_string_literal) @raw_string
(expression_list
(interpreted_string_literal) @string
)
(var_spec (identifier) @identifier)
"#,
extensions: &["go"],
},
Expand Down
41 changes: 34 additions & 7 deletions codebook/tests/test_go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,65 @@ mod utils;

#[test]
fn test_go_location() {
utils::init_logging();
let sample_text = r#"
import (
"fmt"
)
func mispeledFuncion() string {
return ""
var alicz = "Alizzz"
return alicz
}"#;
let expected = vec![
SpellCheckResult::new(
"mispeled".to_string(),
vec![TextRange {
start_char: 9,
end_char: 17,
start_line: 1,
end_line: 1,
start_line: 4,
end_line: 4,
}],
),
SpellCheckResult::new(
"Funcion".to_string(),
vec![TextRange {
start_char: 17,
end_char: 24,
start_line: 1,
end_line: 1,
start_line: 4,
end_line: 4,
}],
),
SpellCheckResult::new(
"Alizzz".to_string(),
vec![TextRange {
start_char: 21,
end_char: 27,
start_line: 5,
end_line: 5,
}],
),
SpellCheckResult::new(
"alicz".to_string(),
vec![TextRange {
start_char: 12,
end_char: 17,
start_line: 5,
end_line: 5,
}],
),
];
let not_expected = ["fmt"];
let processor = utils::get_processor();
let misspelled = processor
.spell_check(sample_text, Some(LanguageType::Text), None)
.spell_check(sample_text, Some(LanguageType::Go), None)
.to_vec();
println!("Misspelled words: {misspelled:?}");
for e in &expected {
let miss = misspelled.iter().find(|r| r.word == e.word).unwrap();
println!("Expecting: {e:?}");
let miss = misspelled.iter().find(|r| r.word == e.word).unwrap();
assert_eq!(miss.locations, e.locations);
}
for result in misspelled {
assert!(!not_expected.contains(&result.word.as_str()));
}
}
6 changes: 4 additions & 2 deletions examples/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import (
func main() {
// I'm bad at speling alice
fmt.Println("Hello, Wolrd!")
var alice = "Alice"
fmt.Println("Hello, " + alice)
var alicz = "Alicz"
fmt.Println("Hello, " + alicz)
var rsvp = "RSVP"
fmt.Println("Hello, " + rsvp)
}

func mispeledFuncion() string {
Expand Down

0 comments on commit e329e41

Please sign in to comment.