# Golf on CLI code

**URL:** <https://www.ruby-forum.com/t/golf-on-cli-code/191122>\
**Category:** Ruby\
**Created:** [July 6, 2010, 1:30am UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122 "2010-07-06T01:30:04Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 6, 2010, 1:30am UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/1 "2010-07-06T01:30:04Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 6, 2010, 6:47am UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/2 "2010-07-06T06:47:15Z")

</div>

Intransition wrote:

> ```
> 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

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 6, 2010, 1:26pm UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/3 "2010-07-06T13:26:32Z")

</div>

On Tue, Jul 6, 2010 at 4:59 AM, Intransition [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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

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

martin

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 13, 2010, 5:25am UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/4 "2010-07-13T05:25:43Z")

</div>

On Jul 6, 6:24 am, Martin DeMello [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > 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] }

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 13, 2010, 2:50am UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/5 "2010-07-13T02:50:36Z")

</div>

Thanks Joel and Martin. Amazingly concise answers – it’s amazes me  
sometimes how small a piece of code can get in Ruby 🙂

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.

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 13, 2010, 5:35pm UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/6 "2010-07-13T17:35:50Z")

</div>

On Jul 12, 10:20 pm, w\_a\_x\_man [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > \<=\> a[1].size }  
> > > lookup = registry.map(&:cli).sort\_by(&:size).reverse  
> > > 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 }

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [July 13, 2010, 7:00pm UTC](https://www.ruby-forum.com/t/golf-on-cli-code/191122/7 "2010-07-13T19:00:46Z")

</div>

On Jul 13, 10:32 am, w\_a\_x\_man [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > > def command(argv)  
> > > > and using the ever-handy symbol.to\_proc
> 
> > > # 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 }

Should be

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