Getopt-App

 view release on metacpan or  search on metacpan

lib/Getopt/App.pm  view on Meta::CPAN

    next if $line =~ m!^sub bundle\s\{! .. $line =~ m!^}$!;    # skip bundle()
    last if $line =~ m!^1;\s*$!;                               # do not include POD

    chomp $line;
    if ($line =~ m!^sub\s!) {
      print {$OUT} $out_line, "\n" if $out_line;
      $line =~ m!\}$! ? print {$OUT} $line, "\n" : ($out_line = $line);
    }
    elsif ($line =~ m!^}$!) {
      print {$OUT} $out_line, $line, "\n";
      $out_line = '';
    }
    else {
      $line =~ s!^[ ]{2,}!!;    # remove leading white space
      $line =~ s!\#\s.*!!;      # remove comments
      $out_line .= $line;
    }
  }

  print {$OUT} qq(BEGIN{\$INC{'Getopt/App.pm'}='BUNDLED'}\n);
  print {$OUT} +($package || "package main\n");
  print {$OUT} @script;
  print {$OUT} $_ while readline $SCRIPT;
}

sub capture {
  my ($app, $argv) = @_;

  require File::Temp;
  my ($STDOUT_CAPTURE, $STDERR_CAPTURE) = (File::Temp->new, File::Temp->new);
  open my $STDOUT_ORIG, '>&STDOUT' or die "Can't remember original STDOUT: $!";
  open my $STDERR_ORIG, '>&STDERR' or die "Can't remember original STDERR: $!";

  my $restore = sub {
    open STDERR, '>&', fileno($STDERR_ORIG) or die "Can't restore STDERR: $!";
    open STDOUT, '>&', fileno($STDOUT_ORIG) or die "Can't restore STDOUT: $!";
    die $_[0] if $_[0];
  };

  open STDOUT, '>&', fileno($STDOUT_CAPTURE) or $restore->("Can't capture STDOUT: $!");
  open STDERR, '>&', fileno($STDERR_CAPTURE) or $restore->("Can't capture STDERR: $!");

  my $exit_value;
  unless (eval { $exit_value = $app->($argv || [@ARGV]); 1; }) {
    print STDERR $@;
    $exit_value = int $!;
  }

  STDERR->flush;
  STDOUT->flush;
  $restore->();
  seek $STDERR_CAPTURE, 0, 0;
  seek $STDOUT_CAPTURE, 0, 0;

  return [join('', <$STDOUT_CAPTURE>), join('', <$STDERR_CAPTURE>), $exit_value];
}

sub extract_usage {
  my %pod2usage;
  $pod2usage{'-sections'} = shift;
  $pod2usage{'-input'}    = shift || (caller)[1];
  $pod2usage{'-verbose'}  = 99 if $pod2usage{'-sections'};

  require Pod::Usage;
  open my $USAGE, '>', \my $usage;
  Pod::Usage::pod2usage(-exitval => 'noexit', -output => $USAGE, %pod2usage);
  close $USAGE;

  $usage //= '';
  $usage =~ s!^(.*?)\n!!s if $pod2usage{'-sections'};
  $usage =~ s!^Usage:\n\s+([A-Z])!$1!s;                 # Remove "Usage" header if SYNOPSIS has a description
  $usage =~ s!^    !!gm;

  return join '', $usage, _usage_for_subcommands($SUBCOMMANDS || []), _usage_for_options($OPTIONS || []);
}

sub getopt_complete_reply { Getopt::App::Complete::complete_reply(@_) }

sub getopt_configure {qw(bundling no_auto_abbrev no_ignore_case pass_through require_order)}

sub getopt_load_subcommand {
  my ($app, $subcommand, $argv) = @_;
  return $subcommand->[1] if ref $subcommand->[1] eq 'CODE';

  my $method      = $subcommand->[1] =~ /^\w+$/ && $app->can($subcommand->[1]);
  my @option_spec = @$OPTIONS;
  return sub { _run($app, [@option_spec], $_[0], $method) }
    if $method;

  ($@, $!) = ('', 0);
  croak "Unable to load subcommand $subcommand->[0]: $@ ($!)" unless my $code = do $subcommand->[1];
  return $code;
}

sub getopt_post_process_argv {
  my ($app, $argv, $state) = @_;
  return unless $state->{valid};
  return unless $argv->[0] and $argv->[0] =~ m!^-!;
  $! = 1;
  die "Invalid argument or argument order: @$argv\n";
}

sub getopt_unknown_subcommand {
  my ($app, $argv) = @_;
  $! = 2;
  die "Unknown subcommand: $argv->[0]\n";
}

sub import {
  my ($class, @flags) = @_;
  my $caller = caller;

  $_->import for qw(strict warnings utf8);
  feature->import(':5.16');

  my $skip_default;
  no strict qw(refs);
  while (my $flag = shift @flags) {
    if ($flag eq '-capture') {
      *{"$caller\::capture"} = \&capture;
      $skip_default = 1;



( run in 1.114 second using v1.01-cache-2.11-cpan-e93a5daba3e )