Command Line Subcommands in Ruby

Our first program will demonstrate how to create command-line subcommands in Ruby. Here’s the full source code:

require 'optparse'

# Define the FooCommand class
class FooCommand
  def initialize
    @options = {}
    @parser = OptionParser.new do |opts|
      opts.banner = "Usage: foo [options]"
      opts.on("-e", "--enable", "Enable") { @options[:enable] = true }
      opts.on("-n", "--name NAME", "Name") { |n| @options[:name] = n }
    end
  end

  def run(args)
    @parser.parse!(args)
    puts "subcommand 'foo'"
    puts "  enable: #{@options[:enable]}"
    puts "  name: #{@options[:name]}"
    puts "  tail: #{args}"
  end
end

# Define the BarCommand class
class BarCommand
  def initialize
    @options = {}
    @parser = OptionParser.new do |opts|
      opts.banner = "Usage: bar [options]"
      opts.on("-l", "--level LEVEL", Integer, "Level") { |l| @options[:level] = l }
    end
  end

  def run(args)
    @parser.parse!(args)
    puts "subcommand 'bar'"
    puts "  level: #{@options[:level]}"
    puts "  tail: #{args}"
  end
end

# Main program
if ARGV.empty?
  puts "expected 'foo' or 'bar' subcommands"
  exit(1)
end

case ARGV[0]
when "foo"
  FooCommand.new.run(ARGV[1..-1])
when "bar"
  BarCommand.new.run(ARGV[1..-1])
else
  puts "expected 'foo' or 'bar' subcommands"
  exit(1)
end

This Ruby script demonstrates how to create command-line subcommands using the OptionParser class. We define two subcommands, ‘foo’ and ‘bar’, each with its own set of options.

To run the program, save it as command_line_subcommands.rb and use ruby:

$ ruby command_line_subcommands.rb foo --enable --name=joe a1 a2
subcommand 'foo'
  enable: true
  name: joe
  tail: ["a1", "a2"]

Now try the ‘bar’ subcommand:

$ ruby command_line_subcommands.rb bar --level 8 a1
subcommand 'bar'
  level: 8
  tail: ["a1"]

But ‘bar’ won’t accept ‘foo’s flags:

$ ruby command_line_subcommands.rb bar --enable a1
invalid option: --enable
Usage: bar [options]
    -l, --level LEVEL                Level

This example demonstrates how to create a command-line tool with subcommands in Ruby. Each subcommand is implemented as a separate class with its own option parser, allowing for flexible and modular command-line interfaces.

Next, we’ll look at environment variables, another common way to parameterize programs.