[Perl 6] Getopt::Kinoko

前端之家收集整理的这篇文章主要介绍了[Perl 6] Getopt::Kinoko前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

About

  • Perl 6

  • Getopt

  • refactor

Code

目录结构

  • Getopt

    • Kinoko.pm6

    • Kinoko

      • Exception.pm6

      • Option.pm6

      • OptionSet.pm6

      • Parser.pm6

Getopt::Kinoko

  1. use Getopt::Kinoko::Parser;
  2. use Getopt::Kinoko::Option;
  3. use Getopt::Kinoko::OptionSet;
  4. use Getopt::Kinoko::Exception;

  5. class Getopt does Associative {

  6. has OptionSet %!optionsets handles ;

  7. has Option $!current;

  8. has Bool $!generate-method;

  9. has Bool $!gnu-style;

  10. has @!args;

  11. method new(:$generate-method,:$gnu-style) {
  12.     self.bless(:generate-method(?$generate-method),:gnu-style(?$gnu-style));
  13. }
  14. submethod BUILD(:$!generate-method,:$!gnu-style) { }
  15. #=[
  16.     push { optionset-name => optionset }s
  17. ]
  18. multi method push(*%optionset-list) {
  19.     %!optionsets.push: %optionset-list;
  20. }
  21. multi method push(Str $name,OptionSet $optset) {
  22.     %!optionsets.push: $name => $optset;
  23. }
  24. multi method push(Str $name,Str $optset-string,&callback = Block) {
  25.     %!optionsets.push: $name => OptionSet.new($optset-string,&callback);
  26. }
  27. method parse(@!args = @*ARGS,Str $method-prefix = "",:&parser = &kinoko-parser) returns Array {
  28.     my @noa;
  29.     for %!optionsets -> $current {
  30.         try {
  31.             @noa := $!gnu-style ??
  32.                 &parser(@!args,$current,True) !! &parser(@!args,$current);
  33.             $!current := $current;
  34.             $!current.check-force-value();
  35.             $!current.generate-method($method-prefix) if $!generate-method;
  36.             last;
  37.             CATCH {
  38.                 when X::Kinoko::Fail {
  39.                     ;
  40.                 }
  41.                 default {
  42.                     note .message;
  43.                     ...
  44.                 }
  45.             }
  46.         }
  47.     }
  48.     @noa;
  49. }
  50. multi method usage(Str $name) {
  51.     return "" unless %!optionsets{$name}:exists;
  52.     return "Usage:\n" ~ $*PROGRAM-NAME ~ %!optionsets{$name}.usage();
  53. }
  54. multi method usage() {
  55.     my Str $usage = "Usage:\n";
  56.     for %!optionsets.values {
  57.         $usage ~= $*PROGRAM-NAME ~ .usage ~ "\n";
  58.     }
  59.     $usage.chomp;
  60. }
  61. }

  62. sub getopt(OptionSet \opset,@args = @*ARGS,:&parser = &kinoko-parser,:$gnu-style,:$generate-method) is export returns Array {

  63. my @noa;

  64. @noa := $gnu-style ?? &parser(@args,opset,True) !! &parser(@args,opset);
  65. opset.check-force-value();
  66. opset.generate-method($method-prefix) if $generate-method;
  67. @noa;
  68. }

Getopt::Kinoko::Exception

  1. class X::Kinoko is Exception {
  2. has $.msg handles ;

  3. method message() {
  4.     $!msg;
  5. }
  6. }

  7. | throw this exception when parse Failed

  8. class X::Kinoko::Fail is Exception { }

