class Kumogata::ArgumentParser

Constants

COMMANDS
DEFAULT_OPTIONS

Public Class Methods

parse!(&block) click to toggle source
# File lib/kumogata/argument_parser.rb, line 66
def parse!(&block)
  self.new.parse!(&block)
end

Public Instance Methods

parse!() { |opt, command, arguments, options| ... } click to toggle source
# File lib/kumogata/argument_parser.rb, line 71
def parse!
  command = nil
  arguments = nil
  options = {}

  if ENV['KUMOGATA_OPTIONS']
    ARGV.concat(scan_args(ENV['KUMOGATA_OPTIONS']))
  end

  ARGV.options do |opt|
    update_usage(opt)

    begin
      supported_formats = [:ruby, :json, :yaml, :js, :coffee, :json5]
      opt.on('-k', '--access-key ACCESS_KEY')                    {|v| options[:access_key_id]           = v     }
      opt.on('-s', '--secret-key SECRET_KEY')                    {|v| options[:secret_access_key]       = v     }
      opt.on('-r', '--region REGION')                            {|v| options[:region]                  = v     }
      opt.on(''  , '--profile CONFIG_PROFILE')                   {|v| options[:config_profile]          = v     }
      opt.on(''  , '--credentials-path PATH')                    {|v| options[:credentials_path]        = v     }
      opt.on(''  , '--config-path PATH')                         {|v| options[:config_path]             = v     }
      opt.on(''  , '--stack-policy-body PATH')                   {|v| options[:stack_policy_body]       = File.read(v) }
      opt.on(''  , '--stack-policy-url URL')                     {|v| options[:stack_policy_url]        = v     }

      opt.on(''  , '--format TMPLATE_FORMAT', supported_formats) {|v| options[:format]                  = v     }
      opt.on(''  , '--output-format FORMAT', supported_formats)  {|v| options[:output_format]           = v     }
      opt.on(''  , '--skip-replace-underscore')                  {    options[:skip_replace_underscore] = false }
      opt.on(''  , '--deletion-policy-retain')                   {    options[:deletion_policy_retain]  = true  }
      opt.on('-p', '--parameters KEY_VALUES', Array)             {|v| options[:parameters]              = v     }
      opt.on('-j', '--json-parameters JSON')                     {|v| options[:json_parameters]         = v     }
      opt.on('-e', '--encrypt-parameters KEYS', Array)           {|v| options[:encrypt_parameters]      = v     }
      opt.on('',   '--encryption-password PASS')                 {|v| options[:encryption_password]     = v     }
      opt.on('',   '--skip-send-password')                       {    options[:skip_send_password]      = true  }
      opt.on(''  , '--capabilities CAPABILITIES', Array)         {|v| options[:capabilities]            = v     }
      opt.on(''  , '--disable-rollback')                         {    options[:disable_rollback]        = true  }
      opt.on(''  , '--notify SNS_TOPICS', Array)                 {|v| options[:notify]                  = v     }
      opt.on(''  , '--timeout MINUTES', Integer)                 {|v| options[:timeout]                 = v     }
      opt.on(''  , '--result-log PATH')                          {|v| options[:result_log]              = v     }
      opt.on(''  , '--command-result-log PATH')                  {|v| options[:command]                 = v     }
      opt.on(''  , '--detach')                                   {    options[:detach]                  = true  }
      opt.on(''  , '--force')                                    {    options[:force]                   = true  }
      opt.on('-w', '--ignore-all-space')                         {    options[:ignore_all_space]        = true  }
      opt.on(''  , '--color')                                    {    options[:color]                   = true  }
      opt.on(''  , '--no-color')                                 {    options[:color]                   = false }
      opt.on(''  , '--debug')                                    {    options[:debug]                   = true  }
      opt.on('-v', '--verbose')                                  {    options[:verbose]                 = true  }
      opt.parse!

      unless (command = ARGV.shift)
        puts opt.help
        exit 1
      end

      command = command.to_sym

      unless COMMANDS.has_key?(command)
        raise "Unknown command: #{command}"
      end

      arguments = ARGV.dup
      validate_arguments(command, arguments)

      options = DEFAULT_OPTIONS.merge(options)
      options = Hashie::Mash.new(options)

      if block_given?
        yield(opt, command, arguments, options)
      end

      update_parameters(options)
    rescue => e
      $stderr.puts("#{e.message}")
      raise e if options[:debug]
      exit 1
    end
  end

  output = COMMANDS[command].fetch(:output, true)
  command = command.to_s.gsub('-', '_').to_sym

  $kumogata.command = command
  $kumogata.arguments = arguments
  $kumogata.options = options
  options = $kumogata.options # Copy of the reference

  [command, arguments, options, output]
end

Private Instance Methods

arguments_to_message(arguments) click to toggle source
# File lib/kumogata/argument_parser.rb, line 198
def arguments_to_message(arguments)
  arguments.map {|i| i.to_s.sub(/(.+)\?\Z/) { "[#{$1}]" }.upcase }.join(' ')
end
scan_args(str) click to toggle source
# File lib/kumogata/argument_parser.rb, line 217
def scan_args(str)
  args = []
  ss = StringScanner.new(str)
  buf = ''

  until ss.eos?
    if ss.scan(/\s+/)
      unless buf.empty?
        args << buf
        buf = ''
      end
    elsif (tok = ss.scan(/'[^']*'/))
      buf << tok.gsub(/'([^']*)'/) { $1 }
    elsif (tok = ss.scan(/"[^"]*"/))
      buf << tok.gsub(/"([^"]*)"/) { $1 }
    elsif (tok = ss.scan(/[^\s'"]+/))
      buf << tok
    else
      buf << ss.getch
    end
  end

  args << buf unless buf.empty?

  return args
end
update_parameters(options) click to toggle source
# File lib/kumogata/argument_parser.rb, line 202
def update_parameters(options)
  parameters = {}

  (options.parameters || []).each do |i|
    key, value = i.split('=', 2)
    parameters[key] = value
  end

  if options.json_parameters
    parameters.merge! JSON.parse(options.json_parameters)
  end

  options.parameters = parameters
end
update_usage(opt) click to toggle source
# File lib/kumogata/argument_parser.rb, line 160
def update_usage(opt)
  opt.banner = "Usage: kumogata <command> [args] [options]"
  opt.separator ''
  opt.separator 'Commands:'

  cmd_max = COMMANDS.keys.map {|i| i.to_s.length }.max

  cmd_arg_descs = COMMANDS.map {|command, attributes|
    description = attributes[:description]
    arguments = attributes[:arguments]

    [
      '%-*s %s' % [cmd_max, command, arguments_to_message(arguments)],
      description,
    ]
  }

  cmd_arg_max = cmd_arg_descs.map {|i| i[0].length }.max

  opt.separator(cmd_arg_descs.map {|cmd_arg, desc|
    '  %-*s  %-s' % [cmd_arg_max, cmd_arg, desc]
  }.join("\n"))

  opt.separator ''
  opt.separator 'Options:'
end
validate_arguments(command, arguments) click to toggle source
# File lib/kumogata/argument_parser.rb, line 187
def validate_arguments(command, arguments)
  expected = COMMANDS[command][:arguments] || []

  min = expected.count {|i| i.to_s !~ /\?\Z/ }
  max = expected.length

  if arguments.length < min or max < arguments.length
    raise "Usage: kumogata #{command} #{arguments_to_message(expected)} [options]"
  end
end