Project

rodish

0.0
A long-lived project that still receives updates
Rodish parses an argv array using a routing tree approach. It is designed to make it easy to implement command line applications that support multiple levels of subcommands, with options at each level.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

Runtime

 Project Readme

Rodish¶ ↑

Rodish parses an argv array using a routing tree approach. It is designed to make it easy to implement command line applications that support multiple levels of subcommands, with options at each level.

Installation¶ ↑

gem install rodish

Resources¶ ↑

Documentation

rodish.jeremyevans.net

Source

github.com/jeremyevans/rodish

Report a Bug

github.com/jeremyevans/rodish/issues

Ask a Question

github.com/jeremyevans/rodish/discussions

Simple Example¶ ↑

Here’s a simple commented example with a single subcommand:

require "rodish"

# This just creates a normal Ruby class.  For each argv parse, Rodish will
# create an instance of this class
class CliExample

  # This allows instances of the class to be instantiated with or without
  # a default person.
  def initialize(default_person=nil)
    @default_person = default_person
  end

  # This installs the Rodish processor into CliExample. It extends the
  # CliExample class with the Rodish::Processor module.
  Rodish.processor(self)

  # Without arguments, the on method configures the root command for
  # the processor.
  on do

    # Provide description for root command
    desc "Example Hello World CLI"

    # This method call creates a hello subcommand of the current/root command.
    on "hello" do

      # Provide description for this subcommand
      desc "Says hello to person or world"

      # This adds a usage string and a -p options for the hello subcommand.
      # The block passed is used to set the options via the optparse library.
      options("cli-example hello [options]") do
        on("-p", "--person=name", "say hello to a specific person")
      end

      # If the given argv is for the hello subcommand, this block will be
      # executed in the context of the CliExample instance.
      run do |opts|
        "Hello #{opts[:person] || @default_person || 'World'}"
      end
    end
  end
end

# This requests Rodish to process the provided argv.  Rodish will determine
# the related command block to execute and execute it.  The return value of
# that block will be returned to the caller.
CliExample.process(["hello"])
# => "Hello World"

# Additional arguments passed to .process are passed to .new.  In this
# example, this sets the default person.
CliExample.process(["hello"], "Adol")
# => "Hello Adol"

# This shows an example of passing an option to a subcommand, and using
# the option value when returning a response.
CliExample.process(["hello", "-p", "Feena"], "Adol")
# => "Hello Feena"

Rodish DSL¶ ↑

Inside the on block with no arguments, you are in the context of the root command. The following methods are available for configuring the processing of the command.

on¶ ↑

The on method adds a subcommand of the current command, and yields to the block to configure the subcommand. All of the methods described in the Rodish DSL section can be executed inside the on block, and arbitrary levels of subcommands are supported.

desc¶ ↑

Provides a description for the command. This description will show up in the help output for the command.

options¶ ↑

The options method sets up an options parser for the current command. The default options parser disallows any options. Options are parsed into a hash, which is yielded to commands (as in the above example).

This method requires a String argument for the usage for the current command. You can also provide a key keyword argument, to put parsed options into a subhash of the main options hash, which can be useful when options are parsed at multiple levels.

A block must be provided, which is executed in the context of a Rodish::OptionParser instance. Rodish::OptionParser is a subclass of Ruby’s standard OptionParser (from optparse), with a few additional methods.

banner¶ ↑

Set the usage banner for the command, without allowing options for the command.

args¶ ↑

The args method sets the number of arguments accepted when running the command. The default for args is 0. You can provide either an Integer to accept a fixed number of arguments, or a Range to allow any number of arguments in that range.

run¶ ↑

The run method sets the block to run for the current command. If the command accepts a fixed number of arguments, those arguments are yielded as the first arguments to the command. If the command accepts a range of argument numbers, then the remaining argv array will be passed as the first argument.

The block will be passed two additional arguments, the options already parsed, and the current Rodish::Command object.

autoload_subcommand_dir¶ ↑

The autoload_subcommand_dir takes a directory, and will autoload subcommands from the given directory. Filenames ending in .rb in this directory will be treated as subcommands, and requiring the file should add the appropriate subcommand.

This allows you to design complex command line programs where only the parts of the program needed to handle the given argv are loaded.

Object Model¶ ↑

Rodish has four main classes/modules:

Rodish::Processor

This is the module that extends the class you load Rodish into. The class becomes a Rodish processor, and contains a reference to the root command for the processor.

Rodish::Command