Getopt::Kinoko::Option

  1. use Getopt::Kinoko::Exception;

  2. role Option {

  3. has $!sn; #= option long name

  4. has $!ln; #= option short name

  5. has &!cb; #= option callback signature(Option -->)

  6. has $!force; #= option optional

  7. #=[
  8.     public initialize function
  9. ]
  10. method !initialize(:$sn,:$ln,:$force,:&cb) {
  11.     unless $sn.defined || $ln.defined {
  12.         X::Kinoko.new(msg => 'Need option name.').throw();
  13.     }
  14.     my %build;
  15.     %build<sn>      = $sn       if $sn;
  16.     %build<ln>      = $ln       if $ln;
  17.     %build<cb>      = &amp;cb       if &amp;cb;
  18.     %build<force>   = ?$force;
  19.     return self.bless(|%build);
  20. }
  21. submethod BUILD(:$!sn,:$!ln,:&amp;!cb,:$!force) { }
  22. method is-short {
  23.     $!sn.defined;
  24. }
  25. method is-long {
  26.     $!ln.defined;
  27. }
  28. method is-force {
  29.     ?$!force;
  30. }
  31. method is-integer() {
  32.     False;
  33. }
  34. method is-string() {
  35.     False;
  36. }
  37. method is-boolean() {
  38.     False;
  39. }
  40. method is-array() {
  41.     False;
  42. }
  43. method is-hash() {
  44.     False;
  45. }
  46. method has-callback {
  47.     &amp;!cb.defined;
  48. }
  49. method short-name {
  50.     self.is-short ?? $!sn !! "";
  51. }
  52. method long-name {
  53.     self.is-long ?? $!ln !! "";
  54. }
  55. method callback {
  56.     &amp;!cb;
  57. }
  58. method set-callback(&amp;cb) {
  59.     &amp;!cb = &amp;cb;
  60. }
  61. method match-name(Str $name,:$long,:$short) {
  62.     my ($lb,$sb) = ($name eq self.long-name,$name eq self.short-name);
  63.     return ($lb || $sb) if ($long &amp;&amp; $short || !$long &amp;&amp; !$short);
  64.     return $lb if $long;
  65.     return $sb if $short;
  66. }
  67. method usage {
  68.     my $usage = "";
  69.     $usage ~= '-'  ~ self.short-name if self.is-short;
  70.     $usage ~= '|'  if self.is-long &amp;&amp; self.is-short;
  71.     $usage ~= '--' ~ self.long-name  if self.is-long;
  72.     $usage ~= '=<' ~ self.major-type ~ '>' if self.major-type ne "boolean";
  73.     $usage;
  74. }
  75. method perl {
  76.     my $perl = self.^name ~ '.new(';
  77.     $perl ~= "sn => " ~ (self.is-short ?? $!sn !! "Any");
  78.     $perl ~= ',';
  79.     $perl ~= "ln => " ~ (self.is-long  ?? $!ln !! "Any");
  80.     $perl ~= ',';
  81.     $perl ~= "cb => " ~ (self.has-callback ?? &amp;!cb.perl !! "Any");
  82.     $perl ~= ',';
  83.     $perl ~= "force => " ~ $!force.perl;
  84.     $perl ~= ',';
  85.     $perl ~= "value => " ~ (self.has-value ?? self.value.perl !! 'Any');
  86.     $perl ~= ')';
  87.     $perl;
  88. }
  89. method has-value { ... }
  90. method set-value($value) { ... }
  91. method value { ... }
  92. method major-type { ... }
  93. }

  94. =[

  95. inetger option
  96. ]

  97. class Option::Integer does Option {

  98. has Int $!value;

  99. method new(:$sn,:&amp;cb,:$value) {
  100.     self!initialize(:$sn,:&amp;cb)!initialize-value($value);
  101. }
  102. method !initialize-value($value,:$use-default = True) {
  103.     my $name = self.is-long ?? '--' ~ self.long-name !! '-' ~ self.short-name;
  104.     my Int $int;
  105.     if $value.defined {
  106.         if $value !~~ Int {
  107.             try {
  108.                 $int = $value.Int; # or use subset ?
  109.                 CATCH {
  110.                     default {
  111.                         X::Kinoko.new(msg => "$value: Option $name need integer.").throw();
  112.                     }
  113.                 }
  114.             }
  115.         }
  116.     }
  117.     elsif $use-default {
  118.         $int = self!default-value;
  119.     }
  120.     else {
  121.         X::Kinoko.new(msg => ": Option $name need a value.").throw();
  122.     }
  123.     $!value = $int;
  124.     self;
  125. }
  126. method !default-value {
  127.     Int
  128. }
  129. method has-value {
  130.     $!value.defined;
  131. }
  132. method set-value($value) {
  133.     self!initialize-value($value,:!use-default);
  134. }
  135. method value {
  136.     $!value;
  137. }
  138. method major-type {
  139.     "integer";
  140. }
  141. method is-integer() {
  142.     True;
  143. }
  144. }

  145. class Option::String does Option {

  146. has Str $!value;

  147. method new(:$sn,:$use-default = True) {
  148.     my $name = self.is-long ?? '--' ~ self.long-name !! '-' ~ self.short-name;
  149.     my Str $string;
  150.     if $value.defined {
  151.         if $value !~~ Str {
  152.             try {
  153.                 $string = $value.Str;
  154.                 CATCH {
  155.                     default {
  156.                         X::Kinoko.new(msg => "$value: Option $name need string.").throw();
  157.                     }
  158.                 }
  159.             }
  160.         }
  161.         else {
  162.             $string = $value;
  163.         }
  164.     }
  165.     elsif $use-default {
  166.         $string = self!default-value;
  167.     }
  168.     else {
  169.         X::Kinoko.new(msg => ": Option $name need a value.").throw();
  170.     }
  171.     $!value = $string;
  172.     self;
  173. }
  174. method !default-value {
  175.     Str
  176. }
  177. method has-value {
  178.     $!value.defined;
  179. }
  180. method set-value($value) {
  181.     self!initialize-value($value,:!use-default);
  182. }
  183. method value {
  184.     $!value;
  185. }
  186. method major-type {
  187.     "string";
  188. }
  189. method is-string() {
  190.     True;
  191. }
  192. }

  193. class Option::Array does Option {

  194. has @!value;

  195. method new(:$sn,:$use-default = True) {
  196.     my $name = self.is-long ?? '--' ~ self.long-name !! '-' ~ self.short-name;
  197.     my @array;
  198.     if $value.defined {
  199.         if $value !~~ Array {
  200.             try {
  201.                 @array = $value.Array;
  202.                 CATCH {
  203.                     default {
  204.                         X::Kinoko.new(msg => "$value: Option $name need array.").throw();
  205.                     }
  206.                 }
  207.             }
  208.         }
  209.         else {
  210.             @array = @$value;
  211.         }
  212.     }
  213.     elsif $use-default {
  214.         @array = self!default-value;
  215.     }
  216.     else {
  217.         X::Kinoko.new(msg => ": Option $name need a value.").throw();
  218.     }
  219.     @!value.append: @array;
  220.     self;
  221. }
  222. method !default-value {
  223.     @[]
  224. }
  225. method has-value {
  226.     @!value.elems > 0;
  227. }
  228. method set-value($value) {
  229.     self!initialize-value($value,:!use-default);
  230. }
  231. method value {
  232.     @!value;
  233. }
  234. method major-type {
  235.     "array";
  236. }
  237. method is-array() {
  238.     True;
  239. }
  240. }

  241. class Option::Hash does Option {

  242. has %!value;

  243. method new(:$sn,:$use-default = True) {
  244.     my $name = self.is-long ?? '--' ~ self.long-name !! '-' ~ self.short-name;
  245.     my %hash;
  246.     if $value.defined {
  247.         if $value !~~ Hash {
  248.             try {
  249.                 %hash = $value.Hash;
  250.                 CATCH {
  251.                     default {
  252.                         X::Kinoko.new(msg => "$value: Option $name need hash.").throw();
  253.                     }
  254.                 }
  255.             }
  256.         }
  257.         else {
  258.             %hash = %$value;
  259.         }
  260.     }
  261.     elsif $use-default {
  262.         %hash = self!default-value;
  263.     }
  264.     else {
  265.         X::Kinoko.new(msg => ": Option $name need a value.").throw();
  266.     }
  267.     %!value.append: %hash;
  268.     self;
  269. }
  270. method !default-value {
  271.     %{};
  272. }
  273. method has-value {
  274.     %!value.defined;
  275. }
  276. method set-value($value) {
  277.     self!initialize-value($value,:!use-default);
  278. }
  279. method value {
  280.     %!value;
  281. }
  282. method major-type {
  283.     "hash";
  284. }
  285. method is-hash() {
  286.     True;
  287. }
  288. }

  289. =[

  290. boolean option
  291. ]

  292. class Option::Boolean does Option {

  293. has Bool $!value;

  294. method new(:$sn,:$use-default = True) {
  295.     my $name = self.is-long ?? '--' ~ self.long-name !! '-' ~ self.short-name;
  296.     my Bool $bool;
  297.     if $value.defined {
  298.         if $value !~~ Hash {
  299.             try {
  300.                 $bool = $value.Bool;
  301.                 CATCH {
  302.                     default {
  303.                         X::Kinoko.new(msg => "$value: Option $name need boolean.").throw();
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.         else {
  309.             $bool = $value;
  310.         }
  311.     }
  312.     elsif $use-default {
  313.         $bool = self!default-value;
  314.     }
  315.     else {
  316.         X::Kinoko.new(msg => ": Option $name need a value.").throw();
  317.     }
  318.     $!value = $bool;
  319.     self;
  320. }
  321. method !default-value {
  322.     Bool
  323. }
  324. method has-value {
  325.     $!value.defined;
  326. }
  327. method set-value($value) {
  328.     self!initialize-value($value,:!use-default);
  329. }
  330. method value {
  331.     $!value;
  332. }
  333. method major-type {
  334.     "boolean";
  335. }
  336. method is-boolean() {
  337.     True;
  338. }
  339. }

  340. =[

  341. return a class type according to $major-type
  342. ]

  343. multi sub option-class-factory(Str $major-type) {

  344. X::Kinoko.new(msg => "type " ~ $major-type ~ " not recognize").throw();

  345. }

  346. multi sub option-class-factory('i') {

  347. Option::Integer

  348. }

  349. multi sub option-class-factory('a') {

  350. Option::Array

  351. }

  352. multi sub option-class-factory('s') {

  353. Option::String

  354. }

  355. multi sub option-class-factory('b') {

  356. Option::Boolean

  357. }

  358. multi sub option-class-factory('h') {

  359. Option::Hash

  360. }

  361. =[

  362. [short-name] [|] [long-name] = major-type [!];
  363. you must specify at least one of [*-name]
  364. if you specify one name,you can moit [|],then [*-name] will determine by [*-name].length
  365. major-type=[
  366.     s,string,i,integer,b,boolean,h,hash,a,array,]
  367. [!] means a force option
  368. sample:
  369.     "u|username=s!",same as "u|username=string!"
  370.     "p|port=i",same as "p|port=integer"
  371.     "port|p=i",same as above option,[*-name] determine by [*-name].length
  372.     "password=s!",password will be determine as [long-name]
  373.     "p=s!",p(password) will be determine as [short-name]
  374. ]

  375. multi sub create-option(Str:D $option,:$value,:&cb) is export {

  376. my Str $ln;

  377. my Str $sn;

  378. my Str $mt;

  379. my $r = False;

  380. my regex type { [s|i|h|a|b] };
  381. my regex name { <-[\|\=\s]>* };
  382. my regex force { [\!]? }
  383. my regex option {
  384.     [
  385.         <.ws> $<ln> = (<name>) <.ws> \| <.ws> $<rn> = (<name>) <.ws>
  386.         ||
  387.         <.ws> $<name> = (<name>) <.ws>
  388.     ]
  389.     \= <.ws>
  390.     $<mt> = (<type>) <.ws>
  391.     $<r> = (<force>) <.ws>
  392.     {
  393.         if $<name>.defined {
  394.             if ~$<name>.chars > 1 {
  395.                 $ln = ~$<name>;
  396.             }
  397.             else {
  398.                 $sn = ~$<name>;
  399.             }
  400.         }
  401.         elsif $<ln>.defined &amp;&amp; $<rn>.defined {
  402.             if ~$<ln>.chars > ~$<rn>.chars {
  403.                 $ln = ~$<ln> if ~$<ln>.chars > 0;
  404.                 $sn = ~$<rn> if ~$<rn>.chars > 0;
  405.             }
  406.             else {
  407.                 $ln = ~$<rn> if ~$<rn>.chars > 0;
  408.                 $sn = ~$<ln> if ~$<ln>.chars > 0;
  409.             }
  410.         }
  411.         $mt = ~$<mt>;
  412.         $r  = True if $<r>.defined &amp;&amp; ~$<r> eq '!';
  413.     }
  414. };
  415. my &amp;process = -> $opt-str is copy {
  416.     my %l2s := {
  417.         string  => 's',integer => 'i',hash    => 'h',boolean => 'b',array   => 'a',};
  418.     $opt-str ~~ s/\=(string|integer|hash|boolean|array)/{%l2s{$0}}/;
  419.     $opt-str;
  420. };
  421. my $opt-str = &amp;process($option);
  422. if $opt-str ~~ /<option>/ {
  423.     return option-class-factory($mt).new(:$ln,:$sn,:force($r),:&amp;cb);
  424. }
  425. X::Kinoko.new(msg => "$option: not a valid option string.").throw();
  426. }

  427. =[

  428. *%option
  429. :$ln,:$cb,:$mt,]
  430. multi sub create-option(*%option) is export {

  431. return option-class-factory(%option).new(|%option);

  432. }

  433. multi sub create-option(%option) is export {

  434. return option-class-factory(%option).new(|%option);

  435. }

Getopt::Kinoko::OptionSet

  1. use Getopt::Kinoko::Option;
  2. use Getopt::Kinoko::Exception;

  3. class OptionSet does Positional {

  4. has Option @!options handles ;

  5. has &!callback;

  6. method new(Str $optionset-str,&amp;noa-callback?) {
  7.     self.bless(callback => &amp;noa-callback).append($optionset-str);
  8. }
  9. submethod BUILD(:@!options,:&amp;!callback) { }
  10. method has(Str $name,:$short) {
  11.     for @!options -> $opt {
  12.         return True if $opt.match-name($name,:$short);
  13.     }
  14.     False
  15. }
  16. method get(Str $name,:$short) {
  17.     for @!options -> $opt {
  18.         return $opt if $opt.match-name($name,:$short);
  19.     }
  20.     Option;
  21. }
  22. method set(Str $name,$value,:&amp;callback,:$short) {
  23.     for @!options -> $opt {
  24.         if $opt.match-name($name,:$short) {
  25.             $opt.set-value($value);
  26.             $opt.set-callback(&amp;callback) if ?&amp;callback;
  27.             last;
  28.         }
  29.     }
  30. }
  31. #| can modify value
  32. method AT-POS(::?CLASS::D: $index) is rw {
  33.     my $option := @!options[$index];
  34.     Proxy.new(
  35.         FETCH => method () { $option; },STORE => method ($value) {
  36.             $option.set-value($value);
  37.         }
  38.     );
  39. }
  40. #| can modify value
  41. method AT-KEY(::?CLASS::D: $name) is rw {
  42.     my $option = Option;
  43.     for @!options -> $opt {
  44.         if $opt.match-name($name) {
  45.             $option := $opt;
  46.             last;
  47.         }
  48.     }
  49.     Proxy.new(
  50.         FETCH => method () { $option; },STORE => method ($value) {
  51.             $option.set-value($value);
  52.         }
  53.     );
  54. }
  55. method EXISTS-KEY($name) {
  56.     return self.has($name);
  57. }
  58. method is-set-noa() {
  59.     &amp;!callback.defined;
  60. }
  61. method process-noa() {
  62.     &amp;!callback;
  63. }
  64. method Numeric() {
  65.     return +@!options;
  66. }
  67. method check-force-value() {
  68.     for @!options -> $opt {
  69.         if $opt.is-force &amp;&amp; !$opt.has-value {
  70.             X::Kinoko.new(msg => ($opt.is-short ?? $opt.short-name !! $opt.long-name) ~
  71.                 ": Option value is <a href="/tag/required/" target="_blank" class="keywords">required</a>.").throw();
  72.         }
  73.     }
  74. }
  75. method generate-method(Str $prefix = "") {
  76.     for @!options -> $opt {
  77.         if $opt.is-long {
  78.             self.^add_method($prefix ~ $opt.long-name,my method { $opt; });
  79.             self.^compose();
  80.         }
  81.         if $opt.is-short {
  82.             self.^add_method($prefix ~ $opt.short-name,my method { $opt; });
  83.             self.^compose();
  84.         }
  85.     }
  86.     self;
  87. }
  88. #=[ option-string;option-string;... ]
  89. method append(Str $optionset-str) {
  90.     @!options.push(create-option($_)) for $optionset-str.split(';');
  91.     self;
  92. }
  93. multi method push(*%option) {
  94.     @!options.push: create-option(|%option);
  95.     self;
  96. }
  97. multi method push(Str $option,&amp;callback,$value) {
  98.     @!options.push: create-option($option,cb => &amp;callback,:$value);
  99.     self;
  100. }
  101. #=[
  102.     how to convenient forward parameters ?
  103. ]
  104. method push-str(Str :$short,Str :$long,Bool :$force,Str :$value) {
  105.     self.add-option(sn => $short,ln => $long,:mt<s>);
  106. }
  107. method push-int(Str :$short,Int :$value) {
  108.     self.add-option(sn => $short,:mt<i>);
  109. }
  110. method push-arr(Str :$short,:$value) {
  111.     self.add-option(sn => $short,:mt<a>);
  112. }
  113. method push-hash(Str :$short,:mt<h>);
  114. }
  115. method push-bool(Str :$short,Bool :$value) {
  116.     self.add-option(sn => $short,:mt<b>);
  117. }
  118. method usage() {
  119.     my Str $usage;
  120.     for @!options -> $opt {
  121.         $usage ~= ' [';
  122.         $usage ~= $opt.usage;
  123.         $usage ~= '] ';
  124.     }
  125.     $usage;
  126. }
  127. }

Getopt::Kinoko::Parser

  1. use Getopt::Kinoko::OptionSet;
  2. use Getopt::Kinoko::Exception;

  3. multi sub kinoko-parser(@args is copy,OptionSet \optset) is export returns Array {

  4. my @noa;

  5. my $opt;

  6. my Str $optname;

  7. my $last-is-boolean = False;

  8. my regex lprefix { '--' }
  9. my regex sprefix { '-'  }
  10. my regex optname { .*   { $optname = ~$/; } }
  11. while +@args > 0 {
  12.     my \arg = @args.shift;
  13.     given arg {
  14.         when /^ [<lprefix> || <sprefix>] <.&amp;optname> / {
  15.             if optset.has($optname,long => $<lprefix>.defined,short => $<sprefix>.defined) {
  16.                 $opt := optset.get($optname,short => $<sprefix>.defined);
  17.             }
  18.             else {
  19.                 X::Kinoko::Fail.new().throw;
  20.             }
  21.         }
  22.         default {
  23.             if optset.is-set-noa {
  24.                 optset.process-noa(arg);
  25.             }
  26.             else {
  27.                 @noa.push: arg;
  28.             }
  29.         }
  30.     }
  31.     if +@args > 0 || $opt.is-boolean {
  32.         $last-is-boolean = $opt.is-boolean;
  33.         $opt.set-value($opt.is-boolean ?? True !! @args.shift);
  34.     }
  35.     else {
  36.         X::Kinoko.new(msg => $optname ~ ": Need a value.").throw;
  37.     }
  38. }
  39. @noa;
  40. }

  41. multi sub kinoko-parser(@args is copy,OptionSet \optset,$gnu-style) is export returns Array {

  42. my @noa;

  43. my $opt;

  44. my $optname;

  45. my $optvalue;

  46. my $last-is-boolean = True;

  47. my regex lprefix    { '--' }
  48. my regex sprefix    { '-'  }
  49. my regex optname    { <-[\=]>* { $optname = ~$/; } }
  50. my regex optvalue   { .*   }
  51. while +@args > 0 {
  52.     my \arg = @args.shift;
  53.     given arg {
  54.         when /^ [<lprefix> || <sprefix>]  <.&amp;optname> \= <optvalue> / {
  55.             if optset.has($optname,short => $<sprefix>.defined);
  56.                 X::Kinoko.new(msg => $optname ~ ": Need a value.").throw if !$<optvalue>.defined &amp;&amp; !$opt.is-boolean;
  57.                 $last-is-boolean = $opt.is-boolean;
  58.                 $opt.set-value($opt.is-boolean ?? True !! $<optvalue>);
  59.             }
  60.             elsif $<sprefix>.defined {
  61.                 @args.unshift: | ( '-' X~ $optname.split("",:skip-empty) );
  62.             }
  63.             else {
  64.                 X::Kinoko::Fail.new().throw;
  65.             }
  66.         }
  67.         when /^ [<lprefix> || <sprefix>] <.&amp;optname> / {
  68.             if optset.has($optname,short => $<sprefix>.defined);
  69.                 $last-is-boolean = $opt.is-boolean;
  70.                 if +@args > 0 || $opt.is-boolean {
  71.                     $opt.set-value($opt.is-boolean ?? True !! @args.shift);
  72.                 }
  73.                 else {
  74.                     X::Kinoko.new(msg => $optname ~ ": Need a value.").throw;
  75.                 }
  76.             }
  77.             else {
  78.                 X::Kinoko::Fail.new().throw;
  79.             }
  80.         }
  81.         default {
  82.             W::Kinoko.new("Argument behind boolean option.").warn if $last-is-boolean;
  83.             if optset.is-set-noa {
  84.                 optset.process-noa(arg);
  85.             }
  86.             else {
  87.                 @noa.push: arg;
  88.             }
  89.         }
  90.     }
  91. }
  92. @noa;
  93. }

猜你在找的Perl相关文章