Haris Krajina
Haris Krajina

Reputation: 15296

Routing CLI commands in Ruby

I am looking for gem or idea on how to eleagntly route CLI commands in Ruby. Thor is solution that I am already using and it is great in sense that it allows you to build specific command line structure. Example:

person show 1               => Info about person Id 1
person show all             => Show all people
person delete 2             => Delete person with Id 2 

Thor is great at this and I highly recommend it. Now I have a need for more semantic oriented CLI structure so for example:

show person 1                => Same as 'show person 1'
show people                  => Same as 'show person all'
etc...

Thor does not support this so I need to implement it. I will build layer above thor which would pre-process commands and send them to thor. I am looking best way to do it. I am hopping to avoid messy structure of case/when/when.... Thank you.

Upvotes: 1

Views: 171

Answers (4)

Yuri Karpovich
Yuri Karpovich

Reputation: 402

You should try console_runner gem. The best thing about it you don't need to write new code. You can execute any existing Ruby file from command line. All you need is to add annotations (YARD-like syntax) to Class and methods you want to make executable:

# @runnable This tool can talk to you. Run it when you are lonely.
#   Written in Ruby.  
class MyClass

    def initialize
      @hello_msg = 'Hello' 
      @bye_msg = 'Good Bye!' 
    end

    # @runnable Say 'Hello' to you.
    # @param [String] name Your name
    def say_hello(name)
      puts @hello_msg + ', ' + name
    end

    # @runnable Say 'Good Bye' to you.
    def say_bye
      puts @bye_msg
    end

end

The gem will generate CLI interface for you.

$ c_run /projects/example/my_class.rb  --help
Options:
  --debug    Run in debug mode.

This tool can talk to you. Run it when you are lonely.
Written in Ruby.

Available actions:
        - say_hello
                Say 'Hello' to you.
        - say_bye
                Say 'Good Bye' to you.

You could use parameters as well. Run MyClass#say_hello:

$ c_run /projects/example/my_class.rb say_hello --name 'Yuri'
 -> Hello, Yuri

Run MyClass#say_bye:

$ c_run /projects/example/my_class.rb say_bye
 -> Good Bye!

Upvotes: 0

nuaavee
nuaavee

Reputation: 1356

Try cliqr https://github.com/anshulverma/cliqr. The README has a great use case example.

Upvotes: 0

davetron5000
davetron5000

Reputation: 24891

A simple way to do this would be to create two executables: one is your current one person, that implements all the functionality.

The second one could be called something like 'person-app` and would be designed to be symlinked. For example

> ln -s person-app show
> ln -s person-app delete
> whatever else

So, you now have several symlinks to the same app, person-app. person-app can detect which symlink was used by examining $0, and then formulate a call to person:

case File.basename($0)
when 'show' then system("person show #{ARGV.join(' ')}")
when 'delete' then system("person delete #{ARGV.join(' ')}")
end

And so forth. It's kinda hacky, but it should work and keep code duplication to a minimum.

Upvotes: 0

patrick_corrigan
patrick_corrigan

Reputation: 899

I highly recommend cocaine! https://rubygems.org/gems/cocaine

Upvotes: 1

Related Questions