From: Krishna Dole Date: 2007-01-22T01:00:22+09:00 Subject: Re: [QUIZ] Method Auto Completion (#110) Last week I was kind of embarrassed that Bob chose to feature my late, poorly commented, somewhat opaque solution, but I certainly appreciate the inclusive spirit of Ruby Quiz. Here's a more timely submission for the auto completion problem. -------------------------------------------------------- class Object def self.abbrev(*args) module_eval <<-EOS @@abbrevs ||= [] @@abbrevs += args def method_missing(m) # abbrev targets themselves are not supposed to be expanded raise NoMethodError if @@abbrevs.include?(m) # which abbrev targets could match m, and which of those correspond to methods? matches = @@abbrevs.select do |sym| sym.to_s.index(m.to_s) == 0 && methods.include?(sym.to_s) end case matches.size when 0 raise NoMethodError when 1 self.send(matches.first) else # multiple matches, pass them back to the user return matches if $TESTING puts matches.join(" ") end end EOS end end -------------------------------------------------------- This code passes the supplied tests, and I also added another test when an earlier version of my code was doing things it shouldn't have: -------------------------------------------------------- # check for unintended effects on other classes class Test3 < Test::Unit::TestCase def setup @foo_class = Class.new { abbrev :start def start; nil end } @bar_class = Class.new { def start; nil end } end def test1 f = @foo_class.new b = @bar_class.new assert_raise NoMethodError do b.send(:sta) end end end -------------------------------------------------------- I don't feel very confident in the approach I've taken, so I'm eager to hear critique and see other solutions. Krishna On 1/19/07, Ruby Quiz wrote: > The three rules of Ruby Quiz: > > 1. Please do not post any solutions or spoiler discussion for this quiz until > 48 hours have passed from the time on this message. > > 2. Support Ruby Quiz by submitting ideas as often as you can: > > http://www.rubyquiz.com/ > > 3. Enjoy! > > Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone > on Ruby Talk follow the discussion. Please reply to the original quiz message, > if you can. > > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= > > by Robert Dober > > Command Line Interfaces very often support command abbreviations The purpose of > this quiz is to automatically dispatch to methods on unambiguous abbreviations, > ask the user for clarification in case of ambiguous abbreviations and raise a > NoMethodError in case of an abbreviation that cannot be matched to any command. > > Behavior of other methods defined in a class shall not be altered. > > Be creative about the interface and about behavior. I have OTOH defined a small > test suite that makes assumptions about the interface and behavior. But the test > suite is only there for your convenience. > > What is said below applies to the test suite and shall in no way inhibit any > alternative ideas. > > class Mine > abbrev :step, :next, :stop > abbrev :exit > end > > Mine.new.e # should resolve to exit > Mine.new.st # should prompt the user > Mine.new.a # should still raise a NoMethodError > > Abbreviation targets themselves are not expanded. > > class Nine > abbrev :hash > abbrev :has > end > > Nine.new.ha # => [:hash, :has] > Nine.new.has # => NoMethodError > > class Nine > def has; 42; end > end > Nine.new.has # => 42 > > In order to allow for automated testing the test code shall not prompt the user > in case of an ambiguous abbreviation but return an array containing all (and > only all) possible completions as symbols. Note that the test suite sets the > global variable $TESTING to a true value for your convenience. > > http://rubyquiz.com/test-abbrev.rb > >