How to create a shell command supporting Ruby?

2019-07-16 14:11发布

问题:

I'm creating a gem in which I would like to be able to make a shell command performing a function in the gem. In a more simple context, I need to create a shell script that performs a Ruby function with options when the shell command is triggered. What is a easiest way to do this?

For example:

$ cow moo

would take a cow gem with a script for the cow command and perform the 'moo' function in the Ruby gem.

If I could, I would also like support for common 'options' formatting in the shell:

$ cow -t moo

Which the above example would take an option and apply a script in Ruby to handle it (in this example -t would print 'moo' twice).

If anyone could help we with this it would be a great help. Thanks!

回答1:

How about using http://visionmedia.github.com/commander/? Never used it before. But it's a gem that makes developing commandline apps easier :) Does the heavy lifting for you.

There is a bunch more over here: https://www.ruby-toolbox.com/categories/CLI_Option_Parsers



回答2:

You could create a regular executable Ruby file named cow containing:

#!/usr/bin/env ruby
require 'cow'

Cow.say ARGV.first

Note the first line, which is the shebang line. It tells your shell which program to use in order to interpret the script. This allows the user to simply call cow instead of ruby $(which cow).

Put your script in the bin directory:

cow/
  bin/
    cow  <- your executable file
  lib/
    cow.rb
    cow/
      say.rb
  cow.gemspec

Now, all you need to do is put that in your gem specification:

Gem::Specification.new 'cow' do |gem|
  gem.executables = %w(bin/cow)
end

During installation, Rubygems will install your gem's binaries somewhere in the user's path, ensuring they can be found.

As for option parsing, the standard library includes optparse, but there are also many gems available.

I created my own option parser, called Acclaim, which I use in my own utilities. Here's a sample:

class Cow::Command < Acclaim::Command
  option :all_caps, '-A', '--all-caps'

  when_called do |options, args|
    text = args.first.to_s
    text.upcase! if options.all_caps?
    Cow.say text
  end
end

In order to test your application, you can simply execute your script:

$ pwd
~/projects/cow
$ ./bin/cow moo
# output here...

However, this requires that you build your gem from the specification and install it locally every time you want to test your changes:

ruby -I ./lib -r cow -e 'puts Cow.version'
0.0.1
gem build cow.gemspec && gem install cow-0.0.1.gem

Bundler makes life easier by inserting your code into the load path automatically. You just have to run your executable through Bundler:

$ bundle exec ./bin/cow moo
# output here...