Class: Jewelbox::Command

Inherits:
Object show all
Defined in:
lib/jewelbox/command.rb

Overview

Description

Simple wrapper around Ruby OptionParser to factor out common code that you have to repeat every time you write a command line tool. This is a simple wrapper. There is minimum additional functionality.

Example Code

Creating a new command line tool or service runner.

class MyApp < Jewelbox::Command

class MyCustomException < RuntimeError; end
exit_code 1, RuntimeError,      "Unexpected error"
exit_code 2, MyCustomException, "Some good explanation"

def initialize
  @address = "default address"
  @name    = "default name"
  @arg1    = ""
  @arg2    = ""
end

def define_options(opt)
  opt.banner = "Usage: #{opt.program_name} [options] arg1 arg2"
  opt.on("-a addr", "--address addr", String, "Address to work with") {|s| @address = s}
  opt.on("-n name", "--name name", String, "Name to work with")       {|s| @name = s}
end

# Main entry point of the application
#
def main(argv)
  @arg1 = argv[0]
  @arg2 = argv[1]
  # write application code here
end

end

MyApp.new.run

Help Output Example

With the above example, you will get the following help text:

Usage: myapp [options] arg1 arg2

-a, --address addr               Address to work with
-n, --name name                  Name to work with
-h, --help                       Display help
-v, --verbose                    Verbose output

Exit codes:

1 [RuntimeError]                Unexpected error
2 [MyApp::MyCustomException]    Some good explanation

Notes

  1. The following options are automatically added.

opt.on("-h", "--help",    "Display help")   { @help = true }
opt.on("-v", "--verbose", "Verbose output") { @verbose = true }
  1. You can map exception type to exit code by using exit_code method When exception happens during “run”, we exit with the matching exit code (default = 1) Also, exception message + “[ERROR]” will be displayed to STDERR.

  2. Make sure to override “define_options” and “main” methods.

Constant Summary collapse

@@exit_code_map =
{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.exit_code(number, eClass, message = "") ⇒ Object

Description

Maps exception class to the exit code.

Parameters

number

(Integer) exit code to return on given exception

eClass

(Class) exception class

message

(String) explanation of the exception



81
82
83
# File 'lib/jewelbox/command.rb', line 81

def self.exit_code(number, eClass, message = "")
  @@exit_code_map[eClass] = [number.to_i, eClass, message]
end

Instance Method Details

#define_options(opt) ⇒ Object

Description

Your application should override this method. Define application command line options.

Parameters

opt

(OptionParser) use this to define options



112
113
114
# File 'lib/jewelbox/command.rb', line 112

def define_options(opt)
  # override this; no additional options by default
end

#main(argv) ⇒ Object

Description

Your application should override this method. Implement the main entry point.

Parameters

argv

(Array) of positional arguments Basically left over after processing command line options starting with dash(s) as defined in get_options.

Returns

(Integer) exit code



128
129
130
# File 'lib/jewelbox/command.rb', line 128

def main(argv)
  # override this; no default action in main
end

#puts_err(msg) ⇒ Object

Description

Print out msg to STDERR in red color



173
174
175
# File 'lib/jewelbox/command.rb', line 173

def puts_err(msg)
  STDERR.puts(msg.to_s.red)
end

#puts_msg(msg) ⇒ Object

Description

Print out msg to STDOUT



166
167
168
# File 'lib/jewelbox/command.rb', line 166

def puts_msg(msg)
  STDOUT.puts(msg)
end

#runObject

Description

Parse options, and run the main method

Returns

(Integer) exit code



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/jewelbox/command.rb', line 138

def run
  code = 0
  opt = OptionParser.new
  define_options(opt)
  default_options(opt)
  define_exit_codes(opt)
  argv = opt.parse!

  if @help
    puts_msg(opt.help)

  else
    begin
      main(argv)
    rescue Exception => e
      arr = @@exit_code_map[e.class]
      code = arr ? arr[0] : 1
      puts_err e.to_s
      puts_err "[ERROR]"
    end
  end

  exit(code)
end