class Cmdline::CmdLine

Public Class Methods

new(*) click to toggle source
Calls superclass method
# File lib/cmdline.rb, line 91
def initialize(*)
  super
  self.options ||= {}
  self.commands ||= {}
  self.command ||= ""
  self.arguments ||= []
  self.command_arguments ||= []
  self.program_name ||= ""
end

Public Instance Methods

add_argument(name, description) click to toggle source
# File lib/cmdline.rb, line 131
def add_argument(name, description)
  argument = Argument.new(
    name: name.to_s,
    description: description.to_s
  )

  addarg(argument)
end
add_command(name, description) click to toggle source
# File lib/cmdline.rb, line 150
def add_command(name, description)
  if self.arguments.size.zero?
    add_argument("command", "the command to execute")
  elsif self.arguments.first.name != "command"
    raise(ArgumentError, "cannot have both arguments and commands")
  end

  cmd = Command.new(
    name: name.to_s,
    description: description.to_s
  )

  self.commands[cmd.name] = cmd
end
add_flag(short, long, description) click to toggle source
# File lib/cmdline.rb, line 101
def add_flag(short, long, description)
  option = Option.new(
    short_name: short.to_s,
    long_name: long.to_s,
    value_string: "",
    description: description.to_s
  )

  addopt(option)
end
add_option(short, long, value, description) click to toggle source
# File lib/cmdline.rb, line 112
def add_option(short, long, value, description)
  option = Option.new(
    short_name: short.to_s,
    long_name: long.to_s,
    value_string: value.to_s,
    description: description.to_s
  )

  addopt(option)
end
add_trailing_arguments(name, description) click to toggle source
# File lib/cmdline.rb, line 140
def add_trailing_arguments(name, description)
  argument = Argument.new(
    name: name.to_s,
    description: description.to_s,
    trailing: true
  )

  addarg(argument)
end
argument_value(name) click to toggle source
# File lib/cmdline.rb, line 360
def argument_value(name)
  self.arguments.each do |arg|
    if arg.name == name
      return arg.value
    end
  end
  raise(ArgumentError, "unknown argument")
end
command_arguments_values() click to toggle source
# File lib/cmdline.rb, line 381
def command_arguments_values
  raise(RuntimeError, "no command defined") if self.commands.empty?
  self.command_arguments
end
command_name() click to toggle source
# File lib/cmdline.rb, line 376
def command_name
  raise(RuntimeError, "no command defined") if self.commands.empty?
  self.command
end
command_name_and_arguments() click to toggle source
# File lib/cmdline.rb, line 386
def command_name_and_arguments
  raise(RuntimeError, "no command defined") if self.commands.empty?
  [self.command, *self.command_arguments]
end
die(format, *args) click to toggle source
# File lib/cmdline.rb, line 165
def die(format, *args)
  msg = sprintf(format, *args)
  STDERR.puts("error: #{msg}")
  exit(1)
end
is_option_set(name) click to toggle source
# File lib/cmdline.rb, line 346
def is_option_set(name)
  opt = self.options[name]
  raise(ArgumentError, "unknown option") if opt.nil?
  opt.set
end
option_value(name) click to toggle source
# File lib/cmdline.rb, line 352
def option_value(name)
  opt = self.options[name]
  raise(ArgumentError, "unknown option") if opt.nil?

  return opt.value if opt.set
  opt.default
end
parse(args) click to toggle source
# File lib/cmdline.rb, line 171
def parse(args)
  die("empty argument array") if args.size == 0

  self.program_name = args.shift

  while args.size > 0
    arg = args.first

    if arg == "--"
      args.shift
      break
    end

    is_short = arg.size == 2 && arg[0] == "-" && arg[1] != "-"
    is_long = arg.size > 2 && arg[0,2] == "--"

    if is_short || is_long
      key = if is_short
              arg[1,2]
            else
              arg[2..]
            end

      opt = self.options[key]
      die("unknown option \"%s\"", key) if opt.nil?

      opt.set = true

      if opt.value_string.empty?
        args = args[1..]
      else
        die("missing value for option \"%s\"", key) if args.size < 2
        opt.value = args[1]
        args = args[2..]
      end
    else
      break
    end
  end

  if self.arguments.size > 0 && !is_option_set("help")
    last = self.arguments.last

    min = self.arguments.size
    min -= 1 if last.trailing

    die("missing argument(s)") if args.size < min

    min.times do |i|
      self.arguments[i].value = args[i]
    end
    args = args[min..]

    if last.trailing
      last.trailing_values = args
      args = args[args.size..]
    end
  end

  if self.commands.size > 0
    self.command = self.arguments.first.value
    self.command_arguments = args
  end

  if !is_option_set("help")
    if self.commands.size > 0
      cmd = self.commands[self.command]
      if cmd.nil?
        die("unknown command \"%s\"", self.command)
      end
    elsif args.size > 0
      die("invalid extra argument(s)")
    end
  end

  if is_option_set("help")
    print_usage
    exit(0)
  end
end
print_usage() click to toggle source
set_option_default(name, value) click to toggle source
# File lib/cmdline.rb, line 123
def set_option_default(name, value)
  option = self.options[name]
  raise(ArgumentError, "unknown option") if option.nil?
  raise(ArgumentError, "flags cannot have a default value") if option.value_string.empty?

  option.default = value
end
trailing_arguments_values(name) click to toggle source
# File lib/cmdline.rb, line 369
def trailing_arguments_values(name)
  raise(ArgumentError, "empty argument array") if self.arguments.empty?
  last = self.arguments.last
  raise(ArgumentError, "no trailing arguments") unless last.trailing
  last.trailing_values
end

Private Instance Methods

addarg(arg) click to toggle source
# File lib/cmdline.rb, line 411
def addarg(arg)
  raise(ArgumentError, "cannot have both arguments and commands") if self.commands.size > 0
  if self.arguments.size > 0
    last = self.arguments.last
    if last.trailing
      raise(ArgumentError, "cannot add argument after trailing argument")
    end
  end

  self.arguments << arg
end
addopt(opt) click to toggle source
# File lib/cmdline.rb, line 393
def addopt(opt)
  if !opt.short_name.empty?
    if opt.short_name.size != 1
      raise(ArgumentError, "option short names must be one character long")
    end

    self.options[opt.short_name] = opt
  end

  if !opt.long_name.empty?
    if opt.long_name.size < 2
      raise(ArgumentError, "option long names must be at least two characters long")
    end

    self.options[opt.long_name] = opt
  end
end