Reputation: 15296
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
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
Reputation: 1356
Try cliqr
https://github.com/anshulverma/cliqr. The README has a great use case example.
Upvotes: 0
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
Reputation: 899
I highly recommend cocaine! https://rubygems.org/gems/cocaine
Upvotes: 1