Handles processing the argv. Contains references to subcommands, similar to a tree.

Rodish::DSL

Used for configuring the Rodish::Command instances.

Rodish::OptionParser

A subclass of Ruby’s standard OptionParser, used for parsing options for commands.

Each Rodish processor has a separate subclass of Command, DSL, and OptionParser.

Plugins¶ ↑

After installing Rodish into a processor, the plugin method can be used to load plugins into the processor. Plugins can change how the processor and related command, DSL, and option parsers work. Each plugin is a module that can contain one or more of the following submodules:

ProcessorMethods

Extends the processor with additional methods

CommandMethods

Module that is included in the Command subclass for the processor.

DSLMethods

Module that is included in the DSL subclass for the processor.

OptionParserMethods

Module that is included in the OptionParser subclass for the processor.

Plugins can also implement singleton before_load and/or after_load methods, which are called before or after loading the plugin modules, respectively.

When loading plugins, you can pass the module instance directly:

class App
  Rodish.processor(self)
  plugin PluginModule
end

However, the typical usage is passing a symbol for the plugin:

class App
  Rodish.processor(self)
  plugin :plugin_name
end

If the plugin has not already been registered, Rodish will require the rodish/plugins/plugin_name file, which should register the plugin. See plugins that ship with Rodish for an example of how to create a plugin.

The following plugins ship with Rodish:

cache_help_output

Cache help output when freezing command.

help_examples

Allow including example help output with command usage.

help_option_values

Allow showing allowed option values for help options.

help_order

Support overriding order of command help sections.

invalid_args_message

Support overriding the message shown when an invalid number of arguments is provided.

is

Adds is method as a shortcut for creating a subcommand with on and run.

post_commands

Adds support for subcommands that appear after arguments (see below).

run_is

Adds run_is method as a shortcut for creating a post subcommand with run_on and run.

skip_option_parsing

Allows for skipping option parsing, treating all elements of argv as arguments.

usages

Get a hash with help output for all commands/subcommands for the processor.

wrap_options_separator

Add wrap method to options parser, for wrapping long separator lines

Post Commands¶ ↑

The post_commands plugin adds support for commands that appear after arguments. It adds the following configuration methods:

run_on¶ ↑

The run_on method is similar to on, except it creates a post subcommand instead of a normal subcommand. Post subcommands allow the run block to parse part of the remaining argv array, and then call a subcommand with the modified (or a new) argv array. You dispatch to post subcommands inside the run block by calling run on the command argument:

on "hello" do
  args(2...)

  run do |argv, opts, command|
    @name = argv.shift
    command.run(self, opts, argv)
  end

  run_on "world" do
    run do
      "Hello #{@name.upcase} World!"
    end
  end
end

# process(%w[hello foo world])
# => "Hello FOO World!"

post_options¶ ↑

The post_options method sets an option parser that is used for post subcommands. This parses options from the argv array that passed to command.run, before calling the related subcommand. Example:

on "hello" do
  args(2...)

  post_options("Usage: hello name [options] subcommand ...") do
    on("-c", "--cap", "capitalize instead of uppercase")
  end

  run do |argv, opts, command|
    @name = argv.shift
    command.run(self, opts, argv)
  end

  run_is "world" do |opts|
    name = opts[:cap] ? @name.capitalize :  @name.upcase
    "Hello #{name} World!"
  end
end

# process(%w[hello foo world])
# => "Hello FOO World!"
# process(%w[hello foo -c world])
# => "Hello Foo World!"

post_banner¶ ↑

Set the usage banner for using post subcommands with the command, without allowing post options for the command.

autoload_post_subcommand_dir¶ ↑

The autoload_post_subcommand_dir operates the same as autoload_subcommand_dir, but it handles post subcommands instead of normal subcommands.

Examples¶ ↑

The tests that ship with Rodish fully cover all of Rodish’s functionality.

If you would like to view a production example using Rodish, which uses most of Rodish’s features, please see UbiCli, which is part of Ubicloud:

History¶ ↑

Rodish was extracted from Ubicloud (github.com/ubicloud/ubicloud), and is the argv processor used in Ubicloud’s command line interface.

Naming¶ ↑

The name Rodish was chosen because Rodish uses an API similar (-ish) to the Roda web framework (roda.jeremyevans.net), and the library is designed for use in applications executed from a shell (sh).

License¶ ↑

MIT

Author¶ ↑

Jeremy Evans <code@jeremyevans.net>