Golf on CLI code

I have a registry (array) of CLI classes. Each class has a class
method cli() that returns an array of strings or regular expressions
to match against ARGV to see if it is the chosen cli. Eg.

  class FooList << CLIBase
    def self.cli ; ['foo', 'list'] ; end
    ...
  end

So if someone puts on the command line:

  $ foo list

Then the above class would match for it. I wrote the algorithm to
handle this, but I think it's Ugh-ly. Wondering if the smart folk here
might play a game of golf on it.

   def command(argv)
      lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
<=> a[1].size }
      x = lookup.find do |cc, cli|
        t = true
        cli.each_with_index do |r, i|
          t = t && (r === argv[i])
        end
        t
      end
      cmdc = x[0]
      argv = argv[x[1].size..-1]
      return cmdc, argv
    end

Intransition wrote:

   def command(argv)
      lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
<=> a[1].size }
      x = lookup.find do |cc, cli|
        t = true
        cli.each_with_index do |r, i|
          t = t && (r === argv[i])
        end
        t
      end
      cmdc = x[0]
      argv = argv[x[1].size..-1]
      return cmdc, argv
    end

Untested:

   def command(argv)
     lookup = registry.sort_by {|cc| cc.cli.size}
     cmdc = lookup.find do |cc|
       cc.cli.zip(argv).all? do |r,arg|
         r === arg
       end
     end
     return cmdc, argv[cmdc.cli.size..-1]
   end

The following (assuming it works!) would be more compact still:

   class Symbol
     alias old_to_proc to_proc
     def to_proc
       case self
       when :=== # etc.
         proc {|x,y| x === y}
       else
         old_to_proc
       end
     end
   end

   def command(argv)
     lookup = registry.sort_by {|cc| cc.cli.size}
     cmdc = lookup.find do |cc|
       cc.cli.zip(argv).all?(&:===)
     end
     return cmdc, argv[cmdc.cli.size..-1]
   end

def command(argv)
lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
<=> a[1].size }

at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by
{|a| -a[1].size}

also, you're never using cc, so why carry it around?

lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size}

and using the ever-handy symbol.to_proc

lookup = registry.map(&:cli).sort_by(&:size).reverse

 x = lookup\.find do |cc, cli|
   t = true
   cli\.each\_with\_index do |r, i|
     t = t &amp;&amp; \(r === argv\[i\]\)
   end
   t
 end

# untested
lookup.find do |cli|
  cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)}
end

 cmdc = x\[0\]
 argv = argv\[x\[1\]\.size\.\.\-1\]
 return cmdc, argv

end

martin

···

On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transfire@gmail.com> wrote:

Thanks Joel and Martin. Amazingly concise answers -- it's amazes me
sometimes how small a piece of code can get in Ruby :slight_smile:

I haven't gotten back to the particular code I need this for yet which
is why I haven't responded until now, but should be back to it soon
and I'll let you know how it worked out.

> def command(argv)
> lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
> <=> a[1].size }

at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by
{|a| -a[1].size}

also, you're never using cc, so why carry it around?

lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size}

and using the ever-handy symbol.to_proc

lookup = registry.map(&:cli).sort_by(&:size).reverse

> x = lookup.find do |cc, cli|
> t = true
> cli.each_with_index do |r, i|
> t = t && (r === argv[i])
> end
> t
> end

# untested
lookup.find do |cli|
cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)}
end

lookup.find{|cli| cli == argv[0,cli.size] }

···

On Jul 6, 6:24 am, Martin DeMello <martindeme...@gmail.com> wrote:

On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transf...@gmail.com> wrote:

> cmdc = x[0]
> argv = argv[x[1].size..-1]
> return cmdc, argv
> end

martin

That won't work if cli contains a regexp.

lookup.find{|cli| cli.zip(argv).all?{|a,b| a == b }

···

On Jul 12, 10:20 pm, w_a_x_man <w_a_x_...@yahoo.com> wrote:

On Jul 6, 6:24 am, Martin DeMello <martindeme...@gmail.com> wrote:

> On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transf...@gmail.com> wrote:

> > def command(argv)
> > lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
> > <=> a[1].size }

> at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by
> {|a| -a[1].size}

> also, you're never using cc, so why carry it around?

> lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size}

> and using the ever-handy symbol.to_proc

> lookup = registry.map(&:cli).sort_by(&:size).reverse

> > x = lookup.find do |cc, cli|
> > t = true
> > cli.each_with_index do |r, i|
> > t = t && (r === argv[i])
> > end
> > t
> > end

> # untested
> lookup.find do |cli|
> cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)}
> end

lookup.find{|cli| cli == argv[0,cli.size] }

Should be

lookup.find{|cli| cli.zip(argv).all?{|a,b| a === b }}

···

On Jul 13, 10:32 am, w_a_x_man <w_a_x_...@yahoo.com> wrote:

On Jul 12, 10:20 pm, w_a_x_man <w_a_x_...@yahoo.com> wrote:

> On Jul 6, 6:24 am, Martin DeMello <martindeme...@gmail.com> wrote:

> > On Tue, Jul 6, 2010 at 4:59 AM, Intransition <transf...@gmail.com> wrote:

> > > def command(argv)
> > > lookup = registry.map{ |cc| [cc, cc.cli] }.sort{ |a,b| b[1].size
> > > <=> a[1].size }

> > at the least this should be registry.map {|cc| [cc, cc.cli]}.sort_by
> > {|a| -a[1].size}

> > also, you're never using cc, so why carry it around?

> > lookup = registry.map {|cc| cc.cli}.sort_by {|cli| -cli.size}

> > and using the ever-handy symbol.to_proc

> > lookup = registry.map(&:cli).sort_by(&:size).reverse

> > > x = lookup.find do |cc, cli|
> > > t = true
> > > cli.each_with_index do |r, i|
> > > t = t && (r === argv[i])
> > > end
> > > t
> > > end

> > # untested
> > lookup.find do |cli|
> > cli.zip(argv).inject(true) {|e, (i, j)| e && (i === j)}
> > end

> lookup.find{|cli| cli == argv[0,cli.size] }

That won't work if cli contains a regexp.

lookup.find{|cli| cli.zip(argv).all?{|a,b| a == b }