class Cyclops

Constants

VERSION

Attributes

config[R]
defaults[R]
options[R]
prog[RW]
stderr[R]
stdin[R]
stdout[R]

Public Class Methods

defaults() click to toggle source
# File lib/cyclops.rb, line 44
def defaults
  {}
end
execute(*args) click to toggle source
# File lib/cyclops.rb, line 48
def execute(*args)
  new.execute(*args)
end
new(defaults = nil, *args) click to toggle source
# File lib/cyclops.rb, line 71
def initialize(defaults = nil, *args)
  @defaults, @prog = defaults || self.class.defaults, $0

  init(*args)

  # prevent backtrace on ^C
  trap(:INT) { exit 130 }
end
usage(prog) click to toggle source
# File lib/cyclops.rb, line 36
def usage(prog)
  "Usage: #{prog} [-h|--help] [options]"
end
version() click to toggle source
# File lib/cyclops.rb, line 40
def version
  parent_const_get(:VERSION)
end

Private Class Methods

parent_const_get(const, range = 0...-1) click to toggle source
# File lib/cyclops.rb, line 54
def parent_const_get(const, range = 0...-1)
  name.split('::').inject([Object]) { |memo, name|
    memo << memo.last.const_get(name)
  }.reverse[range].each { |mod|
    return mod.const_get(const) if mod.const_defined?(const, false)
  }

  raise NameError, "uninitialized constant #{self}::#{const}"
end

Public Instance Methods

execute(arguments = ARGV, *inouterr) click to toggle source
# File lib/cyclops.rb, line 92
def execute(arguments = ARGV, *inouterr)
  reset(*inouterr)
  parse_options(arguments)
  run(arguments)
rescue => err
  raise if $VERBOSE
  err.is_a?(OptionParser::ParseError) ? quit(err) :
    abort("#{err.backtrace.first}: #{err} (#{err.class})")
ensure
  options.each_value { |value| value.close if value.is_a?(Zlib::GzipWriter) }
end
progname() click to toggle source
# File lib/cyclops.rb, line 80
def progname
  File.basename(prog)
end
reset(stdin = STDIN, stdout = STDOUT, stderr = STDERR) click to toggle source
# File lib/cyclops.rb, line 108
def reset(stdin = STDIN, stdout = STDOUT, stderr = STDERR)
  @stdin, @stdout, @stderr = stdin, stdout, stderr
  @options, @config = {}, {}
end
run(arguments) click to toggle source
# File lib/cyclops.rb, line 104
def run(arguments)
  raise NotImplementedError, 'must be implemented by subclass'
end
usage() click to toggle source
# File lib/cyclops.rb, line 84
def usage
  self.class.usage(prog)
end
version() click to toggle source
# File lib/cyclops.rb, line 88
def version
  self.class.version
end

Private Instance Methods

abort(msg = nil, status = 1) click to toggle source
# File lib/cyclops.rb, line 155
def abort(msg = nil, status = 1)
  warn(msg) if msg
  exit(status)
end
agree(question, character = nil, &block) click to toggle source
# File lib/cyclops.rb, line 134
def agree(question, character = nil, &block)
  highline.agree(question, character, &block)
end
ask(question, echo = true) { |q| ... } click to toggle source
# File lib/cyclops.rb, line 123
def ask(question, echo = true)
  highline.ask(question) { |q|
    yield q if block_given?
    q.echo = echo
  }
end
askpass(question, &block) click to toggle source
# File lib/cyclops.rb, line 130
def askpass(question, &block)
  ask(question, false, &block)
end
config_opts(opts, desc = 'Path to config file (YAML)') click to toggle source
# File lib/cyclops.rb, line 246
def config_opts(opts, desc = 'Path to config file (YAML)')
  if config = defaults.fetch(:config) { return }
    desc += ' [Default: %s (%s)]' % [config,
      config_present?(config) ? 'present' : 'currently not present']
  end

  opts.option(:config__FILE, desc)

  opts.separator
end
config_present?(config) click to toggle source
# File lib/cyclops.rb, line 194
def config_present?(config)
  File.readable?(config)
end
exit(status = 0) click to toggle source
# File lib/cyclops.rb, line 165
def exit(status = 0)
  Kernel.exit(status)
