Skip to content

Errors

When calling #parse you should always rescue errors, unless you want your application to crash in a bad way. The method can raises 3 different errors. Those errors have two common properties:

  • they inherit from Clip::Error
  • their message is preformatted and can be shown directly to the user

The first property means you can rescue only Clip::Errors, and the second one means you can do puts ex or ex.to_s (where ex is the rescued exception) and you will have a nice message.

Note

Clip does not provide any i18n support for now, so all messages are in english.

Parsing error

If the parsing of options and arguments failed, a Clip::ParsingError exception is raised. The exception's message is already a ready-to-use message that you can present to the user, but the exception also provides a way to know what happens exactly.

Options parsing error

The errors related to options parsing are accessible with Clip::ParsingError#options. It returns a Hash(String, Clip::Errors)

The key is the name of the option which triggered the error. If the option was present in the user input, the name used will be kept. If not, there are two cases: either the option has no names specified with the Clip::Option annotation and the default one is used, or the first name in the annotation is used.

The possible errors are:

  • Clip::Errors::InvalidValue: the value provided for the option is invalid. It could be triggered when integers or floats are expected.
  • Clip::Errors::MissingValue: a value must be provided for the option but there is no value.
  • Clip::Errors::Required: the option is required but is not provided.
  • Clip::Errors::Unknown: the provided option is unknown.

Arguments parsing error

In the same way, errors related to arguments parsing are accessible with Clip::ParsingError#arguments. It returns a Hash(String, Clip::Errors).

The key is the name of the argument.

The possible errors are:

  • Clip::Errors::InvalidValue: the value provided for the argument is invalid. It could be triggered when integers or floats are expected.
  • Clip::Errors::Required: the argument is required but is not provided.

Excess arguments are ignored, hence you will never get an Unknown error.

Example

require "clip"

module Myapplication
  VERSION = "0.1.0"

  struct Command
    include Clip::Mapper

    @[Clip::Option("-r", "--repeat")]
    getter repeat = 1
    @[Clip::Option]
    getter yell : Bool
    getter name : String
  end

  def self.run
    begin
      command = Command.parse
    rescue ex : Clip::ParsingError
      pp! ex.options, ex.arguments
    end
  end
end

Myapplication.run
$ shards build
Dependencies are satisfied
Building: myapplication
$ ./bin/myapplication --repeat
ex.options   # => {"--yell" => Required, "--repeat" => MissingValue}
ex.arguments # => {"name" => Required}
$ ./bin/myapplication --yell -r yes --name Alice Barbara
ex.options   # => {"-r" => InvalidValue, "--name" => Unknown}
ex.arguments # => {}

Nested commands error

When using nested commands, two exceptions can be raised:

  • Clip::MissingCommand: a nested command is expected but none is provided.
  • Clip::UnknownCommand: the provided nested command is unknown. The command is accessible with Clip::UnknownCommand.command.
require "clip"

module Myapplication
  VERSION = "0.1.0"

  abstract struct Command
    include Clip::Mapper

    Clip.add_commands({"hello" => HelloCommand})
  end

  struct HelloCommand < Command
    include Clip::Mapper
  end

  def self.run
    begin
      command = Command.parse
    rescue ex : Clip::MissingCommand
      pp ex
    rescue ex : Clip::UnknownCommand
      pp! ex.command
    end
  end
end

Myapplication.run
$ shards build
Dependencies are satisfied
Building: myapplication
$ ./bin/myapplication
#<Clip::MissingCommand:Error: you need to provide a command.>
$ ./bin/myapplication goodbye
ex.command # => "goodbye"