iyi

Standard library, 0.18.0

std/option_parser

Flag parsing, written in iyi.

import std/option_parser to use it. Source: src/std/option_parser.iyi at v0.18.0.

on("--name VALUE", "help") { |v| ... } and on("-h", "help") { } register flags, and on("--color [WHEN]", "help") one whose value may be left out. parse walks Program.args (or the array given), calls the blocks, and answers the leftover operands.

  op = OptionParser.new
  op.banner = "usage: tool [options] COMMAND"
  op.on("-v", "--verbose", "say more") { verbose = true }
  op.on("-n NAME", "--name=NAME", "who") { |v| name = v }
  op.separator("commands:")
  op.on("deploy", "ship it") do
    op.on("-f", "--force", "even if dirty") { force = true }
  end
  puts op   # the banner, then a line for each flag and command

A pair, -v and --verbose, is one flag spelled two ways; a value either spelling states, -n NAME or --name=NAME, both take.

A command is a name with no dash, and is one only as the first operand: tool deploy -f runs deploy's block, which registers what follows it

  • its flags, and the commands below it, which replace the ones beside

it. Flags registered before the command still apply after it, where the other library forgets them; a name after an operand is an operand.

What the person typed wrong is the program's to answer, the way Crystal's OptionParser has it: invalid_option { |flag| ... } is handed an unknown flag and a value given to a flag that takes none, missing_option { |flag| ... } a flag that takes a value and is last, and parsing goes on after either. With no handler set they panic - unknown flag: --x, flag --x takes no value, flag --name needs a value - which is a bug report where a usage line was wanted, so a program reading its own command line sets both.

OptionParserclass

std/option_parseriyi doc src/std/option_parser.iyi
pub class OptionParser
  # What a flag does with the argument after it: `--name VALUE` needs one,
  # `--color [WHEN]` takes one unless it is missing or is a flag itself,
  # and `--verbose` takes none.
  enum Value : Int32
    None = 0
    Required = 1
    Optional = 2
  end
  def banner : String | ::Nil
  # The help's first line, "options:" until it is set.
  def banner=(text : String) : Nil
  def help : String
  def initialize
  def invalid_option(&block : (String -> Nil)) : Nil
  def missing_option(&block : (String -> Nil)) : Nil
  # One flag spelled two ways, `-v` and `--verbose`: the value either
  # states, both take.
  def on(short : String, long : String, description : String, &block : (String -> Nil)) : Nil
  # A value is taken by `--name VALUE`, `--name=VALUE`, `-n VALUE` and
  # `-nVALUE`, the four spellings the other library reads. Only the space
  # form was: `--name=VALUE` was stored under the key `--name=VALUE`, which
  # no argument ever looks up, and `-nVALUE` refused itself as not a flag.
  # A short flag is one character, not one byte: `-é` was refused too.
  #
  # A bracketed value, `--color [WHEN]`, `-c [WHEN]` or `-c[WHEN]`, may be
  # left out, as the other library reads the brackets. It was a required
  # value: `--color` last panicked "flag --color needs a value", and
  # `--color -v` handed `-v` to `--color` instead of running it.
  def on(flag : String, description : String, &block : (String -> Nil)) : Nil
  def parse(args : Array(String)) : Array(String)
  def parse : Array(String)
  # A line of its own in the help, between the flags and commands
  # registered before it and after it.
  def separator(text : String) : Nil
  def to_s : String
end