Ruby thor

From wikinotes

Thor lets you define/parse commandline arguments.

Documentation

method options https://github.com/erikhuda/thor/wiki/Method-Options
github https://github.com/erikhuda/thor
wiki https://github.com/erikhuda/thor/wiki
website http://whatisthor.com/

Usage

System

Thor captures commands defined in ruby files anywhere in your project matching:

  • *.thor
  • Thorfile

They can then be referred to from the commandline.
Pascal-Case is converted to Snake-Case

thor class_name:method_name [args..]

Commandline

thor      ${task}:${method} [args...]
thor help ${task}:${method}

Code

## cli.rb

requires 'thor'

class CommandlineInterface < Thor
  desc "print_hi NAME", "prints hello to provided user"
  def print_hi(name)
    puts "Hello, #{name}"
  end
end


Syntax

Executables

## file.rb

require 'thor'

class Cli < Thor
  desc "print_hi NAME", "prints hello to provided user"
  def print_hi
    puts "hello"
  end
end

Cli.start  # <-- treat this script as a standalone executable
./file.rb cli:print_hi

Required Params

class Cli < Thor
  desc "print_hi NAME", "prints hello to provided user"
  def print_hi(name)
    puts "hello, #{name}"
  end
end

Optional Params

method_option: Optional Keyword Arguments are exposed as options.


class Cli < Thor
  desc "print_hi NAME", "prints hello to provided user"

  method_option :prefix, 
    :aliases => "-p", 
    :default => "",
    :desc => "Assign a prefix (ex: mr, mrs)"

  def print_hi(name)
    prefix = options[:prefix]
    puts "hello, #{prefix} #{name}"
  end
end

class_option: You can also define optional arguments for all methods.


class Cli < Thor
  desc "print_hi NAME", "prints hello to provided user"

  class_option :verbose, 
    :aliases => "-v", 
    :type => :boolean,
    :default => false,
    :desc => "Use verbose logging"

  def print_hi(name)
    if options[:verbose]
      puts "printing hello..."
    end
    puts "hello, #{name}"
  end
end

Invoke Methods

Thor comes with an invoke system.

It lets you guarantee that methods are only ever called once-per-commandline invocation.

class Cli < Thor

  desc "print_hi NAME", "prints hello to provided user"
  def print_hi(name)
    invoke :print_bye      # <-- 'print_bye' is called
    puts "hello, #{name}"
    invoke :print_bye      # <-- 'print_bye' not called here (already called)
  end

  def print_bye
    puts "bye!"
  end
end

Subcommands

Git-Style Subcommands can be defined in other files.

## project/server.rb
require 'thor'

class Server < Thor
  def start
    # ..
  end
end
## project/cli.rb
require 'thor'
require "server"

class MyApp < Thor
  desc "parentcommand SUBCOMMAND", "Some Parent Command"
  subcommand "server", Server
end

MyApp.start
./cli.rb server start

Namespaces

You can add namespaces overtop of your CLI classes.

module Program
  class Cli < Thor
  
    desc "print_hi NAME", "prints hello to provided user"
    def print_hi(name)
      invoke :print_bye      # <-- 'print_bye' is called
      puts "hello, #{name}"
      invoke :print_bye      # <-- 'print_bye' not called here (already called)
    end
  
    def print_bye
      puts "bye!"
    end
  end
end
thor program:cli:print_hi "Alex"