[前][次][番号順一覧][スレッド一覧]

ruby-changes:58304

From: Yusuke <ko1@a...>
Date: Fri, 18 Oct 2019 12:21:15 +0900 (JST)
Subject: [ruby-changes:58304] c3b64a86bc (master): lib/optparse.rb: Show a did_you_mean hint for unknown option

https://git.ruby-lang.org/ruby.git/commit/?id=c3b64a86bc

From c3b64a86bcd7773c081f5049115c57ec73d7a76a Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Wed, 16 Oct 2019 16:31:41 +0900
Subject: lib/optparse.rb: Show a did_you_mean hint for unknown option

```
require 'optparse'

OptionParser.new do |opts|
  opts.on("-f", "--foo", "foo") {|v| }
  opts.on("-b", "--bar", "bar") {|v| }
  opts.on("-c", "--baz", "baz") {|v| }
end.parse!
```

```
$ ruby test.rb --baa
Traceback (most recent call last):
test.rb:7:in `<main>': invalid option: --baa (OptionParser::InvalidOption)
Did you mean?  baz
               bar
```

diff --git a/lib/optparse.rb b/lib/optparse.rb
index 25e262a..9ed7b72 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -866,6 +866,10 @@ class OptionParser https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L866
       __send__(id).complete(opt, icase, *pat, &block)
     end
 
+    def get_candidates(id)
+      yield __send__(id).keys
+    end
+
     #
     # Iterates over each option, passing the option to the +block+.
     #
@@ -1766,7 +1770,17 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L1770
     end
     raise AmbiguousOption, catch(:ambiguous) {
       visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
-      raise InvalidOption, opt
+      if defined? DidYouMean::SpellChecker
+        all_candidates = []
+        visit(:get_candidates, typ) do |candidates|
+          all_candidates.concat(candidates)
+        end
+        all_candidates.select! {|cand| cand.is_a?(String) }
+        suggestions = DidYouMean::SpellChecker.new(dictionary: all_candidates).correct(opt)
+        raise InvalidOption.new(opt, "\nDid you mean?  #{suggestions.join("\n               ")}")
+      else
+        raise InvalidOption, opt
+      end
     }
   end
   private :complete
@@ -2048,7 +2062,7 @@ XXX https://github.com/ruby/ruby/blob/trunk/lib/optparse.rb#L2062
     # Default stringizing method to emit standard error message.
     #
     def message
-      reason + ': ' + args.join(' ')
+      reason + ': ' + args.join(" ").gsub(/\s+$/, "")
     end
 
     alias to_s message
diff --git a/test/optparse/test_did_you_mean.rb b/test/optparse/test_did_you_mean.rb
new file mode 100644
index 0000000..4d8e272
--- /dev/null
+++ b/test/optparse/test_did_you_mean.rb
@@ -0,0 +1,22 @@ https://github.com/ruby/ruby/blob/trunk/test/optparse/test_did_you_mean.rb#L1
+# frozen_string_literal: false
+require_relative 'test_optparse'
+require "did_you_mean" rescue return
+
+class TestOptionParser::DidYouMean < TestOptionParser
+  def setup
+    super
+    @opt.def_option("--foo", Integer) { |v| @foo = v }
+    @opt.def_option("--bar", Integer) { |v| @bar = v }
+    @opt.def_option("--baz", Integer) { |v| @baz = v }
+  end
+
+  def test_did_you_mean
+    assert_raise(OptionParser::InvalidOption) do
+      begin
+        @opt.permute!(%w"--baa")
+      ensure
+        assert_equal("invalid option: --baa\nDid you mean?  baz\n               bar", $!.message)
+      end
+    end
+  end
+end
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]