Module: Rvim::Spell
- Defined in:
- lib/rvim/spell.rb
Constant Summary collapse
- DEFAULT_DICT_PATHS =
[ '/usr/share/dict/words', '/usr/share/dict/american-english', '/usr/share/dict/british-english', ].freeze
Class Attribute Summary collapse
Class Method Summary collapse
- .add_bad(word) ⇒ Object
- .add_good(word) ⇒ Object
- .cache_dir ⇒ Object
- .distance(a, b) ⇒ Object
- .load_dictionary(paths = DEFAULT_DICT_PATHS) ⇒ Object
- .load_user_set(filename) ⇒ Object
- .misspelled?(word) ⇒ Boolean
- .persist(filename, words) ⇒ Object
- .reset! ⇒ Object
- .suggest(word, n: 5, max_dist: 3) ⇒ Object
Class Attribute Details
.bad_set ⇒ Object
25 26 27 |
# File 'lib/rvim/spell.rb', line 25 def bad_set @bad_set ||= load_user_set('bad.txt') end |
.dict ⇒ Object
17 18 19 |
# File 'lib/rvim/spell.rb', line 17 def dict @dict ||= load_dictionary end |
.good_set ⇒ Object
21 22 23 |
# File 'lib/rvim/spell.rb', line 21 def good_set @good_set ||= load_user_set('good.txt') end |
Class Method Details
.add_bad(word) ⇒ Object
62 63 64 65 66 |
# File 'lib/rvim/spell.rb', line 62 def add_bad(word) bad_set << word.downcase good_set.delete(word.downcase) persist('bad.txt', bad_set) end |
.add_good(word) ⇒ Object
56 57 58 59 60 |
# File 'lib/rvim/spell.rb', line 56 def add_good(word) good_set << word.downcase bad_set.delete(word.downcase) persist('good.txt', good_set) end |
.cache_dir ⇒ Object
100 101 102 103 104 |
# File 'lib/rvim/spell.rb', line 100 def cache_dir base = ENV['XDG_CACHE_HOME'] base = File.('~/.cache') if base.nil? || base.empty? File.join(base, 'rvim', 'spell') end |
.distance(a, b) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rvim/spell.rb', line 81 def distance(a, b) m = a.length n = b.length return n if m.zero? return m if n.zero? prev = (0..n).to_a cur = Array.new(n + 1, 0) (1..m).each do |i| cur[0] = i (1..n).each do |j| cost = a[i - 1] == b[j - 1] ? 0 : 1 cur[j] = [cur[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost].min end prev, cur = cur, prev end prev[n] end |
.load_dictionary(paths = DEFAULT_DICT_PATHS) ⇒ Object
29 30 31 32 33 34 35 36 37 |
# File 'lib/rvim/spell.rb', line 29 def load_dictionary(paths = DEFAULT_DICT_PATHS) paths.each do |p| next unless File.exist?(p) words = File.foreach(p).map { |l| l.chomp.downcase } return words.to_set end Set.new end |
.load_user_set(filename) ⇒ Object
106 107 108 109 110 111 112 113 |
# File 'lib/rvim/spell.rb', line 106 def load_user_set(filename) path = File.join(cache_dir, filename) return Set.new unless File.exist?(path) File.foreach(path).each_with_object(Set.new) { |l, s| s << l.chomp.downcase } rescue Set.new end |
.misspelled?(word) ⇒ Boolean
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rvim/spell.rb', line 45 def misspelled?(word) return false if word.nil? || word.empty? return false unless word.match?(/\A[A-Za-z]/) w = word.downcase return true if bad_set.include?(w) return false if good_set.include?(w) !dict.include?(w) end |
.persist(filename, words) ⇒ Object
115 116 117 118 119 120 |
# File 'lib/rvim/spell.rb', line 115 def persist(filename, words) FileUtils.mkdir_p(cache_dir) File.write(File.join(cache_dir, filename), words.to_a.sort.join("\n")) rescue nil end |
.reset! ⇒ Object
39 40 41 42 43 |
# File 'lib/rvim/spell.rb', line 39 def reset! @dict = nil @good_set = nil @bad_set = nil end |
.suggest(word, n: 5, max_dist: 3) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/rvim/spell.rb', line 68 def suggest(word, n: 5, max_dist: 3) w = word.downcase scored = [] dict.each do |entry| delta = (entry.length - w.length).abs next if delta > max_dist d = distance(w, entry) scored << [d, entry] if d <= max_dist end scored.sort.first(n).map { |_, e| e } end |