end
generic_opts(opts) click to toggle source
# File lib/cyclops.rb, line 273
def generic_opts(opts)
  verbose_opts(opts)

  opts.option(:help, 'Print this help message and exit') {
    shut opts
  }

  opts.option('version', 'Print program version and exit') {
    shut "#{progname} v#{version}"
  }
end
highline() click to toggle source
# File lib/cyclops.rb, line 119
def highline
  @highline ||= HighLine.new(stdin, stdout)
end
init(*args) click to toggle source
# File lib/cyclops.rb, line 115
def init(*args)
  reset
end
load_config(file = options[:config] || default = defaults[:config]) click to toggle source
# File lib/cyclops.rb, line 198
def load_config(file = options[:config] || default = defaults[:config])
  return unless file

  if File.readable?(file)
    @config = Psych.safe_load(File.read(file), symbolize_names: true)
  else
    quit "No such file: #{file}" unless default
  end
end
merge_config(args = [config, defaults]) click to toggle source
# File lib/cyclops.rb, line 208
def merge_config(args = [config, defaults])
  args.each { |hash| hash && hash.each { |key, value|
    options[key] = value unless options.key?(key)
  } }
end
open_file(file, mode = 'r') click to toggle source
# File lib/cyclops.rb, line 174
def open_file(file, mode = 'r')
  write = write?(mode) or
    File.readable?(file) or quit "No such file: #{file}"

  file =~ /\.gz\z/i ? (write ? Zlib::GzipWriter :
    Zlib::GzipReader).open(file) : File.open(file, mode)
end
open_file_or_std(file, mode = 'r') click to toggle source
# File lib/cyclops.rb, line 169
def open_file_or_std(file, mode = 'r')
  mode = 'w' if mode == true
  stdio?(file) ? open_std(file, mode) : open_file(file, mode)
end
open_std(file, mode = nil) click to toggle source
# File lib/cyclops.rb, line 182
def open_std(file, mode = nil)
  write?(mode) ? stdout : stdin
end
option_parser() click to toggle source
# File lib/cyclops.rb, line 221
def option_parser
  OptionParser.new { |opts|
    opts.extend(OptionParserExtension).cli = self

    opts.banner = usage

    pre_opts(opts)

    opts.separator
    opts.separator 'Options:'

    config_opts(opts)
    opts(opts)

    opts.separator
    opts.separator 'Generic options:'

    generic_opts(opts)
    post_opts(opts)
  }
end
opts(opts) click to toggle source
# File lib/cyclops.rb, line 257
def opts(opts)
end
parse_options(arguments) click to toggle source
# File lib/cyclops.rb, line 214
def parse_options(arguments)
  option_parser.parse!(arguments)

  load_config
  merge_config
end
post_opts(opts) click to toggle source
# File lib/cyclops.rb, line 285
def post_opts(opts)
end
pre_opts(opts) click to toggle source
# File lib/cyclops.rb, line 243
def pre_opts(opts)
end
puts(*msg) click to toggle source
# File lib/cyclops.rb, line 138
def puts(*msg)
  stdout.puts(*msg)
end
quit(msg = nil, include_usage = msg != false) click to toggle source
# File lib/cyclops.rb, line 146
def quit(msg = nil, include_usage = msg != false)
  out = []

  out << "#{progname}: #{msg}" if msg
  out << usage if include_usage

  abort out.any? && out.join("\n\n")
end
shut(msg = nil, status = 0) click to toggle source
# File lib/cyclops.rb, line 160
def shut(msg = nil, status = 0)
  puts(msg) if msg
  exit(status)
end
stdio?(file) click to toggle source
# File lib/cyclops.rb, line 190
def stdio?(file)
  file == '-'
end
verbose_opts(opts) click to toggle source
# File lib/cyclops.rb, line 260
def verbose_opts(opts)
  verbose, debug = defaults.key?(:verbose), defaults.key?(:debug)

  opts.switch(:verbose, 'Print verbose output') {
    warn "#{progname} v#{version}"
  } if verbose

  msg = "; #{debug_message}" if respond_to?(:debug_message, true)
  opts.switch(:debug, :D, "Print debug output#{msg}") if debug

  opts.separator if verbose || debug
end
warn(*msg) click to toggle source
# File lib/cyclops.rb, line 142
def warn(*msg)
  stderr.puts(*msg)
end
write?(mode) click to toggle source
# File lib/cyclops.rb, line 186
def write?(mode)
  mode == true || mode =~ /w/
end