2015-06-21 60 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 
相關問題