Class: Kotoshu::Suggestions::Strategies::KeyboardProximityStrategy

Inherits:
BaseStrategy
  • Object
show all
Defined in:
lib/kotoshu/suggestions/strategies/keyboard_proximity_strategy.rb

Overview

Keyboard proximity suggestion strategy.

Generates suggestions by finding words that can be formed by substituting adjacent keys on a QWERTY keyboard.

Examples:

Creating a keyboard proximity strategy

strategy = KeyboardProximityStrategy.new
result = strategy.generate(context)

Constant Summary collapse

KEYBOARD_LAYOUT =

QWERTY keyboard layout (US).

Each key maps to its adjacent keys.

{
  "`" => %w[1 tab],
  "1" => ["`", "2", "q"],
  "2" => %w[1 3 w q],
  "3" => %w[2 4 e w],
  "4" => %w[3 5 r e],
  "5" => %w[4 6 t r],
  "6" => %w[5 7 y t],
  "7" => %w[6 8 u y],
  "8" => %w[7 9 i u],
  "9" => %w[8 0 o i],
  "0" => %w[9 p o],
  "-" => ["0", "="],
  "=" => ["-"],
  "q" => %w[tab w a 1],
  "w" => %w[q e a s 2],
  "e" => %w[w r s d 3],
  "r" => %w[e t d f 4],
  "t" => %w[r y f g 5],
  "y" => %w[t u g h 6],
  "u" => %w[y i h j 7],
  "i" => %w[u o j k 8],
  "o" => %w[i p k l 9],
  "p" => ["o", "l", ";", "0"],
  "[" => ["p", "'"],
  "]" => ["enter", "\\"],
  "\\" => ["enter"], # Backslash neighbors
  "a" => %w[caps s z q],
  "s" => %w[a d z x w],
  "d" => %w[s f x c e],
  "f" => %w[d g c v r],
  "g" => %w[f h v b t],
  "h" => %w[g j b n y],
  "j" => %w[h k n m u],
  "k" => ["j", "l", "m", ",", "i"],
  "l" => ["k", ";", ",", ".", "o"],
  ";" => ["l", "'", ".", "p"],
  "'" => [";"],
  "z" => %w[shift s x a],
  "x" => %w[z c s d],
  "c" => %w[x v d f],
  "v" => %w[c b f g],
  "b" => %w[v n g h],
  "n" => %w[b m h j],
  "m" => ["n", ",", "j", "k"],
  "," => ["m", ".", "k", "l"],
  "." => [",", "/", "l", ";"],
  "/" => [".", "shift"],
  " " => [] # Space has no neighbors
}.freeze

Instance Attribute Summary

Attributes inherited from BaseStrategy

#config, #name

Instance Method Summary collapse

Methods inherited from BaseStrategy

#calculate_ngram_similarity, #create_suggestion, #create_suggestion_set, #enabled?, #generate_ngrams, #get_config, #has_config?, #max_results, #priority, #to_s

Constructor Details

#initialize(name: :keyboard_proximity, **config) ⇒ KeyboardProximityStrategy

Create a new keyboard proximity strategy.

Parameters:

  • name (String, Symbol) (defaults to: :keyboard_proximity)

    Name of the strategy

  • config (Hash)

    Configuration options

Options Hash (**config):

  • max_distance (Integer)

    Maximum keyboard distance

  • max_results (Integer)

    Maximum results to return



75
76
77
# File 'lib/kotoshu/suggestions/strategies/keyboard_proximity_strategy.rb', line 75

def initialize(name: :keyboard_proximity, **config)
  super(name: name, **config)
end

Instance Method Details

#generate(context) ⇒ SuggestionSet

Generate suggestions based on keyboard proximity.

Parameters:

  • context (Context)

    The suggestion context

Returns:



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/kotoshu/suggestions/strategies/keyboard_proximity_strategy.rb', line 83

def generate(context)
  word = context.word
  max_dist = get_config(:max_distance, 2)
  min_similarity = get_config(:min_similarity, 0.70)  # Filter low-similarity suggestions

  all_words = dictionary_words(context)

  # Generate keyboard variants
  variants = keyboard_variants(word, max_dist)

  # Find matching dictionary words with their edit distances and similarity
  results_with_distances = {}
  variants.each do |variant|
    dict_word = find_word(all_words, variant)
    next unless dict_word && dict_word != word

    # Calculate edit distance from original word
    dist = edit_distance(word, dict_word)
    next if dist > max_dist

    # Calculate typo correction similarity
    similarity = calculate_ngram_similarity(word, dict_word)
    next if similarity < min_similarity  # Filter by similarity threshold

    # Keep the minimum distance for each word
    results_with_distances[dict_word] ||= dist
    results_with_distances[dict_word] = dist if dist < results_with_distances[dict_word]
  end

  # Sort by distance and create suggestions
  sorted_words = results_with_distances.sort_by { |_, dist| dist }.map(&:first)
  create_suggestion_set(sorted_words, distances: results_with_distances, original_word: word)
end

#handles?(context) ⇒ Boolean

Check if this strategy should handle the context.

Parameters:

  • context (Context)

    The suggestion context

Returns:

  • (Boolean)

    True if the word needs correction



121
122
123
124
125
# File 'lib/kotoshu/suggestions/strategies/keyboard_proximity_strategy.rb', line 121

def handles?(context)
  return false unless enabled?

  !dictionary_lookup(context, context.word)
end