From 66df18c55e929de4d133cd9e71807a70de392ec0 Mon Sep 17 00:00:00 2001 From: Yuki Nishijima Date: Fri, 22 Oct 2021 21:00:23 -0400 Subject: Sync did_you_mean again --- lib/did_you_mean.rb | 12 ++--- lib/did_you_mean/formatter.rb | 35 +++++++++++++++ lib/did_you_mean/formatters/plain_formatter.rb | 35 ++------------- lib/did_you_mean/formatters/verbose_formatter.rb | 52 +++------------------- lib/did_you_mean/spell_checker.rb | 18 ++++---- .../spell_checkers/pattern_key_name_checker.rb | 20 +++++++++ lib/did_you_mean/verbose.rb | 6 +-- 7 files changed, 82 insertions(+), 96 deletions(-) create mode 100644 lib/did_you_mean/formatter.rb create mode 100644 lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb (limited to 'lib') diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb index ab7e6b01a8..6a680fe975 100644 --- a/lib/did_you_mean.rb +++ b/lib/did_you_mean.rb @@ -7,7 +7,8 @@ require_relative 'did_you_mean/spell_checkers/method_name_checker' require_relative 'did_you_mean/spell_checkers/key_error_checker' require_relative 'did_you_mean/spell_checkers/null_checker' require_relative 'did_you_mean/spell_checkers/require_path_checker' -require_relative 'did_you_mean/formatters/plain_formatter' +require_relative 'did_you_mean/spell_checkers/pattern_key_name_checker' +require_relative 'did_you_mean/formatter' require_relative 'did_you_mean/tree_spell_checker' # The +DidYouMean+ gem adds functionality to suggest possible method/class @@ -97,16 +98,17 @@ module DidYouMean correct_error KeyError, KeyErrorChecker correct_error NoMethodError, MethodNameChecker correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0' + correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError) # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+. def self.formatter - @@formatter + @formatter end # Updates the primary formatter used to format the suggestions. - def self.formatter=(formatter) - @@formatter = formatter + def self.formatter=(*) + @formatter = formatter end - self.formatter = PlainFormatter.new + @formatter = Formatter.new end diff --git a/lib/did_you_mean/formatter.rb b/lib/did_you_mean/formatter.rb new file mode 100644 index 0000000000..01eb59100a --- /dev/null +++ b/lib/did_you_mean/formatter.rb @@ -0,0 +1,35 @@ +# frozen-string-literal: true + +module DidYouMean + # The +DidYouMean::Formatter+ is the basic, default formatter for the + # gem. The formatter responds to the +message_for+ method and it returns a + # human readable string. + class Formatter + + # Returns a human readable string that contains +corrections+. This + # formatter is designed to be less verbose to not take too much screen + # space while being helpful enough to the user. + # + # @example + # + # formatter = DidYouMean::Formatter.new + # + # # displays suggestions in two lines with the leading empty line + # puts formatter.message_for(["methods", "method"]) + # + # Did you mean? methods + # method + # # => nil + # + # # displays an empty line + # puts formatter.message_for([]) + # + # # => nil + # + def message_for(corrections) + corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" + end + end + + PlainFormatter = Formatter +end diff --git a/lib/did_you_mean/formatters/plain_formatter.rb b/lib/did_you_mean/formatters/plain_formatter.rb index e2d995f587..d669588e0f 100644 --- a/lib/did_you_mean/formatters/plain_formatter.rb +++ b/lib/did_you_mean/formatters/plain_formatter.rb @@ -1,33 +1,4 @@ -# frozen-string-literal: true +require_relative '../formatter' -module DidYouMean - # The +DidYouMean::PlainFormatter+ is the basic, default formatter for the - # gem. The formatter responds to the +message_for+ method and it returns a - # human readable string. - class PlainFormatter - - # Returns a human readable string that contains +corrections+. This - # formatter is designed to be less verbose to not take too much screen - # space while being helpful enough to the user. - # - # @example - # - # formatter = DidYouMean::PlainFormatter.new - # - # # displays suggestions in two lines with the leading empty line - # puts formatter.message_for(["methods", "method"]) - # - # Did you mean? methods - # method - # # => nil - # - # # displays an empty line - # puts formatter.message_for([]) - # - # # => nil - # - def message_for(corrections) - corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}" - end - end -end +warn "`require 'did_you_mean/formatters/plain_formatter'` is deprecated. Please `require 'did_you_mean/formatter'` " \ + "instead." diff --git a/lib/did_you_mean/formatters/verbose_formatter.rb b/lib/did_you_mean/formatters/verbose_formatter.rb index b8fe214d57..8ee98fa070 100644 --- a/lib/did_you_mean/formatters/verbose_formatter.rb +++ b/lib/did_you_mean/formatters/verbose_formatter.rb @@ -1,49 +1,9 @@ -# frozen-string-literal: true - -module DidYouMean - # The +DidYouMean::VerboseFormatter+ uses extra empty lines to make the - # suggestion stand out more in the error message. - # - # In order to activate the verbose formatter, - # - # @example - # - # OBject - # # => NameError: uninitialized constant OBject - # # Did you mean? Object - # - # require 'did_you_mean/verbose' - # - # OBject - # # => NameError: uninitialized constant OBject - # # - # # Did you mean? Object - # # - # - class VerboseFormatter +warn "`require 'did_you_mean/formatters/verbose_formatter'` is deprecated and falls back to the default formatter. " - # Returns a human readable string that contains +corrections+. This - # formatter is designed to be less verbose to not take too much screen - # space while being helpful enough to the user. - # - # @example - # - # formatter = DidYouMean::PlainFormatter.new - # - # puts formatter.message_for(["methods", "method"]) - # - # - # Did you mean? methods - # method - # - # # => nil - # - def message_for(corrections) - return "" if corrections.empty? +require_relative '../formatter' - output = "\n\n Did you mean? ".dup - output << corrections.join("\n ") - output << "\n " - end - end +# frozen-string-literal: true +module DidYouMean + # For compatibility: + VerboseFormatter = Formatter end diff --git a/lib/did_you_mean/spell_checker.rb b/lib/did_you_mean/spell_checker.rb index e5106abba2..37da2fc7a6 100644 --- a/lib/did_you_mean/spell_checker.rb +++ b/lib/did_you_mean/spell_checker.rb @@ -10,25 +10,25 @@ module DidYouMean end def correct(input) - input = normalize(input) - threshold = input.length > 3 ? 0.834 : 0.77 + normalized_input = normalize(input) + threshold = normalized_input.length > 3 ? 0.834 : 0.77 - words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), input) >= threshold } - words.reject! { |word| input == word.to_s } - words.sort_by! { |word| JaroWinkler.distance(word.to_s, input) } + words = @dictionary.select { |word| JaroWinkler.distance(normalize(word), normalized_input) >= threshold } + words.reject! { |word| input.to_s == word.to_s } + words.sort_by! { |word| JaroWinkler.distance(word.to_s, normalized_input) } words.reverse! # Correct mistypes - threshold = (input.length * 0.25).ceil - corrections = words.select { |c| Levenshtein.distance(normalize(c), input) <= threshold } + threshold = (normalized_input.length * 0.25).ceil + corrections = words.select { |c| Levenshtein.distance(normalize(c), normalized_input) <= threshold } # Correct misspells if corrections.empty? corrections = words.select do |word| word = normalize(word) - length = input.length < word.length ? input.length : word.length + length = normalized_input.length < word.length ? normalized_input.length : word.length - Levenshtein.distance(word, input) < length + Levenshtein.distance(word, normalized_input) < length end.first(1) end diff --git a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb new file mode 100644 index 0000000000..ed263c8f93 --- /dev/null +++ b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb @@ -0,0 +1,20 @@ +require_relative "../spell_checker" + +module DidYouMean + class PatternKeyNameChecker + def initialize(no_matching_pattern_key_error) + @key = no_matching_pattern_key_error.key + @keys = no_matching_pattern_key_error.matchee.keys + end + + def corrections + @corrections ||= exact_matches.empty? ? SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect) : exact_matches + end + + private + + def exact_matches + @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect) + end + end +end diff --git a/lib/did_you_mean/verbose.rb b/lib/did_you_mean/verbose.rb index 4e86f167ea..1ff19aef80 100644 --- a/lib/did_you_mean/verbose.rb +++ b/lib/did_you_mean/verbose.rb @@ -1,4 +1,2 @@ -require_relative '../did_you_mean' -require_relative 'formatters/verbose_formatter' - -DidYouMean.formatter = DidYouMean::VerboseFormatter.new +warn "The verbose formatter has been removed and now `require 'did_you_mean/verbose'` has no effect. Please " \ + "remove this call." -- cgit v1.2.3