Class: Kotoshu::Dictionary::CSpell
- Defined in:
- lib/kotoshu/dictionary/cspell.rb
Overview
CSpell dictionary backend.
This dictionary reads CSpell-formatted dictionary files (plain text .txt or compressed .trie files). CSpell is the spell checker used by VS Code.
File format:
- .txt: Plain text with one word per line, # comments supported
- .trie: Compressed trie format (DAFSA - Deterministic Acyclic Finite State Automaton)
Instance Attribute Summary collapse
-
#case_sensitive ⇒ Boolean
readonly
Whether lookups are case-sensitive.
-
#path ⇒ String
readonly
The path to the dictionary file.
-
#trie ⇒ Core::Trie::Trie
readonly
The trie data structure.
Attributes inherited from Base
#language_code, #locale, #metadata
Class Method Summary collapse
-
.from_words(words, language_code:, locale: nil, case_sensitive: false) ⇒ CSpell
Create a dictionary from an array of words.
Instance Method Summary collapse
-
#add_word(word, flags: []) ⇒ Boolean
Add a word to the dictionary.
-
#has_prefix?(prefix) ⇒ Boolean
Check if the dictionary has words with a prefix.
-
#initialize(path = nil, language_code:, locale: nil, case_sensitive: false, metadata: {}, words: nil) ⇒ CSpell
constructor
Create a new CSpell dictionary.
-
#lookup(word) ⇒ Boolean
Check if a word exists in the dictionary.
-
#remove_word(_word) ⇒ Boolean
Remove a word from the dictionary.
-
#suggest(word, max_suggestions: 10) ⇒ Array<String>
Generate spelling suggestions.
-
#words ⇒ Array<String>
Get all words in the dictionary.
-
#words_with_prefix(prefix) ⇒ Array<String>
Get words with a prefix.
Methods inherited from Base
#<<, #all_words, #contains?, #each_word, #empty?, #has_word?, #include?, load, #lookup?, register_type, registry, #size, #to_s, #type, #words_matching
Constructor Details
#initialize(path = nil, language_code:, locale: nil, case_sensitive: false, metadata: {}, words: nil) ⇒ CSpell
Create a new CSpell dictionary.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 45 def initialize(path = nil, language_code:, locale: nil, case_sensitive: false, metadata: {}, words: nil) super(language_code, locale: locale, metadata: ) @path = path ? File.(path) : nil @case_sensitive = case_sensitive if words normalized = words.map { |w| case_sensitive ? w : w.downcase }.uniq @trie = Core::Trie::Builder.from_array(normalized) else raise DictionaryNotFoundError, @path unless File.exist?(@path) @trie = if @path.end_with?(".trie") load_trie_file(@path) else load_text_file(@path) end end # Register this dictionary type self.class.register_type(:cspell) unless Dictionary.registry.key?(:cspell) end |
Instance Attribute Details
#case_sensitive ⇒ Boolean (readonly)
Returns Whether lookups are case-sensitive.
25 26 27 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 25 def case_sensitive @case_sensitive end |
#path ⇒ String (readonly)
Returns The path to the dictionary file.
22 23 24 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 22 def path @path end |
#trie ⇒ Core::Trie::Trie (readonly)
Returns The trie data structure.
28 29 30 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 28 def trie @trie end |
Class Method Details
.from_words(words, language_code:, locale: nil, case_sensitive: false) ⇒ CSpell
Create a dictionary from an array of words.
181 182 183 184 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 181 def self.from_words(words, language_code:, locale: nil, case_sensitive: false) new(words: words, language_code: language_code, locale: locale, case_sensitive: case_sensitive) end |
Instance Method Details
#add_word(word, flags: []) ⇒ Boolean
Add a word to the dictionary.
138 139 140 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 138 def add_word(word, flags: []) false end |
#has_prefix?(prefix) ⇒ Boolean
Check if the dictionary has words with a prefix.
84 85 86 87 88 89 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 84 def has_prefix?(prefix) return false if prefix.nil? || prefix.empty? lookup_prefix = @case_sensitive ? prefix : prefix.downcase @trie.has_prefix?(lookup_prefix) end |
#lookup(word) ⇒ Boolean
Check if a word exists in the dictionary.
73 74 75 76 77 78 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 73 def lookup(word) return false if word.nil? || word.empty? lookup_word = @case_sensitive ? word : word.downcase @trie.lookup(lookup_word) end |
#remove_word(_word) ⇒ Boolean
CSpell dictionaries are typically immutable after loading
Remove a word from the dictionary.
147 148 149 150 151 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 147 def remove_word(_word) # Trie doesn't support removal easily # Would need to rebuild the trie false end |
#suggest(word, max_suggestions: 10) ⇒ Array<String>
Generate spelling suggestions.
Uses trie walk to find similar words.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 98 def suggest(word, max_suggestions: 10) return [] if word.nil? || word.empty? lookup_word = @case_sensitive ? word : word.downcase # First try prefix-based suggestions prefix_suggestions = @trie.suggestions(lookup_word, max_results: max_suggestions) # If we have enough prefix suggestions, return them return prefix_suggestions if prefix_suggestions.length >= max_suggestions # Otherwise, use edit distance for more suggestions all_words = @trie.all_words candidates = all_words.select do |w| w.length >= lookup_word.length - 2 && w.length <= lookup_word.length + 2 end # Calculate edit distances results = candidates.map do |dict_word| dist = edit_distance(lookup_word, dict_word) [dict_word, dist] end.select { |_, dist| dist.positive? && dist <= 2 } .sort_by { |_, dist| dist } .first(max_suggestions - prefix_suggestions.length) .map(&:first) # Combine both sets (prefix_suggestions + results).uniq.first(max_suggestions) end |
#words ⇒ Array<String>
Get all words in the dictionary.
156 157 158 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 156 def words @trie.all_words end |
#words_with_prefix(prefix) ⇒ Array<String>
Get words with a prefix.
164 165 166 167 168 169 |
# File 'lib/kotoshu/dictionary/cspell.rb', line 164 def words_with_prefix(prefix) return [] if prefix.nil? || prefix.empty? lookup_prefix = @case_sensitive ? prefix : prefix.downcase @trie.words_with_prefix(lookup_prefix) end |