2015-06-21 87 views
0

我想给我的Perl程序提供更好的文档。为此,我没有很多解决方案。 Actuatlly我发现只有一个:POD。获取-h与Pod :: Usage和GetOpt ::长期违反DRY原则

对于NAME节中,我们通常有:

=head1 NAME 

program_name - Short description 

=cut 

它采用5行,唯一的相关信息的简短说明。 program_name应自动填入basename($0)

然后它来的选项。从GetOptions论点,我可以自动提取:

  • 每个选项
  • 的名称是参数强制

我们可以轻松地添加选项,如categorymandatorydescriptionin_conflict_with。那么我为什么要在POD中重复自己呢?

为了说明我的例子,我写了这个:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use feature 'say'; 
use Getopt::Long; 
use Pod::Usage 'pod2usage'; 
use File::Basename; 

=head1 AUTHOR 

John Doe <[email protected]> 

=head1 DESCRIPTION 

B<This program> does nothing important. But at least it is properly documented. 

=head1 COPYRIGHT 

    Copyright(c) Nobody 

=head1 VERSION 

    v0.1 

=cut 


my %cfg; 
CliInfo (
    args => [ 
    {arg => "l|length=i", dest => \$cfg{length}, desc => "Length of the string", type => 'mandatory'}, 
    {arg => "f|file=s" , dest => \$cfg{data}, desc => "Input filename", type => 'mandatory'}, 
    {arg => "v"   , dest => sub {\$cfg{verbose}++}, desc => "Verbose"}, 
    ] 
); 

sub CliInfo { 
    my %info = @_; 
    my $programName = basename $0; 
    GetOptions(map({$_->{arg} => $_->{dest}} @{$info{args}}), 
     'h|help' => sub { 
      say "Usage: $programName [options]..."; 
      say pod2scalar(-verbose => 99, -sections => "DESCRIPTION"); 
      say "\nOptions:"; 
      say sprintf('%-20s', (sub { 
       my @opt = split /\|/, shift =~ s/=.*//r; 
       return " -$opt[0], --$opt[1]" if @opt > 1; 
       return "  --$opt[0]" if length $opt[0] > 1; 
       return " -$opt[0]"; 
      })->($_->{arg})), $_->{desc} for @{$info{args}}; 
      say "\n"; 
     }, 
     'version' => sub { 
      my $ver = pod2scalar(-verbose => 99, -sections => "VERSION"); 
      say STDERR $programName, " - $ver"; 
      say pod2scalar(-verbose => 99, -sections => "COPYRIGHT"); 
      say ""; 
      exit; 
     }) 
     or say "Invalid option, try --help" and exit 1; 

    sub pod2scalar { 
     open my $fh, '>', \my $text; 
     pod2usage(@_, -output => $fh, -exitval => 'NOEXIT'); 
     $text =~ s/^(?:.*\n)//; 
     $text =~ s/(?:\s*\n)\z//r; 
    } 
} 

__END__ 

哪个给出了这样的输出(也是相当与GNU标准兼容):

$ ./help.pl --help 
Usage: help.pl [options]... 
This program does nothing important. But at least it is properly documented. 

Options: 
    -l, --length  Length of the string 
    -f, --file  Input filename 
    -v    Verbose 

所以问题:

对于我在这里就DRY原理展示的内容,是否有任何标准和类似的解决方案?

回答

1

也许Perl库Getopt::Long::Descriptive是你所需要的。

这是你的剧本改写Getopt::Long::Descriptive

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Pod::Usage 'pod2usage'; 
use Capture::Tiny ':all'; 
use Getopt::Long::Descriptive; 

=head1 AUTHOR 

John Doe <[email protected]> 

=head1 DESCRIPTION 

B<This program> does nothing important. But at least it is properly documented. 

=head1 COPYRIGHT 

    Copyright(c) Nobody 

=head1 VERSION 

    v0.1 

=cut 

sub pod2scalar { 
    my $stdout = capture_merged { 
     pod2usage(-verbose => 99, -sections => "DESCRIPTION", -exitval => "noexit"); 
    }; 

    return $stdout; 
} 

my ($opt, $usage) = describe_options(
    pod2scalar() . "%c %o <some-arg>", 
    [ 'l|length=i', 'Length of the string', { required => 1, default => 4 } ], 
    [ 'f|file=s', 'Input filename', { required => 1 } ], 
    [ 'v', 'Verbose' ], 
    [ 'help', "print usage message and exit" ], 
    { 
     show_defaults => 1, 
    }, 
); 

if ($opt->help) { 
    print($usage->text); 
    exit; 
} 

这是你的原始脚本的输出:

$ ./before.pl --help 
Usage: before.pl [options]... 
    This program does nothing important. But at least it is properly 
    documented. 

Options: 
    -l, --length  Length of the string 
    -f, --file  Input filename 
    -v    Verbose 

这里是新脚本的输出:

$ ./after.pl --help 
Mandatory parameter 'f' missing in call to (eval) 

Description: 
This program does nothing important. But at least it is properly 
documented. 

after.pl [-flv] [long options...] <some-arg> 
     --length INT -l INT Length of the string 
           (default value: 4) 
     --file STR -f STR  Input filename 
     -v     Verbose 
     --help    print usage message and exit 
相关问题