Skip to content
David Copeland edited this page Jun 3, 2014 · 11 revisions

You don't need to do anything special to message the user about errors (though it's polite to use the standard error when doing so). If you need to exit immediately due to an unrecoverable error, simply raise an exception; GLI will display the exception message to the user, but not the backtrace. In general, this is what you want and should work fine.

GLI will exit zero if no exception was raised. GLI will exit nonzero as follows:

  • If there is a problem parsing the command line (e.g. unknown command, unknown flag), GLI exits with 64
  • If your code raises an exception, GLI exits with 1

Custom Exit Codes

If you need to exit but don't have an exception to raise, you can use either exit_now! or help_now!. exit_now! with raise a CustomExit for you with the mesage and optional exit status.

help_now! will do the same, but will also redisplay the help for the command the user attempted to execute. This is useful for sanity-checking command-line arguments.

What's the point of CustomExit?

If you need some very sophisticated error reporting and message codes, peppering your code with exit_now! might lead to a mess. In this case, you could use CustomExit as a base class for your exceptions:

    class NoNetworkConnection < CustomExit
      def initialize
        super("No network connection was available", -4)
      end
    end
    class BadInput < CustomExit
      def initialize(message)
        super(message, -5)
      end
    end

You could also mix in GLI::StandardException to any exception that you get:

def doit
  # some code that might raise
rescue => ex
  ex.extends(GLI::StandardException)
  raise
end

Custom Error Handling

If you want to skip GLI's "catch exceptions, print the message, and exit nonzero" behavior, you can by using the on_error hook.

For example:

on_error do |exception|
  case exception
  when NetworkProblem
    $stderr.puts "Problem with the network: #{exception.message}"
    false # skip GLI's error handling
  when ArgumentError
    $stderr.puts "Programmer made some mistake"
    false # skip GLI's error handling
  else
    true # use GLI's default error handling
  end
end

If the block evaluates to true, GLI's error handling kicks in, but you can avoid that by having your block evaluate to false.

Debugging installed GLI applications

Unless you have overridden the on_error hook, GLI will not make the backtrace of any exceptions caught available. To cause GLI to print it, set the environment variable 'GLI_DEBUG' to 'true'. This is useful for debugging your application

$ bin/gli foo
error: Unknown command 'foo'
$ env GLI_DEBUG=true bin/gli foo
error: Unknown command 'foo'
/Users/davec/Projects/gli/lib/gli.rb:305:in `parse_options_helper': Unknown command 'foo' (GLI::BadCommandLine)
	from /Users/davec/Projects/gli/lib/gli.rb:244:in `parse_options'
	from /Users/davec/Projects/gli/lib/gli.rb:139:in `run'
	from bin/gli:70

This should also work when running system tests:

$ GLI_DEBUG=true rake cucumber