did_you_mean-1.2.0/ 0000755 0000041 0000041 00000000000 13221505156 014176 5 ustar www-data www-data did_you_mean-1.2.0/Rakefile 0000644 0000041 0000041 00000002220 13221505156 015637 0 ustar www-data www-data require 'bundler/gem_tasks'
require 'rake/testtask'
Rake::TestTask.new do |task|
task.libs << "test"
task.test_files = Dir['test/**/*_test.rb'].reject {|path| /(experimental)/ =~ path }
task.verbose = true
task.warning = true
end
Rake::TestTask.new("test:experimental") do |task|
task.libs << "test"
task.pattern = 'test/experimental/**/*_test.rb'
task.verbose = true
task.warning = true
task.ruby_opts << "-rdid_you_mean/experimental"
end
task default: %i(test test:experimental)
namespace :test do
namespace :accuracy do
desc "Download Wiktionary's Simple English data and save it as a dictionary"
task :prepare do
sh 'ruby evaluation/dictionary_generator.rb'
end
end
desc "Calculate accuracy of the gems' spell checker"
task :accuracy do
if !File.exist?("evaluation/dictionary.yml")
puts 'Generating dictionary for evaluation:'
Rake::Task["test:accuracy:prepare"].execute
puts "\n"
end
sh 'ruby evaluation/calculator.rb'
end
end
namespace :benchmark do
desc "Measure memory usage by the did_you_mean gem"
task :memory do
sh 'ruby benchmark/memory_usage.rb'
end
end
did_you_mean-1.2.0/Gemfile 0000644 0000041 0000041 00000000253 13221505156 015471 0 ustar www-data www-data source 'https://rubygems.org'
# Specify your gem's dependencies in did_you_mean.gemspec
gemspec
gem 'benchmark-ips'
gem 'memory_profiler'
gem 'jaro_winkler', '>= 1.4.0'
did_you_mean-1.2.0/doc/ 0000755 0000041 0000041 00000000000 13221505156 014743 5 ustar www-data www-data did_you_mean-1.2.0/doc/CHANGELOG.md.erb 0000644 0000041 0000041 00000000346 13221505156 017326 0 ustar www-data www-data <% releases.each do |release| %>
## [<%= release.name %>](https://github.com/<%= repository %>/tree/<%= release.tag_name %>)
_released at <%= release.published_at %>_
<%= release.body.gsub(/\r\n/, "\n") %>
<% end %>
did_you_mean-1.2.0/doc/changelog_generator.rb 0000644 0000041 0000041 00000001562 13221505156 021271 0 ustar www-data www-data require 'octokit'
require 'reverse_markdown'
require 'erb'
class ChangeLogGenerator
attr :repository, :template_path, :changelog_path
def initialize(repository, template_path: "CHANGELOG.md.erb", changelog_path: "CHANGELOG.md")
@repository = repository
@template_path = template_path
@changelog_path = changelog_path
end
def generate_and_save!
changelog_in_md = ERB.new(template).result(binding)
changelog_in_html = Octokit.markdown(changelog_in_md, context: repository, mode: "gfm")
File.open(changelog_path, 'w') do |file|
file.write ReverseMarkdown.convert(changelog_in_html, github_flavored: true)
end
end
private
def template
open("#{__dir__}/#{template_path}").read
end
def releases
@releases ||= Octokit.releases(repository)
end
end
ChangeLogGenerator.new("yuki24/did_you_mean").generate_and_save!
did_you_mean-1.2.0/.ruby-version 0000644 0000041 0000041 00000000012 13221505156 016634 0 ustar www-data www-data 2.5.0-dev
did_you_mean-1.2.0/LICENSE.txt 0000644 0000041 0000041 00000002064 13221505156 016023 0 ustar www-data www-data Copyright (c) 2014-2016 Yuki Nishijima
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
did_you_mean-1.2.0/.travis.yml 0000644 0000041 0000041 00000000342 13221505156 016306 0 ustar www-data www-data language: ruby
script: bundle exec rake
cache: bundler
sudo: false
before_install:
- gem install bundler
after_success:
- bundle exec rake test:accuracy
- bundle exec rake benchmark:memory
rvm:
- ruby-head
did_you_mean-1.2.0/benchmark/ 0000755 0000041 0000041 00000000000 13221505156 016130 5 ustar www-data www-data did_you_mean-1.2.0/benchmark/memory_usage.rb 0000644 0000041 0000041 00000000632 13221505156 021152 0 ustar www-data www-data # frozen-string-literal: true
require 'memory_profiler'
require 'did_you_mean'
# public def foo; end
# error = (self.fooo rescue $!)
# executable = -> { error.to_s }
METHODS = ''.methods
INPUT = 'start_with?'
collection = DidYouMean::SpellChecker.new(dictionary: METHODS)
executable = proc { collection.correct(INPUT) }
GC.disable
MemoryProfiler.report { 100.times(&executable) }.pretty_print
did_you_mean-1.2.0/benchmark/jaro_winkler/ 0000755 0000041 0000041 00000000000 13221505156 020616 5 ustar www-data www-data did_you_mean-1.2.0/benchmark/jaro_winkler/memory_usage.rb 0000644 0000041 0000041 00000000352 13221505156 023637 0 ustar www-data www-data require 'memory_profiler'
require 'did_you_mean/jaro_winkler'
str1, str2 = "user_signed_in?", "user_logged_in?"
report = MemoryProfiler.report do
80.times do
DidYouMean::Jaro.distance str1, str2
end
end
report.pretty_print
did_you_mean-1.2.0/benchmark/jaro_winkler/speed.rb 0000644 0000041 0000041 00000000444 13221505156 022245 0 ustar www-data www-data require 'benchmark/ips'
require 'did_you_mean'
Benchmark.ips do |x|
x.report "before" do
DidYouMean::Jaro.before_distance "user_signed_in?", "user_logged_in?"
end
x.report "after" do
DidYouMean::Jaro.after_distance "user_signed_in?", "user_logged_in?"
end
x.compare!
end
did_you_mean-1.2.0/benchmark/levenshtein/ 0000755 0000041 0000041 00000000000 13221505156 020454 5 ustar www-data www-data did_you_mean-1.2.0/benchmark/levenshtein/memory_usage.rb 0000644 0000041 0000041 00000000360 13221505156 023474 0 ustar www-data www-data require 'memory_profiler'
require 'did_you_mean/levenshtein'
str1, str2 = "user_signed_in?", "user_logged_in?"
report = MemoryProfiler.report do
80.times do
DidYouMean::Levenshtein.distance str1, str2
end
end
report.pretty_print
did_you_mean-1.2.0/benchmark/levenshtein/speed.rb 0000644 0000041 0000041 00000000530 13221505156 022077 0 ustar www-data www-data require 'benchmark/ips'
require 'did_you_mean'
require 'did_you_mean/levenshtein'
STR1, STR2 = "user_signed_in?", "user_logged_in?"
Benchmark.ips do |x|
x.report "enumerable" do
DidYouMean::Levenshtein.before_distance STR1, STR2
end
x.report "while" do
DidYouMean::Levenshtein.after_distance STR1, STR2
end
x.compare!
end
did_you_mean-1.2.0/lib/ 0000755 0000041 0000041 00000000000 13221505156 014744 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/ 0000755 0000041 0000041 00000000000 13221505156 017400 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/verbose.rb 0000644 0000041 0000041 00000000204 13221505156 021366 0 ustar www-data www-data require 'did_you_mean'
require 'did_you_mean/formatters/verbose_formatter'
DidYouMean.formatter = DidYouMean::VerboseFormatter.new
did_you_mean-1.2.0/lib/did_you_mean/core_ext/ 0000755 0000041 0000041 00000000000 13221505156 021210 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/core_ext/name_error.rb 0000644 0000041 0000041 00000000763 13221505156 023674 0 ustar www-data www-data module DidYouMean
module Correctable
def original_message
method(:to_s).super_method.call
end
def to_s
msg = super.dup
if !cause.respond_to?(:corrections) || cause.corrections.empty?
msg << DidYouMean.formatter.message_for(corrections)
end
msg
rescue
super
end
def corrections
spell_checker.corrections
end
def spell_checker
@spell_checker ||= SPELL_CHECKERS[self.class.to_s].new(self)
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checker.rb 0000644 0000041 0000041 00000002454 13221505156 022535 0 ustar www-data www-data # frozen-string-literal: true
require "did_you_mean/levenshtein"
require "did_you_mean/jaro_winkler"
module DidYouMean
class SpellChecker
def initialize(dictionary: )
@dictionary = dictionary
end
def correct(input)
input = normalize(input)
threshold = 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.reverse!
# Correct mistypes
threshold = (input.length * 0.25).ceil
corrections = words.select {|c| Levenshtein.distance(normalize(c), input) <= threshold }
# Correct misspells
if corrections.empty?
corrections = words.select do |word|
word = normalize(word)
length = input.length < word.length ? input.length : word.length
Levenshtein.distance(word, input) < length
end.first(1)
end
corrections
end
private
def normalize(str_or_symbol) #:nodoc:
str = if str_or_symbol.is_a?(String)
str_or_symbol.dup
else
str_or_symbol.to_s
end
str.downcase!
str.tr!("@", "")
str
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/experimental/ 0000755 0000041 0000041 00000000000 13221505156 022075 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/experimental/initializer_name_correction.rb 0000644 0000041 0000041 00000000724 13221505156 030177 0 ustar www-data www-data # frozen-string-literal: true
require 'did_you_mean/levenshtein'
module DidYouMean
module Experimental
module InitializerNameCorrection
def method_added(name)
super
distance = Levenshtein.distance(name.to_s, 'initialize')
if distance != 0 && distance <= 2
warn "warning: #{name} might be misspelled, perhaps you meant initialize?"
end
end
end
::Class.prepend(InitializerNameCorrection)
end
end
did_you_mean-1.2.0/lib/did_you_mean/experimental/ivar_name_correction.rb 0000644 0000041 0000041 00000004016 13221505156 026613 0 ustar www-data www-data # frozen-string-literal: true
require 'did_you_mean'
module DidYouMean
module Experimental #:nodoc:
class IvarNameCheckerBuilder #:nodoc:
attr_reader :original_checker
def initialize(original_checker) #:nodoc:
@original_checker = original_checker
end
def new(no_method_error) #:nodoc:
IvarNameChecker.new(no_method_error, original_checker: @original_checker)
end
end
class IvarNameChecker #:nodoc:
REPLS = {
"(irb)" => -> { Readline::HISTORY.to_a.last }
}
TRACE = TracePoint.trace(:raise) do |tp|
e = tp.raised_exception
if SPELL_CHECKERS.include?(e.class.to_s) && !e.instance_variable_defined?(:@frame_binding)
e.instance_variable_set(:@frame_binding, tp.binding)
end
end
attr_reader :original_checker
def initialize(no_method_error, original_checker: )
@original_checker = original_checker.new(no_method_error)
@location = no_method_error.backtrace_locations.first
@ivar_names = no_method_error.frame_binding.receiver.instance_variables
end
def corrections
original_checker.corrections + ivar_name_corrections
end
def ivar_name_corrections
@ivar_name_corrections ||= SpellChecker.new(dictionary: @ivar_names).correct(receiver_name.to_s)
end
private
def receiver_name
return unless @original_checker.receiver.nil?
abs_path = @location.absolute_path
lineno = @location.lineno
/@(\w+)*\.#{@original_checker.method_name}/ =~ line(abs_path, lineno).to_s && $1
end
def line(abs_path, lineno)
if REPLS[abs_path]
REPLS[abs_path].call
elsif File.exist?(abs_path)
File.open(abs_path) do |file|
file.detect { file.lineno == lineno }
end
end
end
end
end
NameError.send(:attr, :frame_binding)
SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameCheckerBuilder.new(SPELL_CHECKERS['NoMethodError'])
end
did_you_mean-1.2.0/lib/did_you_mean/jaro_winkler.rb 0000644 0000041 0000041 00000003451 13221505156 022416 0 ustar www-data www-data module DidYouMean
module Jaro
module_function
def distance(str1, str2)
str1, str2 = str2, str1 if str1.length > str2.length
length1, length2 = str1.length, str2.length
m = 0.0
t = 0.0
range = (length2 / 2).floor - 1
range = 0 if range < 0
flags1 = 0
flags2 = 0
# Avoid duplicating enumerable objects
str1_codepoints = str1.codepoints
str2_codepoints = str2.codepoints
i = 0
while i < length1
last = i + range
j = (i >= range) ? i - range : 0
while j <= last
if flags2[j] == 0 && str1_codepoints[i] == str2_codepoints[j]
flags2 |= (1 << j)
flags1 |= (1 << i)
m += 1
break
end
j += 1
end
i += 1
end
k = i = 0
while i < length1
if flags1[i] != 0
j = index = k
k = while j < length2
index = j
break(j + 1) if flags2[j] != 0
j += 1
end
t += 1 if str1_codepoints[i] != str2_codepoints[index]
end
i += 1
end
t = (t / 2).floor
m == 0 ? 0 : (m / length1 + m / length2 + (m - t) / m) / 3
end
end
module JaroWinkler
WEIGHT = 0.1
THRESHOLD = 0.7
module_function
def distance(str1, str2)
jaro_distance = Jaro.distance(str1, str2)
if jaro_distance > THRESHOLD
codepoints2 = str2.codepoints
prefix_bonus = 0
i = 0
str1.each_codepoint do |char1|
char1 == codepoints2[i] && i < 4 ? prefix_bonus += 1 : break
i += 1
end
jaro_distance + (prefix_bonus * WEIGHT * (1 - jaro_distance))
else
jaro_distance
end
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/ 0000755 0000041 0000041 00000000000 13221505156 022366 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/null_checker.rb 0000644 0000041 0000041 00000000150 13221505156 025345 0 ustar www-data www-data module DidYouMean
class NullChecker
def initialize(*); end
def corrections; [] end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/ 0000755 0000041 0000041 00000000000 13221505156 026366 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb 0000644 0000041 0000041 00000002027 13221505156 032505 0 ustar www-data www-data # frozen-string-literal: true
require 'delegate'
require "did_you_mean/spell_checker"
module DidYouMean
class ClassNameChecker
attr_reader :class_name
def initialize(exception)
@class_name, @receiver = exception.name, exception.receiver
end
def corrections
@corrections ||= SpellChecker.new(dictionary: class_names).correct(class_name).map(&:full_name)
end
def class_names
scopes.flat_map do |scope|
scope.constants.map do |c|
ClassName.new(c, scope == Object ? "" : "#{scope}::")
end
end
end
def scopes
@scopes ||= @receiver.to_s.split("::").inject([Object]) do |_scopes, scope|
_scopes << _scopes.last.const_get(scope)
end.uniq
end
class ClassName < SimpleDelegator
attr :namespace
def initialize(name, namespace = '')
super(name)
@namespace = namespace
end
def full_name
self.class.new("#{namespace}#{__getobj__}")
end
end
private_constant :ClassName
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb 0000644 0000041 0000041 00000002023 13221505156 033161 0 ustar www-data www-data # frozen-string-literal: true
require "did_you_mean/spell_checker"
module DidYouMean
class VariableNameChecker
attr_reader :name, :method_names, :lvar_names, :ivar_names, :cvar_names
NAMES_TO_EXCLUDE = { 'foo' => [:fork] }
NAMES_TO_EXCLUDE.default = []
RB_PREDEFINED_OBJECTS = [:false, :true, :nil]
def initialize(exception)
@name = exception.name.to_s.tr("@", "")
@lvar_names = exception.respond_to?(:local_variables) ? exception.local_variables : []
receiver = exception.receiver
@method_names = receiver.methods + receiver.private_methods
@ivar_names = receiver.instance_variables
@cvar_names = receiver.class.class_variables
@cvar_names += receiver.class_variables if receiver.kind_of?(Module)
end
def corrections
@corrections ||= SpellChecker
.new(dictionary: (RB_PREDEFINED_OBJECTS + lvar_names + method_names + ivar_names + cvar_names))
.correct(name) - NAMES_TO_EXCLUDE[@name]
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers.rb 0000644 0000041 0000041 00000001135 13221505156 026713 0 ustar www-data www-data require 'did_you_mean/spell_checkers/name_error_checkers/class_name_checker'
require 'did_you_mean/spell_checkers/name_error_checkers/variable_name_checker'
module DidYouMean
class << (NameErrorCheckers = Object.new)
def new(exception)
case exception.original_message
when /uninitialized constant/
ClassNameChecker
when /undefined local variable or method/,
/undefined method/,
/uninitialized class variable/,
/no member '.*' in struct/
VariableNameChecker
else
NullChecker
end.new(exception)
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/key_error_checker.rb 0000644 0000041 0000041 00000000466 13221505156 026406 0 ustar www-data www-data require "did_you_mean/spell_checker"
module DidYouMean
class KeyErrorChecker
def initialize(key_error)
@key = key_error.key
@keys = key_error.receiver.keys
end
def corrections
@corrections ||= SpellChecker.new(dictionary: @keys).correct(@key).map(&:inspect)
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/method_name_checker.rb 0000644 0000041 0000041 00000001422 13221505156 026656 0 ustar www-data www-data require "did_you_mean/spell_checker"
module DidYouMean
class MethodNameChecker
attr_reader :method_name, :receiver
NAMES_TO_EXCLUDE = { NilClass => nil.methods }
NAMES_TO_EXCLUDE.default = []
def initialize(exception)
@method_name = exception.name
@receiver = exception.receiver
@private_call = exception.respond_to?(:private_call?) ? exception.private_call? : false
end
def corrections
@corrections ||= SpellChecker.new(dictionary: method_names).correct(method_name) - NAMES_TO_EXCLUDE[@receiver.class]
end
def method_names
method_names = receiver.methods + receiver.singleton_methods
method_names += receiver.private_methods if @private_call
method_names.uniq!
method_names
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/version.rb 0000644 0000041 0000041 00000000052 13221505156 021407 0 ustar www-data www-data module DidYouMean
VERSION = "1.2.0"
end
did_you_mean-1.2.0/lib/did_you_mean/formatters/ 0000755 0000041 0000041 00000000000 13221505156 021566 5 ustar www-data www-data did_you_mean-1.2.0/lib/did_you_mean/formatters/verbose_formatter.rb 0000644 0000041 0000041 00000000437 13221505156 025647 0 ustar www-data www-data # frozen-string-literal: true
module DidYouMean
class VerboseFormatter
def message_for(corrections)
return "" if corrections.empty?
output = "\n\n Did you mean? ".dup
output << corrections.join("\n ")
output << "\n "
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/formatters/plain_formatter.rb 0000644 0000041 0000041 00000000327 13221505156 025303 0 ustar www-data www-data # frozen-string-literal: true
module DidYouMean
class PlainFormatter
def message_for(corrections)
corrections.empty? ? "" : "\nDid you mean? #{corrections.join("\n ")}"
end
end
end
did_you_mean-1.2.0/lib/did_you_mean/experimental.rb 0000644 0000041 0000041 00000000171 13221505156 022421 0 ustar www-data www-data require 'did_you_mean/experimental/initializer_name_correction'
require 'did_you_mean/experimental/ivar_name_correction'
did_you_mean-1.2.0/lib/did_you_mean/verbose_formatter.rb 0000644 0000041 0000041 00000000471 13221505156 023457 0 ustar www-data www-data require 'did_you_mean'
require 'did_you_mean/formatters/verbose_formatter'
DidYouMean.formatter = DidYouMean::VerboseFormatter.new
warn '`require "did_you_mean/verbose_formatter"\' has been deprecated and will be removed' \
" in the next major Ruby version. Please require 'did_you_mean/verbose' instead."
did_you_mean-1.2.0/lib/did_you_mean/levenshtein.rb 0000644 0000041 0000041 00000002541 13221505156 022253 0 ustar www-data www-data module DidYouMean
module Levenshtein # :nodoc:
# This code is based directly on the Text gem implementation
# Copyright (c) 2006-2013 Paul Battley, Michael Neumann, Tim Fletcher.
#
# Returns a value representing the "cost" of transforming str1 into str2
def distance(str1, str2)
n = str1.length
m = str2.length
return m if n.zero?
return n if m.zero?
d = (0..m).to_a
x = nil
# to avoid duplicating an enumerable object, create it outside of the loop
str2_codepoints = str2.codepoints
str1.each_codepoint.with_index(1) do |char1, i|
j = 0
while j < m
cost = (char1 == str2_codepoints[j]) ? 0 : 1
x = min3(
d[j+1] + 1, # insertion
i + 1, # deletion
d[j] + cost # substitution
)
d[j] = i
i = x
j += 1
end
d[m] = x
end
x
end
module_function :distance
private
# detects the minimum value out of three arguments. This method is
# faster than `[a, b, c].min` and puts less GC pressure.
# See https://github.com/yuki24/did_you_mean/pull/1 for a performance
# benchmark.
def min3(a, b, c)
if a < b && a < c
a
elsif b < c
b
else
c
end
end
module_function :min3
end
end
did_you_mean-1.2.0/lib/did_you_mean.rb 0000644 0000041 0000041 00000002330 13221505156 017723 0 ustar www-data www-data require "did_you_mean/version"
require "did_you_mean/core_ext/name_error"
require "did_you_mean/spell_checker"
require 'did_you_mean/spell_checkers/name_error_checkers'
require 'did_you_mean/spell_checkers/method_name_checker'
require 'did_you_mean/spell_checkers/key_error_checker'
require 'did_you_mean/spell_checkers/null_checker'
require "did_you_mean/formatters/plain_formatter"
module DidYouMean
class DeprecatedIgnoredCallers < Array
%i(
+
<<
[]=
insert
unshift
push
).each do |method_name|
eval <<-RUBY, nil, __FILE__, __LINE__ + 1
def #{method_name}(*)
warn "IGNORED_CALLERS has been deprecated and has no effect."
super
end
RUBY
end
end
IGNORED_CALLERS = DeprecatedIgnoredCallers.new
SPELL_CHECKERS = Hash.new(NullChecker)
SPELL_CHECKERS.merge!({
"NameError" => NameErrorCheckers,
"NoMethodError" => MethodNameChecker,
"KeyError" => KeyErrorChecker
})
NameError.prepend DidYouMean::Correctable
KeyError.prepend DidYouMean::Correctable
def self.formatter
@@formatter
end
def self.formatter=(formatter)
@@formatter = formatter
end
self.formatter = PlainFormatter.new
end
did_you_mean-1.2.0/did_you_mean.gemspec 0000644 0000041 0000041 00000001610 13221505156 020175 0 ustar www-data www-data # coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'did_you_mean/version'
Gem::Specification.new do |spec|
spec.name = "did_you_mean"
spec.version = DidYouMean::VERSION
spec.authors = ["Yuki Nishijima"]
spec.email = ["mail@yukinishijima.net"]
spec.summary = '"Did you mean?" experience in Ruby'
spec.description = 'The gem that has been saving people from typos since 2014.'
spec.homepage = "https://github.com/yuki24/did_you_mean"
spec.license = "MIT"
spec.files = `git ls-files`.split($/)
spec.test_files = spec.files.grep(%r{^(test)/})
spec.require_paths = ["lib"]
spec.required_ruby_version = '>= 2.5.0dev'
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "minitest"
end
did_you_mean-1.2.0/test/ 0000755 0000041 0000041 00000000000 13221505156 015155 5 ustar www-data www-data did_you_mean-1.2.0/test/core_ext/ 0000755 0000041 0000041 00000000000 13221505156 016765 5 ustar www-data www-data did_you_mean-1.2.0/test/core_ext/name_error_extension_test.rb 0000644 0000041 0000041 00000002265 13221505156 024603 0 ustar www-data www-data require 'test_helper'
class NameErrorExtensionTest < Minitest::Test
SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
class TestSpellChecker
def initialize(*); end
def corrections; ["does_exist"]; end
end
def setup
@org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
@error = assert_raises(NameError){ doesnt_exist }
end
def teardown
SPELL_CHECKERS['NameError'] = @org
end
def test_message
message = <<~MESSAGE.chomp
undefined local variable or method `doesnt_exist' for #{method(:to_s).super_method.call}
Did you mean? does_exist
MESSAGE
assert_equal message, @error.to_s
assert_equal message, @error.message
end
def test_to_s_does_not_make_disruptive_changes_to_error_message
error = assert_raises(NameError) do
raise NameError, "uninitialized constant Object"
end
error.to_s
assert_equal 1, error.to_s.scan("Did you mean?").count
end
end
class DeprecatedIgnoreCallersTest < Minitest::Test
def test_ignore
assert_output nil, "IGNORED_CALLERS has been deprecated and has no effect.\n" do
DidYouMean::IGNORED_CALLERS << /( |`)do_not_correct_typo'/
end
end
end
did_you_mean-1.2.0/test/edit_distance/ 0000755 0000041 0000041 00000000000 13221505156 017754 5 ustar www-data www-data did_you_mean-1.2.0/test/edit_distance/jaro_winkler_test.rb 0000644 0000041 0000041 00000002624 13221505156 024032 0 ustar www-data www-data # -*- coding: utf-8 -*-
require 'test_helper'
# These tests were originally written by Jian Weihang (簡煒航) as part of his work
# on the jaro_winkler gem. The original code could be found here:
# https://github.com/tonytonyjan/jaro_winkler/blob/9bd12421/spec/jaro_winkler_spec.rb
#
# Copyright (c) 2014 Jian Weihang
class JaroWinklerTest < Minitest::Test
def test_jaro_winkler_distance
assert_distance 0.9667, 'henka', 'henkan'
assert_distance 1.0, 'al', 'al'
assert_distance 0.9611, 'martha', 'marhta'
assert_distance 0.8324, 'jones', 'johnson'
assert_distance 0.9167, 'abcvwxyz', 'zabcvwxy'
assert_distance 0.9583, 'abcvwxyz', 'cabvwxyz'
assert_distance 0.84, 'dwayne', 'duane'
assert_distance 0.8133, 'dixon', 'dicksonx'
assert_distance 0.0, 'fvie', 'ten'
assert_distance 0.9067, 'does_exist', 'doesnt_exist'
assert_distance 1.0, 'x', 'x'
end
def test_jarowinkler_distance_with_utf8_strings
assert_distance 0.9818, '變形金剛4:絕跡重生', '變形金剛4: 絕跡重生'
assert_distance 0.8222, '連勝文', '連勝丼'
assert_distance 0.8222, '馬英九', '馬英丸'
assert_distance 0.6667, '良い', 'いい'
end
private
def assert_distance(score, str1, str2)
assert_equal score, DidYouMean::JaroWinkler.distance(str1, str2).round(4)
end
end
did_you_mean-1.2.0/test/experimental/ 0000755 0000041 0000041 00000000000 13221505156 017652 5 ustar www-data www-data did_you_mean-1.2.0/test/experimental/method_name_checker_test.rb 0000644 0000041 0000041 00000000561 13221505156 025204 0 ustar www-data www-data require 'test_helper'
class ExperimentalMethodNameCorrectionTest < Minitest::Test
def test_corrects_incorrect_ivar_name
@number = 1
@nubmer = nil
error = assert_raises(NoMethodError) { @nubmer.zero? }
remove_instance_variable :@nubmer
assert_correction :@number, error.corrections
assert_match "Did you mean? @number", error.to_s
end
end
did_you_mean-1.2.0/test/experimental/initializer_name_correction_test.rb 0000644 0000041 0000041 00000000635 13221505156 027014 0 ustar www-data www-data require 'test_helper'
class InitializerNameCorrectionTest < Minitest::Test
def test_corrects_wrong_initializer_name
assert_output nil, "warning: intialize might be misspelled, perhaps you meant initialize?\n" do
Class.new { def intialize; end }
end
end
def test_does_not_correct_correct_initializer_name
assert_output nil, "" do
Class.new { def initialize; end }
end
end
end
did_you_mean-1.2.0/test/test_helper.rb 0000644 0000041 0000041 00000000551 13221505156 020021 0 ustar www-data www-data require 'minitest/autorun'
require 'minitest/pride'
require 'did_you_mean'
puts "DidYouMean version: #{DidYouMean::VERSION}"
module DidYouMean::TestHelper
def assert_correction(expected, array)
assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}"
end
end
MiniTest::Test.include(DidYouMean::TestHelper)
did_you_mean-1.2.0/test/spell_checker_test.rb 0000644 0000041 0000041 00000005716 13221505156 021355 0 ustar www-data www-data require 'test_helper'
class SpellCheckerTest < Minitest::Test
def test_spell_checker_corrects_mistypes
assert_spell 'foo', input: 'doo', dictionary: ['foo', 'fork']
assert_spell 'email', input: 'meail', dictionary: ['email', 'fail', 'eval']
assert_spell 'fail', input: 'fial', dictionary: ['email', 'fail', 'eval']
assert_spell 'fail', input: 'afil', dictionary: ['email', 'fail', 'eval']
assert_spell 'eval', input: 'eavl', dictionary: ['email', 'fail', 'eval']
assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval']
assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!']
assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!']
assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!)
assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!)
group_methods = %w(groups group_url groups_url group_path)
assert_spell 'groups', input: 'group', dictionary: group_methods
group_classes = %w(
GroupMembership
GroupMembershipPolicy
GroupMembershipDecorator
GroupMembershipSerializer
GroupHelper
Group
GroupMailer
NullGroupMembership
)
assert_spell 'GroupMembership', dictionary: group_classes, input: 'GroupMemberhip'
assert_spell 'GroupMembershipDecorator', dictionary: group_classes, input: 'GroupMemberhipDecorator'
names = %w(first_name_change first_name_changed? first_name_will_change!)
assert_spell names, input: 'first_name_change!', dictionary: names
assert_empty DidYouMean::SpellChecker.new(dictionary: ['proc']).correct('product_path')
assert_empty DidYouMean::SpellChecker.new(dictionary: ['fork']).correct('fooo')
end
def test_spell_checker_corrects_misspells
assert_spell 'descendants', input: 'dependents', dictionary: ['descendants']
assert_spell 'drag_to', input: 'drag', dictionary: ['drag_to']
assert_spell 'set_result_count', input: 'set_result', dictionary: ['set_result_count']
end
def test_spell_checker_sorts_results_by_simiarity
expected = %w(
name12345
name1234
name123
)
actual = DidYouMean::SpellChecker.new(dictionary: %w(
name12
name123
name1234
name12345
name123456
)).correct('name123456')
assert_equal expected, actual
end
def test_spell_checker_excludes_input_from_dictionary
assert_empty DidYouMean::SpellChecker.new(dictionary: ['input']).correct('input')
assert_empty DidYouMean::SpellChecker.new(dictionary: [:input]).correct('input')
assert_empty DidYouMean::SpellChecker.new(dictionary: ['input']).correct(:input)
end
private
def assert_spell(expected, input: , dictionary: )
corrections = DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
assert_equal Array(expected), corrections, "Expected to suggest #{expected}, but got #{corrections.inspect}"
end
end
did_you_mean-1.2.0/test/spell_checking/ 0000755 0000041 0000041 00000000000 13221505156 020127 5 ustar www-data www-data did_you_mean-1.2.0/test/spell_checking/key_name_check_test.rb 0000644 0000041 0000041 00000002633 13221505156 024444 0 ustar www-data www-data require "test_helper"
class KeyNameCheckTest < Minitest::Test
def test_corrects_hash_key_name_with_fetch
hash = { "foo" => 1, bar: 2 }
error = assert_raises(KeyError) { hash.fetch(:bax) }
assert_correction ":bar", error.corrections
assert_match "Did you mean? :bar", error.to_s
error = assert_raises(KeyError) { hash.fetch("fooo") }
assert_correction %("foo"), error.corrections
assert_match %(Did you mean? "foo"), error.to_s
end
def test_corrects_hash_key_name_with_fetch_values
hash = { "foo" => 1, bar: 2 }
error = assert_raises(KeyError) { hash.fetch_values("foo", :bar, :bax) }
assert_correction ":bar", error.corrections
assert_match "Did you mean? :bar", error.to_s
error = assert_raises(KeyError) { hash.fetch_values("foo", :bar, "fooo") }
assert_correction %("foo"), error.corrections
assert_match %(Did you mean? "foo"), error.to_s
end
def test_corrects_sprintf_key_name
error = assert_raises(KeyError) { sprintf("%d", {fooo: 1}) }
assert_correction ":fooo", error.corrections
assert_match "Did you mean? :fooo", error.to_s
end
def test_corrects_env_key_name
ENV["FOO"] = "1"
ENV["BAR"] = "2"
error = assert_raises(KeyError) { ENV.fetch("BAX") }
assert_correction %("BAR"), error.corrections
assert_match %(Did you mean? "BAR"), error.to_s
ensure
ENV.delete("FOO")
ENV.delete("BAR")
end
end
did_you_mean-1.2.0/test/spell_checking/variable_name_check_test.rb 0000644 0000041 0000041 00000006144 13221505156 025442 0 ustar www-data www-data require 'test_helper'
class VariableNameCheckTest < Minitest::Test
class User
def initialize
@email_address = 'email_address@address.net'
@first_name = nil
@last_name = nil
end
def first_name; end
def to_s
"#{@first_name} #{@last_name} <#{email_address}>"
end
private
def cia_codename; "Alexa" end
end
module UserModule
def from_module; end
end
def setup
@user = User.new.extend(UserModule)
end
def test_corrections_include_instance_method
error = assert_raises(NameError) do
@user.instance_eval { flrst_name }
end
@user.instance_eval do
remove_instance_variable :@first_name
remove_instance_variable :@last_name
end
assert_correction :first_name, error.corrections
assert_match "Did you mean? first_name", error.to_s
end
def test_corrections_include_method_from_module
error = assert_raises(NameError) do
@user.instance_eval { fr0m_module }
end
assert_correction :from_module, error.corrections
assert_match "Did you mean? from_module", error.to_s
end
def test_corrections_include_local_variable_name
person = person = nil
error = (eprson rescue $!) # Do not use @assert_raises here as it changes a scope.
assert_correction :person, error.corrections
assert_match "Did you mean? person", error.to_s
end
def test_corrections_include_ruby_predefined_objects
some_var = nil
false_error = assert_raises(NameError) do
some_var = fals
end
true_error = assert_raises(NameError) do
some_var = treu
end
nil_error = assert_raises(NameError) do
some_var = nol
end
assert_correction :false, false_error.corrections
assert_match "Did you mean? false", false_error.to_s
assert_correction :true, true_error.corrections
assert_match "Did you mean? true", true_error.to_s
assert_correction :nil, nil_error.corrections
assert_match "Did you mean? nil", nil_error.to_s
end
def test_corrections_include_instance_variable_name
error = assert_raises(NameError){ @user.to_s }
assert_correction :@email_address, error.corrections
assert_match "Did you mean? @email_address", error.to_s
end
def test_corrections_include_private_method
error = assert_raises(NameError) do
@user.instance_eval { cia_code_name }
end
assert_correction :cia_codename, error.corrections
assert_match "Did you mean? cia_codename", error.to_s
end
@@does_exist = true
def test_corrections_include_class_variable_name
error = assert_raises(NameError){ @@doesnt_exist }
assert_correction :@@does_exist, error.corrections
assert_match "Did you mean? @@does_exist", error.to_s
end
def test_struct_name_error
value = Struct.new(:does_exist).new
error = assert_raises(NameError){ value[:doesnt_exist] }
assert_correction [:does_exist, :does_exist=], error.corrections
assert_match "Did you mean? does_exist", error.to_s
end
def test_exclude_typical_incorrect_suggestions
error = assert_raises(NameError){ foo }
assert_empty error.corrections
end
end
did_you_mean-1.2.0/test/spell_checking/class_name_check_test.rb 0000644 0000041 0000041 00000003153 13221505156 024757 0 ustar www-data www-data require 'test_helper'
module ACRONYM
end
class Project
def self.bo0k
Bo0k
end
end
class Book
class TableOfContents; end
def tableof_contents
TableofContents
end
class Page
def tableof_contents
TableofContents
end
def self.tableof_contents
TableofContents
end
end
end
class ClassNameCheckTest < Minitest::Test
def test_corrections
error = assert_raises(NameError) { ::Bo0k }
assert_correction "Book", error.corrections
end
def test_corrections_include_case_specific_class_name
error = assert_raises(NameError) { ::Acronym }
assert_correction "ACRONYM", error.corrections
end
def test_corrections_include_top_level_class_name
error = assert_raises(NameError) { Project.bo0k }
assert_correction "Book", error.corrections
end
def test_names_in_corrections_have_namespaces
error = assert_raises(NameError) { ::Book::TableofContents }
assert_correction "Book::TableOfContents", error.corrections
end
def test_corrections_candidates_for_names_in_upper_level_scopes
error = assert_raises(NameError) { Book::Page.tableof_contents }
assert_correction "Book::TableOfContents", error.corrections
end
def test_corrections_should_work_from_within_instance_method
error = assert_raises(NameError) { ::Book.new.tableof_contents }
assert_correction "Book::TableOfContents", error.corrections
end
def test_corrections_should_work_from_within_instance_method_on_nested_class
error = assert_raises(NameError) { ::Book::Page.new.tableof_contents }
assert_correction "Book::TableOfContents", error.corrections
end
end
did_you_mean-1.2.0/test/spell_checking/uncorrectable_name_check_test.rb 0000644 0000041 0000041 00000000473 13221505156 026504 0 ustar www-data www-data require 'test_helper'
class UncorrectableNameCheckTest < Minitest::Test
class FirstNameError < NameError; end
def setup
@error = assert_raises(FirstNameError) do
raise FirstNameError, "Other name error"
end
end
def test_message
assert_equal "Other name error", @error.message
end
end
did_you_mean-1.2.0/test/spell_checking/method_name_check_test.rb 0000644 0000041 0000041 00000005725 13221505156 025141 0 ustar www-data www-data require 'test_helper'
class MethodNameCheckTest < Minitest::Test
class User
def friends; end
def first_name; end
def descendants; end
def call_incorrect_private_method
raiae NoMethodError
end
def raise_no_method_error
self.firstname
rescue NoMethodError => e
raise e, e.message, e.backtrace
end
protected
def the_protected_method; end
private
def friend; end
def the_private_method; end
class << self
def load; end
end
end
module UserModule
def from_module; end
end
def setup
@user = User.new.extend(UserModule)
end
def test_corrections_include_instance_method
error = assert_raises(NoMethodError){ @user.flrst_name }
assert_correction :first_name, error.corrections
assert_match "Did you mean? first_name", error.to_s
end
def test_corrections_include_private_method
error = assert_raises(NoMethodError){ @user.friend }
assert_correction :friends, error.corrections
assert_match "Did you mean? friends", error.to_s
end
def test_corrections_include_method_from_module
error = assert_raises(NoMethodError){ @user.fr0m_module }
assert_correction :from_module, error.corrections
assert_match "Did you mean? from_module", error.to_s
end
def test_corrections_include_class_method
error = assert_raises(NoMethodError){ User.l0ad }
assert_correction :load, error.corrections
assert_match "Did you mean? load", error.to_s
end
def test_private_methods_should_not_be_suggested
error = assert_raises(NoMethodError){ User.new.the_protected_method }
refute_includes error.corrections, :the_protected_method
error = assert_raises(NoMethodError){ User.new.the_private_method }
refute_includes error.corrections, :the_private_method
end
def test_corrections_when_private_method_is_called_with_args
error = assert_raises(NoMethodError){ @user.call_incorrect_private_method }
assert_correction :raise, error.corrections
assert_match "Did you mean? raise", error.to_s
end
def test_exclude_methods_on_nil
error = assert_raises(NoMethodError){ nil.map }
assert_empty error.corrections
end
def test_does_not_exclude_custom_methods_on_nil
def nil.empty?
end
error = assert_raises(NoMethodError){ nil.empty }
assert_correction :empty?, error.corrections
ensure
NilClass.class_eval { undef empty? }
end
def test_does_not_append_suggestions_twice
error = assert_raises NoMethodError do
begin
@user.firstname
rescue NoMethodError => e
raise e, e.message, e.backtrace
end
end
assert_equal 1, error.to_s.scan(/Did you mean/).count
end
def test_does_not_append_suggestions_three_times
error = assert_raises NoMethodError do
begin
@user.raise_no_method_error
rescue NoMethodError => e
raise e, e.message, e.backtrace
end
end
assert_equal 1, error.to_s.scan(/Did you mean/).count
end
end
did_you_mean-1.2.0/test/verbose_formatter_test.rb 0000644 0000041 0000041 00000001010 13221505156 022261 0 ustar www-data www-data require 'test_helper'
class VerboseFormatterTest < Minitest::Test
def setup
require 'did_you_mean/verbose'
does_exist = does_exist = nil
@error = assert_raises(NameError){ doesnt_exist }
end
def teardown
DidYouMean.formatter = DidYouMean::PlainFormatter.new
end
def test_message
assert_equal <<~MESSAGE.chomp, @error.message
undefined local variable or method `doesnt_exist' for #{method(:to_s).super_method.call}
Did you mean? does_exist
MESSAGE
end
end
did_you_mean-1.2.0/.gitignore 0000644 0000041 0000041 00000000275 13221505156 016172 0 ustar www-data www-data *.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc
coverage
doc/
lib/bundler/man
pkg
rdoc
test/tmp
test/version_tmp
tmp
log
evaluation/dictionary.yml
benchmark/results
did_you_mean-1.2.0/evaluation/ 0000755 0000041 0000041 00000000000 13221505156 016345 5 ustar www-data www-data did_you_mean-1.2.0/evaluation/incorrect_words.yaml 0000644 0000041 0000041 00000055453 13221505156 022453 0 ustar www-data www-data # This data is based on Birkbeck Spelling Error Corpus: http://ota.ox.ac.uk/headers/0643.xml
# More specifically, this is a yaml version of the data in FAWTHROP1DAT.643 and FAWTHROP2DAT.643.
# released under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
# https://creativecommons.org/licenses/by-nc-sa/3.0/
---
abattoir: abbatoir
abhorrence: abhorence
absence: absense
absorbent: absorbant
absorption: absorbtion
accede: acceed
accelerate: acellerate
accessible: accesible
accidentally: accidently
accommodate: accomodate
accommodation: accomodation
accommodations: accomodations
accompaniment: accompanimen
accompanying: acompaning
accomplice: acomplice
accrued: acrued
accumulated: acumulated
accustom: acustom
achievement: acheivement
acknowledgment: acknowledgement
acquaintance: acquantance
acquiesce: aquiese
acquiescence: acquiesence
acquire: aquire
actually: actualy
adaptability: adaptibility
addition: additon
address: adress
adequately: adequattly
adjacent: ajacent
adjourned: adjorned
administration: adminstration
admissible: admissable
admitting: admiting
advantageous: advantageos
advice: advise
affidavit: afidavit
aggravated: agravated
aghast: agast
agreeable: agreable
allotted: alloted
also: allso
alumnae: alumni
alumni: alumnae
amateur: amatuer
amiable: aimiable
ammonia: amonia
analogous: analagous
analysis: analsis
analyze: analize
angel: angell
anniversary: anniversery
announcement: anouncement
annoyance: anoyance
answer: anwser
antarctic: antartic
any: anye
anything: anythin
apollo: appolo
apology: appology
apparent: apparant
appearance: appearence
appearing: appearin
appetite: appitite
appetites: appatites
appropriate: apropriate
appropriation: apropriation
approximate: aproximate
approximately: aproximatly
archaeological: archeological
ascertain: assertain
asinine: assinine
asking: askin
asleep: asleeep
assassinate: assasinate
assessment: assesment
assiduous: assidious
assistance: assistence
attorneys: attornies
authoritative: authorative
auxiliary: auxillary
available: availble
awkward: aukward
bachelor: batchelor
balloon: baloon
banana: bananna
bankruptcy: bankrupcy
bargaining: baragining
battalion: batallion
beam: beame
before: befor
beginning: begining
believe: belive
belligerent: beligerant
beneficent: beneficient
beneficial: benificial
bitch: bich
brake: brakke
brethren: bretheren
brief: brif
britain: britian
britannia: britania
brown: broun
bungalow: bungalo
buoyancy: bouyancy
buoyant: bouyant
buried: burried
bushel: bushell
business: busness
buying: buyin
cancellation: cancelation
calling: callin
cantaloupe: cantaloube
caribbean: carribean
catalogues: catologues
category: catagorey
cemetery: cemetary
chauffeur: chauffuer
chemistry: chemestry
chimneys: chimnies
cincinnati: cincinatti
clever: cleva
coalesced: coalesed
coherent: coherant
coliseum: colosium
collateral: calateral
colossal: collosal
colossus: collosus
commanded: commaunded
commission: commision
commitment: committment
committee: committe
communicate: comunicate
comparative: comparitive
comparatively: comparitively
compendium: conpendium
competent: compitent
concede: consede
conceive: concieve
conceived: concieved
conditions: condicions
confectionery: confectionary
confirmation: confermation
confusing: confusin
connoisseurs: connoiseurs
conscience: concience
conscientious: conscientous
consensus: concensus
considering: consderin
consistent: consistant
conspired: conpired
consumer: comsumer
contemptible: contempible
continuous: continous
controllable: controlable
controversy: controversey
conveniently: conviently
coolly: cooly
corduroy: corderoy
correspondence: correspondanc
corrugated: corrigated
could: coud
counting: countin
countryman: countriman
craftsman: craftman
curiosity: curiousity
curriculum: curicculum
customary: customery
cynical: synical
darling: darlin
decidedly: dicidely
deem: deam
definitely: definatly
delinquent: delinquint
delirious: dilirious
delving: delvin
denying: denyin
dependant: dependent
depreciation: depeciation
descendant: descendent
description: desacription
despair: dispair
deuce: duece
develop: develope
development: developement
dictionary: dictionery
dignitary: dignatary
dilapidated: dilapadated
diminish: diminsh
dining: dinning
diphtheria: diptheria
disappoint: dissappoint
disappointment: dissappointment
disastrous: disasterous
discipline: disiplin
discrete: discite
dispel: dispell
dissipate: disippate
divine: devine
doctor: docter
doctors: docters
dormitory: dormatory
doubt: doupt
drastically: drasticly
drawing: drawin
dreaming: dreamin
drew: drewe
dropped: droped
drunkenness: drunkeness
duchess: dutchess
duly: duely
during: durin
earnest: ernest
ecstasy: ecstacy
effecting: effectinge
effeminate: affeminate
effervescent: effervesent
efficiency: effeciency
eisenhower: eisenhhower
eligible: elegable
eliminate: illiminate
embarrass: embarass
embarrassment: embarrasment
encyclopedia: encylopedia
endorsement: endorsment
enemy: emeny
engineers: egnineers
enlarged: enlargd
entertained: enterteyned
equipped: equipt
equivalent: equivelant
esteemed: estimed
every: evrey
exaggerate: exagerate
exaggeration: exageration
examination: eximination
examining: examinin
excellence: excelence
exercises: excercises
exhilarating: exhilirating
exhorted: exorted
existence: existance
exorbitant: exhorbitant
experience: experiance
explicitly: explisitly
exquisite: exqusite
eyeing: eying
facilitate: facilatate
fascinating: facinating
fatiguing: fatiging
fear: feare
february: febuary
fictitious: fictitous
fielder: fiedler
fiery: firey
fighting: fieghting
filipinos: philipinoes
filthiness: filthness
finally: finaly
flammable: flamable
flourished: florished
foreign: forien
forthright: fortright
forty: fourty
fox: foxx
frescos: frescoes
friend: freind
fulfill: fullfil
fundamental: fundemental
fundamentally: fundementally
gardener: gardner
gauge: guage
generosity: generousity
genius: genious
ghastly: gastly
gnawing: knawing
gone: gonne
government: goverment
grabbing: grabbin
grammar: grammer
gramophone: grammophon
grandeur: granduer
grateful: greatful
grievous: grievious
grill: grille
guarantee: gaurantee
guaranteed: guarenteed
guardian: guardien
guttural: gutteral
hammarskjold: hammerskjold
hand: hande
handkerchief: hankerchief
handsome: hansome
harass: harrass
having: haveing
heartrending: heartrendering
height: heighth
heinous: hienous
hemorrhage: hemorrage
heyday: heydey
himself: himselfe
hindrance: hinderence
humbly: humly
hurricane: huricane
hygiene: hygeine
identified: indentified
idiosyncrasy: idiocyncracy
imagination: imagnation
imitation: immitation
immediately: imidatly
immensely: immensly
impedance: impedence
impresario: impressario
incense: insense
incessant: incesant
incidentally: incidently
incompatibility: incompatability
inconvenience: inconvience
incorrigible: incorigible
incredible: incredable
indefinite: indefinate
independence: independance
indictment: inditement
indispensable: indispensible
inevitable: inevitible
infallible: infalable
infinite: infinate
ingratitude: ingratitoode
innocuous: inocuous
inoculate: innoculate
insistence: insistance
instantaneous: instantanous
instead: insted
intercede: intersede
interfered: interferred
interference: intereference
interrupted: interupted
invariably: invarably
irrelevant: irrelavent
irreparable: irrepairable
irresistible: irristible
itemized: itimized
jackknife: jacknife
jaguar: jagaur
japanese: japaneze
jaundice: jaundise
jealousy: jelousy
jeopardize: jeprodise
judgment: judgement
kaleidoscope: kaliedoscope
kapok: kapock
khaki: kahki
kimono: kimona
kindergarten: kindergarden
kitchen: kitchin
knickknacks: knicknacks
labeled: labelled
laboratory: labratory
language: langauge
leeway: leaway
leisure: liesure
leveled: levelled
library: libray
license: lisence
lieutenant: leutenant
linoleum: linolium
liquefied: liquified
liquefy: liquify
livelihood: livelyhood
lodestone: loadstone
lodgment: lodgement
lonely: lonley
magnificent: magnigicient
maintenance: maintainance
mammoth: mamoth
management: managment
maneuver: manuveur
manufactories: manufacturies
masterpiece: masterpice
material: materiel
mathematics: mathmatics
mattress: mattres
maudlin: mauldin
meant: ment
medicine: medecine
meeting: meetin
mercenary: mercanery
merchandise: merchandize
merchantmen: merchantment
meteorological: meterological
metropolitan: metropolitian
millionaire: millionnaire
miniature: minature
miscellaneous: miscelaneous
mischievous: mischievious
moccasins: mocassins
momentous: momentus
mortgage: morgage
mortgaged: mortgauged
murmurs: murmers
mustnt: musnt
mutilate: mutalate
mythical: mithical
nadir: nadar
naphtha: naptha
narrative: narative
naturally: naturaly
navigating: navagating
necessarily: necessarilly
necessary: nessisary
niagara: niagra
nickel: nickle
niggardly: nigardly
ninetieth: nintieth
ninetyninth: nintynineth
nocturnal: nocternal
nonsense: nonsence
notwithstanding: nothwithstanding
nowadays: nowdays
obbligato: obliggato
obdurate: obdirate
occasion: ocassion
occasionally: occasionaly
occurred: occureed
occurrence: occurence
octopus: octapus
odyssey: oddysey
ominous: omenous
omission: ommision
onerous: onirous
opportunities: oppotunities
opposition: oposition
oppressor: oppresser
optician: optitian
oratorio: orotario
orchestra: ochestra
ordinarily: ordinarilly
origin: origen
originally: origionally
own: owne
pain: paine
pamphlet: phamplet
pamphlets: phamplets
parallel: parellel
paralysis: parallysis
paraphernalia: parephernalia
parenthesis: parenthasis
participle: participal
pastime: pasttime
pastor: paster
paternity: paternaty
pavilion: pavillion
peasant: peasent
peculiar: pecular
penance: pennance
pendulum: pendelum
penguins: pengiuns
peninsula: peninsular
penitentiary: penitentary
perceive: percieve
perforation: preforation
permissible: permissable
perseverance: perseverence
personalty: personality
perspiration: persperation
persuade: pursuade
persuaded: pursuaded
persuasion: persausion
pertaining: pertaning
pervaded: prevaded
pharaohs: pharoahs
phase: faze
phenomenal: phenominal
phenomenon: phenonenon
philippines: phillipines
physician: physican
pickerel: pickeral
picnicking: picnicing
pittsburgh: pittsburg
plagiarism: plaigarism
plaque: placque
playwright: playwrite
pleasant: plesent
poetry: poetrie
poisonous: poisenous
ponderous: pondorous
possess: posess
possession: possesion
possibilities: possablities
prairie: prarie
preceding: preceeding
precipice: presipice
preferable: preferrable
preference: preferance
preferred: prefered
prejudice: prejedice
preparation: preperation
preserved: perserved
presumptuous: presumptous
prevalent: prevelant
preventive: preventative
prisoner: prisner
privilege: priviledge
probably: probabley
procedure: proceduer
professor: proffesor
proffer: profer
prominent: prominant
promontory: promonotory
pronunciation: pronounciation
propeller: propellor
prophecy: prophesy
provisions: provisons
pseudonym: pseudynom
psychological: psycological
public: publick
publicly: publically
pumpkin: pumkin
pursue: persue
pursuer: persuer
pursuit: persuit
qualified: qualafied
quandary: quandry
quantities: quanties
quarantine: quarrantine
quarreled: quarelled
quarter: quater
questionnaire: questionare
quiescent: quiscent
quorum: quorem
radiant: radient
radiator: radiater
raise: raize
rating: rateing
really: realy
rebuttal: rebutal
receded: receeded
receipt: reciept
receipts: reciepts
receive: recieve
receiver: reciever
receptacle: receptacel
recipient: resipient
reciprocal: reciprocel
reckon: recon
reclamation: reclaimation
recommend: recomend
recommendation: recomendation
recommendations: reccomendations
recommended: recommend
recommending: recomending
recompense: recompence
redundant: redundent
reference: refference
referred: refered
referring: refering
refrigerator: refrigerater
regretted: regreted
rehabilitate: rehabilatate
relevant: relevaant
religious: religous
remembrance: rememberance
rendezvous: rendevous
renegade: renagade
renown: renoun
reparation: repairation
repel: repell
repetition: repitition
representatives: representitives
rescinded: resinded
reservoir: resevoir
responsibility: responsiblity
restaurant: restuarant
restaurateur: restauranteur
rhapsody: raphsody
rheumatism: rhuematism
rhododendron: rhododrendon
rhubarb: ruhbarb
rhythm: rythm
ridiculous: rediculous
romantic: romantick
rummage: rumage
running: runing
sabbath: sabath
sacrament: sacrement
sacrilegious: sacreligious
safety: safty
sagacious: sagatious
sailor: sailer
sandwich: sanwich
sanitary: sanatary
satisfactory: satisfactary
scarcity: scarsity
scissors: sissers
seize: sieze
seized: siezed
self: selfe
sell: selle
semesters: semisters
seminary: seminery
separate: seporate
sergeant: sergant
sheep: sheepe
shepherd: sheperd
silhouette: silhuette
shipping: shippin
shoulder: shouldda
shoulders: sholders
showing: showin
shrubbery: shrubery
siege: seige
significant: significent
silk: silke
similar: similiar
simultaneous: similtanous
sincerity: sincerety
slimmest: slimest
smiling: smilin
sociable: socable
social: socal
solemn: solomn
sophomore: sophmore
sorority: sororiety
sought: saught
source: sorce
souvenir: souviner
sovereignty: sovreignty
sparsely: sparcely
spear: speer
specifically: specificly
specimen: speciment
specimens: specimans
spirituous: spiritous
sprinkle: sprinkel
starting: startin
stationary: stationery
statue: statu
stirring: stirrin
stirrups: stirups
stomach: stomack
straining: strainin
straitjacket: straightjacket
stratagem: strategem
strategy: stratagy
strenuous: strenous
stretched: streched
stubbornness: stubborness
suburban: sububan
success: sucess
sufficient: suficient
suffrage: sufferage
sugar: suger
suing: sueing
superficial: superfical
superintendent: supertendent
supersede: supercede
supplement: suplement
suppress: supress
surprise: suprise
surreptitious: sureptitous
surrounded: surounded
swearing: swearinge
syllables: sylables
symmetry: symetry
synonymous: synonomous
systematically: systemetically
tacit: tasit
taking: takin
technically: technecally
television: televison
temperament: temperment
temporarily: temporarly
temporary: tempory
tendency: tendancy
terrestrial: terestial
terrors: terrours
that: thatt
therefore: therefor
thief: theaf
think: thinke
thinking: thinkin
thorough: thourough
thoroughly: throughly
tobacco: tobbaco
tobogganing: tobboganing
tonnage: tonage
tragedy: tradgedy
tranquility: tranquillity
tranquillity: tranquility
transferable: transferrable
transferred: transfred
truculent: trucculent
truly: truley
tying: tieing
tyrannical: tyranical
undoubtedly: undoubtly
unequaled: unequalled
unfortunately: unfortunatly
university: unversity
unmistakable: unmistakeable
unparalleled: unparalelled
until: untill
usage: useage
usually: usualy
usurious: usurous
utterance: utterence
vacancy: vancancy
vaccination: vacinnation
vacillate: vaccilate
various: vairious
vegetable: vegatable
vengeance: vengance
vertical: verticle
vice: vise
victuals: vituals
vilify: villify
villain: villian
violence: violance
violin: vioiln
visible: visable
vitamins: vitamines
voucher: vouture
wagging: waggin
waggish: wagish
wednesday: wensday
weed: weede
weight: weigth
weird: wierd
whether: wether
which: whitch
who: whoe
withhold: withold
worshiping: worshipping
yacht: yaht
yearned: yerned
yeoman: yoman
yield: yeild
zealous: zelous
zenith: zeenith
ability: ablity
academically: academicly
accept: acept
accepted: acepted
access: acess
accessibility: accessability
accessing: accesing
according: acording
account: acount
accounts: acounts
acquaintances: aquantences
adaptable: adabtable
addressable: addresable
adequate: adiquate
adjournment: adjurnment
advise: advice
again: agiin
agencies: agences
aggravating: agravating
allow: alow
although: athough
analyse: analiss
analysed: analised
analysing: aalysing
and: anf
announcing: anouncing
annoying: anoying
annual: anual
anomalies: anomolies
apologies: appologies
apologised: appologised
appeal: apeal
appendix: apendix
applicable: aplicable
applied: upplied
applying: applieing
appointment: appoitment
appointments: apointments
appreciated: apreciated
appreciation: apreciation
approach: aproach
approached: aproached
are: arte
arguing: aurguing
arranged: arrainged
arrangeing: aranging
arrangement: arrangment
arrangements: araingements
articles: articals
assessing: accesing
associated: assosiated
atmosphere: atmospher
auguments: aurgument
availability: avaiblity
base: basse
benefit: benifit
benefits: benifits
between: beetween
bicycle: bicycal
bingley: bingly
bonus: bonas
build: biuld
building: biulding
busy: buisy
career: carrer
careers: currers
categories: catagoris
centrally: centraly
certain: cirtain
challenges: chalenges
challenge: chalange
choice: choise
choices: choises
choose: chose
choosing: chosing
clerical: clearical
clerk: clerck
collate: colate
combine: comibine
commercial: comersial
comments: coments
commit: comit
committees: commitees
compare: compair
compared: comppared
comparison: comparrison
completely: completly
component: componant
composed: compossed
conditioning: conditining
conference: conferance
consider: concider
considerable: conciderable
consist: consisit
consisting: consisiting
consists: consisits
contained: contasined
containing: contasining
continually: contually
continued: contuned
controlled: controled
conversely: conversly
corporate: corparate
credit: creadit
criticism: citisum
currently: curruntly
data: dsata
dealt: delt
decide: descide
decided: descided
decides: descides
decision: descisions
decisions: descisions
declarations: declaratrions
definition: defenition
definitions: defenitions
demands: diemands
dependence: dependance
described: discribed
desirable: disiable
desperately: despratly
diagrammatically: diagrammatica
different: diffrent
difficult: dificult
difficulty: dificulty
disaggregate: disaggreagte
disappointing: dissapoiting
discretion: discresion
dissension: desention
dragged: draged
earlier: earlyer
earliest: earlyest
easier: easer
easily: easyly
econometric: economtric
edition: ediition
eliminated: elimiated
embellishing: embelishing
employed: emploied
employees: emploies
employment: empolyment
encompassing: encompasing
encourage: encorage
enormously: enomosly
entirely: entierly
equalled: equaled
erroneous: errounous
especially: especaily
essential: esential
eventually: eventully
evident: evedent
exact: exsact
exactly: exsactly
examine: examin
excellent: exerlant
except: excxept
excessively: exessively
executed: executted
expansion: expanion
expense: expence
expensive: expencive
experiences: experances
explaining: explaning
exponentially: exponentualy
extremely: extreemly
facilities: facilitys
fails: failes
'false': faulse
familiar: familer
families: familys
favourable: faverable
favourably: favorably
feeling: fealing
female: femail
figure: figuar
figures: figuars
financial: finatical
financially: financialy
flexible: flexable
forbidden: forbiden
forecast: forcast
fourth: forth
functionally: functionaly
functions: functuions
further: futher
gaining: ganing
generated: generataed
geneva: geniva
geographically: goegraphicaly
graphically: graphicaly
guidelines: guidlines
handle: handel
hierarchal: hierachial
hierarchy: hierchy
however: howeverr
humour: humor
ideally: idealy
immediate: imediate
inconceivable: inconcievable
indeed: indead
independent: independant
inefficient: ineffiect
initial: intital
input: inut
inquiries: equiries
insight: insite
intelligence: inteligence
interest: intrest
interesting: intresting
interpretation: interpritatio
interrogating: interogationg
investigated: investegated
journalism: journaism
knowledge: knowlege
largely: largly
later: latter
length: lengh
level: leval
levels: levals
lieu: liew
literature: litriture
loans: lones
locally: localy
luckily: luckeley
majority: majorty
manually: manualy
many: mony
mathematically: mathematicaly
matrix: matriiix
mean: meen
means: meens
minutes: muiuets
misleading: missleading
monitoring: monitering
months: monthes
moving: moveing
nationally: nationaly
nature: natior
necessitates: nessisitates
necessity: nessesity
negligible: negligable
neither: niether
night: nite
normally: normaly
now: noe
numbers: numbuers
obtaining: optaning
occur: occure
operations: operatins
operator: opertor
operators: oprators
opinion: oppinion
opportunity: oppotunity
ordinary: ordenary
organization: oranisation
organized: oranised
orientated: orentated
output: oputput
overall: overal
paid: payed
parameters: perametres
partially: partialy
particular: particulaur
particularly: particulary
patterns: pattarns
per: pere
perhaps: perhapse
permanent: perminant
permanently: perminantly
personnel: personel
pivoting: pivting
politics: polatics
position: possition
possible: possable
prepared: prepaired
primarily: pimarily
prior: piror
proceeding: proceding
profession: preffeson
profit: proffit
profits: proffits
progresses: progressess
progression: progresion
projects: projeccts
proportions: proprtions
provide: provid
provisionally: provisionaly
proviso: provisoe
qualities: quaties
queries: quies
reaching: reching
readjusted: reajusted
received: recived
receives: recives
receiving: reciving
recently: reciently
refered: reffered
regained: regined
register: rgister
relatively: relitivly
repetitive: repetative
representative: representitiv
requested: rquested
required: reequired
research: reserch
resolved: resoved
responsibilities: responsibliti
responsible: responcible
resulting: reulting
retirement: retirment
routine: rouint
safeguard: safegaurd
salaries: salarys
scheme: scheem
scrutinized: scrutiniesed
search: serch
searching: serching
secretaries: secutaries
security: seurity
seen: seeen
segment: segemnt
senior: sienior
sense: sence
sensible: sensable
separated: seperated
separation: seperation
session: sesion
set: et
sheets: sheertes
shortened: shortend
shown: hown
sign: eign
simular: similar
singular: singulaur
someone: somone
sources: sorces
speaking: speeking
standardizing: stanerdizing
stopped: stoped
students: studens
studying: studing
subsequent: subsiquent
subtract: subtrcat
successful: sucssuful
successive: sucsesive
such: shuch
suffering: suufering
suggested: sugested
suggestion: sugestion
suggests: sugests
suited: suted
summarys: sumarys
supervision: supervison
supplementary: suplementary
supplements: suplements
supposedly: supposidly
surrounding: serounding
surroundings: suroundings
surveys: servays
surveying: servaying
system: sysem
table: tasble
technique: tecnique
techniques: tecniques
the: thw
their: thier
there: thear
thermawear: thermawhere
these: thess
they: thay
thoughts: thorts
through: throut
throughout: throuout
timing: timeing
titles: tittles
to: ro
together: togehter
totally: totaly
traditionally: traditionaly
transactions: trasactions
transportability: transportibil
triangular: triangulaur
umbrella: umberalla
unavailable: unavailble
understandable: understadable
unequalled: unequaled
unequivocally: unequivocaly
union: unioun
unique: uneque
universally: universaly
unnecessarily: unessasarily
unnecessary: unessessay
unresolved: unresloved
used: usedf
useful: usful
user: uers
utilized: utalised
valuable: valuble
variable: varible
variant: vairiant
variety: variatry
virtually: vertually
visitor: vistor
visitors: vistors
voluntary: volantry
voting: voteing
weapons: wepons
weighted: wagted
were: where
when: whn
whereas: wheras
widely: widly
will: wil
within: withing
would: whould
written: writen
years: yesars
did_you_mean-1.2.0/evaluation/dictionary_generator.rb 0000644 0000041 0000041 00000001444 13221505156 023110 0 ustar www-data www-data require 'open-uri'
require 'cgi'
require 'json'
per_page = 500
base_url = "https://simple.wiktionary.org/w/api.php?action=query&aplimit=#{per_page}&list=allpages&format=json"
filename = "evaluation/dictionary.yml"
apfrom = ""
num = 0
titles = []
loop do
url = base_url + "&apfrom=#{apfrom}"
puts "downloading page %2d: #{url}" % num
body = open(url).read
json = JSON.load(body)
count = json["query"]["allpages"].size
apfrom = CGI.escape(json["query"]["allpages"].last['title']) if count > 0
titles += json["query"]["allpages"].map {|hash| hash["title"] }
num += 1
break if count != per_page
end
require 'yaml'
File.open(filename, 'w') do |file|
file.write(titles.uniq.to_yaml)
end
puts "
Number of titles: #{titles.uniq.size}
Dictionary saved: #{filename}
"
did_you_mean-1.2.0/evaluation/calculator.rb 0000644 0000041 0000041 00000004620 13221505156 021025 0 ustar www-data www-data # frozen-string-literal: true
require 'benchmark'
require 'did_you_mean'
def report(message, &block)
time = 1000 * Benchmark.realtime(&block)
if (time / 1000 / 60) >= 1
minutes = (time / 1000 / 60).floor
seconds = (time % (60 * 1000)) / 1000
puts " \e[36m%2dm%.3fs:\e[0m %s" % [minutes, seconds, message]
elsif (time / 1000) >= 1
seconds = (time % (60 * 1000)) / 1000
puts " \e[36m%9.3fs:\e[0m %s" % [seconds, message]
else
puts " \e[36m%8.1fms:\e[0m %s" % [time, message]
end
time
end
puts "did_you_mean version: #{DidYouMean::VERSION}\n\n"
report "loading program" do
require 'yaml'
require 'set'
begin
require 'jaro_winkler'
DidYouMean::JaroWinkler.module_eval do
module_function
def distance(str1, str2)
::JaroWinkler.distance(str1, str2)
end if RUBY_ENGINE != 'jruby'
end
rescue LoadError, NameError => e
puts "couldn't load the jaro_winkler gem: #{e.message}\n\n"
end
end
report "loading dictionary" do
yaml = open("evaluation/dictionary.yml").read
yaml = YAML.load(yaml).map{|word| word.downcase.tr(" ", "_") }
DICTIONARY = Set.new(yaml)
end
report "loading correct/incorrect words" do
SPELL_CHECKER = DidYouMean::SpellChecker.new(dictionary: DICTIONARY)
INCORRECT_WORDS = YAML.load(open("evaluation/incorrect_words.yaml").read)
end
total_count = 0
correct_count = 0
words_not_corrected = []
filename = "log/words_not_corrected_#{Time.now.to_i}.yml"
puts <<-MSG
Total number of test data: #{INCORRECT_WORDS.size}
MSG
report "calculating accuracy" do
INCORRECT_WORDS.each_with_index do |(expected, user_input), index|
if DICTIONARY.include?(expected)
total_count += 1
corrections = SPELL_CHECKER.correct(user_input)
if corrections.first == expected
correct_count += 1
else
words_not_corrected << {
'input' => user_input,
'expected' => expected,
'actual' => corrections
}
end
end
puts "processed #{index} items" if index % 100 == 0
end
puts "\n"
end
puts <<-MSG
Evaulation result
Total count : #{total_count}
Correct count: #{correct_count}
Accuracy : #{correct_count.to_f / total_count}
MSG
Dir.mkdir('log') unless File.exist?('log')
File.open(filename, 'w') do |file|
file.write(words_not_corrected.to_yaml)
end
puts "Incorrect corrections were logged to #{filename}."
did_you_mean-1.2.0/CHANGELOG.md 0000644 0000041 0000041 00000036263 13221505156 016021 0 ustar www-data www-data ## [v1.1.2](https://github.com/yuki24/did_you_mean/tree/v1.1.2)
_released at 2017-09-24 07:28:48 UTC_
**This version is compatible with Ruby 2.4 and older**
#### Bug Fixes
- Fixed a bug where `did_you_mean` shows duplicate suggestions when the exception is raised multiple times ([#84](https://github.com/yuki24/did_you_mean/pull/84), [c2e4008](https://github.com/yuki24/did_you_mean/commit/c2e40083cef604c00ccd10efc6d7a5036ad9eb5b))
## [v1.1.1](https://github.com/yuki24/did_you_mean/tree/v1.1.1)
_released at 2017-09-24 07:24:02 UTC_
### This version has been yanked from Rubygems.org and is not available.
## [v1.1.0](https://github.com/yuki24/did_you_mean/tree/v1.1.0)
_released at 2016-12-19 23:19:06 UTC_
The version `1.1.0` only has support for Ruby 2.4.0 and later. Also, all patch releasess under `1.1.*` will only be compatible with Ruby 2.4.0 and later as well. Versions under `1.0.*` will still be maintained until Ruby 2.3 is deprecated. Any other versions below `1.0` will no longer be maintained.
#### New Features
- Suggest a method name on a NameError from the `Struct#[]` or `Struct#[]=` method ([#73](https://github.com/yuki24/did_you_mean/pull/73)):
```ruby
Struct.new(:foo).new[:fooo]
# => NameError: no member 'fooo' in struct
# Did you mean? foo
# foo=
```
- Added a public interface for the gem's spell checker:
```ruby
DidYouMean::SpellChecker.new(dictionary: ['email', 'fail', 'eval']).correct('meail')
# => ['email']
```
- Methods defined on `nil` by default are no longer suggested. Note that methods, defined after the gem is loaded, will still be suggested (e.g. ActiveSupport).
#### Bug Fixes
- Fixed a bug where private method names were added to the dictionary when an argument was passed in to a public method. Use the `NoMethodError#private_call?` method instead ([0a1b761](https://github.com/yuki24/did_you_mean/commit/0a1b7612252055e583a373b473932f789381ca0f))
## [v1.0.3](https://github.com/yuki24/did_you_mean/tree/v1.0.3)
_released at 2017-09-24 07:22:07 UTC_
**This version is compatible with Ruby 2.3 and older**
#### Bug Fixes
- Fixed a bug where `did_you_mean` shows duplicate suggestions when the exception is raised multiple times ([#84](https://github.com/yuki24/did_you_mean/pull/84), [c2e4008](https://github.com/yuki24/did_you_mean/commit/c2e40083cef604c00ccd10efc6d7a5036ad9eb5b))
## [v1.0.2](https://github.com/yuki24/did_you_mean/tree/v1.0.2)
_released at 2016-11-20 18:03:07 UTC_
**This version is compatible with Ruby 2.3 and older**
#### Features
- Experimental features are officially available through `require 'did_you_mean/experimental'`
#### Deprecations
- `require 'did_you_mean/extra_features'` is now deprecated in favor of `require 'did_you_mean/experimental'`
#### Internal Changes
- Replaced the `DidYouMean::SpellCheckable` module with the `DidYouMean::SpellChecker` class. This is a slower implementation but close to the model explained in [this talk](https://speakerdeck.com/yuki24/saving-people-from-typos), more reusable and possibly makes it easier to expose the class as a public interface.
## [v1.0.1](https://github.com/yuki24/did_you_mean/tree/v1.0.1)
_released at 2016-05-15 05:17:22 UTC_
#### Bug Fixes
- Fixed a bug where the gem suggests what is actually typed by the user: [1c52c88](https://github.com/yuki24/did_you_mean/commit/1c52c887c62b0921e799f94bcc4a846dc7cbc057)
- Fixed features that didn't work on JRuby 9.1.0.0: [dc48dde](https://github.com/yuki24/did_you_mean/commit/dc48dde1b2a8f05aab1fcf897e1cb3075a206f53), [4de23f8](https://github.com/yuki24/did_you_mean/commit/4de23f880502c80c5f321371d39c08bb0fa34040), [00e3059](https://github.com/yuki24/did_you_mean/commit/00e305971060d150fae4817b5e895d6478b37579). The local variable name correction is still disabled. Also see: [jruby/jruby#3480](https://github.com/jruby/jruby/issues/3480)
## [v1.0.0](https://github.com/yuki24/did_you_mean/tree/v1.0.0)
_released at 2015-12-25 05:13:04 UTC_
#### Features
- Introduced a [verbose formatter](https://github.com/yuki24/did_you_mean#verbose-formatter)
- Introduced an easy way to enabling [experimental features](https://github.com/yuki24/did_you_mean#experimental-features)
#### Bug Fixes
- Fixed a bug where the Jaro-Winkler implementation returns the wrong distance when 2 identical strings are given. fixes [#58](https://github.com/yuki24/did_you_mean/pull/58)
#### Internal Changes
- Slightly changed the spell checking algorithm. Take a look at [e2f5b24](https://github.com/yuki24/did_you_mean/commit/e2f5b2437f967565e4830eab6077f73ae166e0a7) for more details. fixes [#60](https://github.com/yuki24/did_you_mean/issues/60)
## [v1.0.0.rc1](https://github.com/yuki24/did_you_mean/tree/v1.0.0.rc1)
_released at 2015-12-25 05:02:25 UTC_
#### Internal Chagens
- No longer uses `TracePoint` API by default. fixes [#55](https://github.com/yuki24/did_you_mean/issues/55) and [#56](https://github.com/yuki24/did_you_mean/issues/56)
## [v1.0.0.beta3](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta3)
_released at 2015-12-25 04:56:13 UTC_
#### Internal Changes
- Use the `frozen-string-literal` pragma rather than calling `.freeze` everywhere
- Use the `NameError#receiver` method in `DidYouMean:: ClassNameChecker` to know the namespace where the constant call is made
- Refactored the `SpellCheckerTest`
## [v1.0.0.beta2](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta2)
_released at 2015-12-25 04:50:36 UTC_
#### Bug Fixes
- Fixed a bug where the gem doesn't install properly on Ruby 2.3.0dev
## [v1.0.0.beta1](https://github.com/yuki24/did_you_mean/tree/v1.0.0.beta1)
_released at 2015-12-25 05:27:53 UTC_
#### Breaking Changes
- Dropped support for MRIs older than 2.3, JRuby and Rubinus
#### Internal Changes
- The C extension has been removed since the `NameError#receiver` method has become part of the MRI 2.3
- The interception gem has been removed from the dependencies
- Removed code that was needed to support multiple Ruby implementations
## [v0.10.0](https://github.com/yuki24/did_you_mean/tree/v0.10.0)
_released at 2015-08-21 06:44:11 UTC_
#### Features
- Now it corrects an instance variable name if the ivar name is mistyped and `NoMethodError` is raised:
```ruby
@number = 1
@nubmer.zero?
# => NoMethodError: undefined method `zero?' for nil:NilClass
#
# Did you mean? @number
#
```
- Support for JRuby 9.0.0.0
- Prefix-based correction ( [@tjohn](https://github.com/tjohn), [#50](https://github.com/yuki24/did_you_mean/issues/50 "Match start of method name"), [#49](https://github.com/yuki24/did_you_mean/issues/49 "Use Jaro distance instead of Jaro-Winkler distance"))
- Correction search is about 75% faster than 0.9.10
#### Breaking Changes
- The ActiveRecord integration has been removed
## [v0.9.10](https://github.com/yuki24/did_you_mean/tree/v0.9.10)
_released at 2015-05-14 03:04:47 UTC_
#### Bug Fixes
- Fixed a bug where a duplicate "did you mean?" message was appended each time `#to_s` is called ( [@danfinnie](https://github.com/danfinnie), [#51](https://github.com/yuki24/did_you_mean/issues/51 "Duplicate output for constants in separate gem"))
## [v0.9.9](https://github.com/yuki24/did_you_mean/tree/v0.9.9)
_released at 2015-05-13 03:48:19 UTC_
#### Features
- Order word suggestions based on Levenshtein distance ( [@tleish](https://github.com/tleish), [#31](https://github.com/yuki24/did_you_mean/pull/31))
#### Internal Changes
- Reduce memory allocation by about 40%
- Speed up Levenshtein distance calculation by about 40%
- The Java extension has been replaced with a pure JRuby implementation
## [v0.9.8](https://github.com/yuki24/did_you_mean/tree/v0.9.8)
_released at 2015-04-12 01:55:27 UTC_
#### Internal Changes
- Speed up Levenshtein by 50% and reduce 97% of memory usage
## [v0.9.7](https://github.com/yuki24/did_you_mean/tree/v0.9.7)
_released at 2015-04-02 04:20:26 UTC_
#### Bug Fixes
- Fixed an issue where _did\_you\_mean_ doesn't install on JRuby properly.
## [v0.9.6](https://github.com/yuki24/did_you_mean/tree/v0.9.6)
_released at 2015-01-24 23:19:27 UTC_
#### Bug Fixes
- Fixed a bug where did\_you\_mean incorrectly suggests protected methods when it just isn't callable ( [@glittershark](https://github.com/glittershark), [#34](https://github.com/yuki24/did_you_mean/issues/34 "Did\_you\_mean incorrectly called when attempting to call protected/private method"))
## [v0.9.5](https://github.com/yuki24/did_you_mean/tree/v0.9.5)
_released at 2015-01-07 12:41:23 UTC_
#### Bug Fixes
- Whitelist `#safe_constantize` method from `ActiveSupport::Inflector` to avoid significant performance slowdown ( [@tleish](https://github.com/tleish), [#19](https://github.com/yuki24/did_you_mean/issues/19 "Significant Slowdown when Using Debugger"), [#20](https://github.com/yuki24/did_you_mean/pull/20 "Whitelisting safe\_constantize (ActiveSupport::Inflector) method"))
## [v0.9.4](https://github.com/yuki24/did_you_mean/tree/v0.9.4)
_released at 2014-11-19 20:00:00 UTC_
#### Bug Fixes
- Fixed a bug where no suggestions will be made on JRuby
## [v0.9.3](https://github.com/yuki24/did_you_mean/tree/v0.9.3)
_released at 2014-11-18 03:50:11 UTC_
**This version has been yanked from rubygems.org as it doesn't work with jRuby at all. Please upgrade to 0.9.4 or higher as soon as possible.**
#### Internal Changes
- Replaced the crazy C extension with a so much better one (thanks to [@nobu](https://github.com/nobu)!)
## [v0.9.2](https://github.com/yuki24/did_you_mean/tree/v0.9.2)
_released at 2014-11-17 15:32:33 UTC_
#### Bug Fixes
- Fixed a bug where did\_you\_mean doesn't compile on Ruby 2.1.2/2.1.5 ( [#16](https://github.com/yuki24/did_you_mean/issues/16 "Gem building failed on Debian 6.0.10 x86\_64"))
## [v0.9.1](https://github.com/yuki24/did_you_mean/tree/v0.9.1)
_released at 2014-11-16 18:54:24 UTC_
**This version has been yanked from rubygems.org as it doesn't compile on Ruby 2.1.2 and 2.1.5. Please upgrade to 0.9.4 or higher as soon as possible.**
#### Internal Changes
- Shrink the gem size by removing unneeded ruby header files.
- Now it forces everyone to upgrade the gem when they upgrade Ruby to a new version. This avoids introducing a bug like [#14](https://github.com/yuki24/did_you_mean/issues/14 "Compatibility with `letter\_opener` gem").
## [v0.9.0](https://github.com/yuki24/did_you_mean/tree/v0.9.0)
_released at 2014-11-09 01:26:31 UTC_
#### Features
- did\_you\_mean now suggests instance variable names if `@` is missing ( [#12](https://github.com/yuki24/did_you_mean/issues/12 "Suggest instance- and class-vars"), [39d1e2b](https://github.com/yuki24/did_you_mean/commit/39d1e2bd66d6ff8acbc4dd5da922fc7e5fcefb20))
```ruby
@full_name = "Yuki Nishijima"
first_name, last_name = full_name.split(" ")
# => NameError: undefined local variable or method `full_name' for main:Object
#
# Did you mean? @full_name
#
```
#### Bug Fixes
- Fixed a bug where did\_you\_mean changes some behaviours of Ruby 2.1.3/2.1.4 installed on Max OS X ( [#14](https://github.com/yuki24/did_you_mean/issues/14 "Compatibility with `letter\_opener` gem"), [44c451f](https://github.com/yuki24/did_you_mean/commit/44c451f8c38b11763ba28ddf1ceb9696707ccea0), [9ebde21](https://github.com/yuki24/did_you_mean/commit/9ebde211e92eac8494e704f627c62fea7fdbee16))
- Fixed a bug where sometimes `NoMethodError` suggests duplicate method names ( [9865cc5](https://github.com/yuki24/did_you_mean/commit/9865cc5a9ce926dd9ad4c20d575b710e5f257a4b))
## [v0.8.0](https://github.com/yuki24/did_you_mean/tree/v0.8.0)
_released at 2014-10-27 02:03:13 UTC_
**This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.**
#### Features
- JRuby support!
#### Bug Fixes
- Fixed a bug where did\_you\_mean unexpectedly disables [better\_errors](https://github.com/charliesome/better_errors)'s REPL
- Replaced [binding\_of\_caller](https://github.com/banister/binding_of_caller) dependency with [interception](https://github.com/ConradIrwin/interception)
- Fixed the wrong implementation of Levenshtein algorithm ( [#2](https://github.com/yuki24/did_you_mean/pull/2 "Fix bug of DidYouMean::Levenshtein#min3."), [@fortissimo1997](https://github.com/fortissimo1997))
## [v0.7.0](https://github.com/yuki24/did_you_mean/tree/v0.7.0)
_released at 2014-09-26 03:37:18 UTC_
**This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.**
#### Features
- Added support for Ruby 2.1.3, 2.2.0-preview1 and ruby-head
- Added support for ActiveRecord 4.2.0.beta1
- Word searching is now about 40% faster than v0.6.0
- Removed `text` gem dependency
- Better output on pry and Rspec
#### Internal Changes
- A lot of internal refactoring
## [v0.6.0](https://github.com/yuki24/did_you_mean/tree/v0.6.0)
_released at 2014-05-18 00:23:24 UTC_
**This version has been yanked from rubygems.org as it has a serious bug with Ruby 2.1.3 and 2.1.4 installed on Max OS X. Please upgrade to 0.9.4 or higher as soon as possible.**
#### Features
- Added basic support for constants. Now you'll see class name suggestions when you misspelled a class names/module names:
```ruby
> Ocject
# => NameError: uninitialized constant Ocject
#
# Did you mean? Object
#
```
#### Bug Fixes
- Fixed a bug where did\_you\_mean segfaults on Ruby head(2.2.0dev)
## [v0.5.0](https://github.com/yuki24/did_you_mean/tree/v0.5.0)
_released at 2014-05-10 17:59:54 UTC_
#### Features
- Added support for Ruby 2.1.2
## [v0.4.0](https://github.com/yuki24/did_you_mean/tree/v0.4.0)
_released at 2014-04-20 02:10:31 UTC_
#### Features
- did\_you\_mean now suggests a similar attribute name when you misspelled it.
```ruby
User.new(flrst_name: "wrong flrst name")
# => ActiveRecord::UnknownAttributeError: unknown attribute: flrst_name
#
# Did you mean? first_name: string
#
```
#### Bug Fixes
- Fixed a bug where did\_you\_mean doesn't work with `ActiveRecord::UnknownAttributeError`
## [v0.3.1](https://github.com/yuki24/did_you_mean/tree/v0.3.1)
_released at 2014-03-20 23:16:20 UTC_
#### Features
- Changed output for readability.
- Made the spell checking algorithm slight better to find the correct method.
## [v0.3.0](https://github.com/yuki24/did_you_mean/tree/v0.3.0)
_released at 2014-03-20 23:13:13 UTC_
#### Features
- Added support for Ruby 2.1.1 and 2.2.0(head).
## [v0.2.0](https://github.com/yuki24/did_you_mean/tree/v0.2.0)
_released on 2014-03-20 23:12:13 UTC_
#### Features
- did\_you\_mean no longer makes Ruby slow.
#### Breaking Changes
- dropped support for JRuby and Rubbinious.
## [v0.1.0: First Release](https://github.com/yuki24/did_you_mean/tree/v0.1.0)
_released on 2014-03-20 23:11:14 UTC_
- Now you will have "did you mean?" experience in Ruby!
- but still very experimental since this gem makes Ruby a lot slower.
did_you_mean-1.2.0/README.md 0000644 0000041 0000041 00000006247 13221505156 015466 0 ustar www-data www-data # did_you_mean [](https://rubygems.org/gems/did_you_mean) [](https://travis-ci.org/yuki24/did_you_mean)
## Installation
Ruby 2.3 and later ships with this gem and it will automatically be `require`d when a Ruby process starts up. No special setup is required.
## Examples
### NameError
#### Correcting a Misspelled Method Name
```ruby
methosd
# => NameError: undefined local variable or method `methosd' for main:Object
# Did you mean? methods
# method
```
#### Correcting a Misspelled Class Name
```ruby
OBject
# => NameError: uninitialized constant OBject
# Did you mean? Object
```
#### Suggesting an Instance Variable Name
```ruby
@full_name = "Yuki Nishijima"
first_name, last_name = full_name.split(" ")
# => NameError: undefined local variable or method `full_name' for main:Object
# Did you mean? @full_name
```
#### Correcting a Class Variable Name
```ruby
@@full_name = "Yuki Nishijima"
@@full_anme
# => NameError: uninitialized class variable @@full_anme in Object
# Did you mean? @@full_name
```
### NoMethodError
```ruby
full_name = "Yuki Nishijima"
full_name.starts_with?("Y")
# => NoMethodError: undefined method `starts_with?' for "Yuki Nishijima":String
# Did you mean? start_with?
```
### KeyError
```ruby
hash = {foo: 1, bar: 2, baz: 3}
hash.fetch(:fooo)
# => KeyError: key not found: :fooo
# Did you mean? :foo
```
## Experimental Features
Aside from the basic features above, the `did_you_mean` gem comes with experimental features. They can be enabled by calling `require 'did_you_mean/experimental'`.
Note that **these experimental features should never be enabled in production as they would impact Ruby's performance and use some unstable Ruby APIs.**
### Correcting an Instance Variable When It's Incorrectly Spelled
```ruby
require 'did_you_mean/experimental'
@full_name = "Yuki Nishijima"
@full_anme.split(" ")
# => NoMethodError: undefined method `split' for nil:NilClass
# Did you mean? @full_name
```
### Displaying a Warning When `initialize` is Incorrectly Spelled
```ruby
require 'did_you_mean/experimental'
class Person
def intialize
...
end
end
# => warning: intialize might be misspelled, perhaps you meant initialize?
```
## Verbose Formatter
This verbose formatter changes the error message format to take more lines/spaces so it'll be slightly easier to read the suggestions. This formatter can totally be used in any environment including production.
```ruby
OBject
# => NameError: uninitialized constant OBject
# Did you mean? Object
require 'did_you_mean/verbose'
OBject
# => NameError: uninitialized constant OBject
#
# Did you mean? Object
#
```
## Contributing
1. Fork it (http://github.com/yuki24/did_you_mean/fork)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Make sure all tests pass (`bundle exec rake`)
5. Push to the branch (`git push origin my-new-feature`)
6. Create new Pull Request
## License
Copyright (c) 2014-16 Yuki Nishijima. See MIT-LICENSE for further details.