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 <james / grayproductions.net> 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
>
>