1

Using Getopt::Long, I want to capture any failures from GetOptions and, rather than printing them to STDOUT/STDERR, I want to print out a Usage string and exit the script. I tried wrapping the call to GetOptions in a Try::Tiny try/catch block, but it doesn't get caught. I'm not sure what's going on behind the scenes here.

How can I capture a failure in GetOptions, prevent it from printing, and print my own usage statement instead?

ewok
  • 20,148
  • 51
  • 149
  • 254
  • See [this post](https://stackoverflow.com/a/44011471/4653379) (for instance), on `__WARN__` hooks. But I also leave `Getopt`'s messages, as they are good, and add my own. – zdim Jul 27 '17 at 17:48

2 Answers2

2

It uses warn, so you could use $SIG{__WARN__}. I would say it's better to provide a usage statement in addition to the specific error found by GetOptions.

sub usage {
   my $prog = basename($0);
   if (my ($msg) = @_) {
      chomp($msg);
      warn("$msg\n");
   }

   warn("Try `$prog --help' for more information.\n");
   exit(1);
}

sub help {
   my $prog = basename($0);
   print(<<"__EOS__");
usage: $prog [options] [--] {foo} {bar}
       $prog --help

Options:
   ...
__EOS__
   exit(0);
}

sub parse_args {
   GetOptions(
      'h|?|help' => \&help,
      ...,
   )
      or usage();

   @ARGV == 2
      or usage("Too many arguments.");
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
1

Here's what I do:

eval {
    local $SIG{__WARN__} = sub { die $_[0] };

    GetOptions( \%opt, ... );
  };

if ( $@ ) {
  ...
}
Diab Jerius
  • 2,310
  • 13
  • 18