From 72afd8af50dcd0f79ce871aaf0131fa70dd6c239 Mon Sep 17 00:00:00 2001 From: Steve Hancock Date: Tue, 1 Feb 2022 07:14:21 -0800 Subject: [PATCH] add flag -lpil=s as a simpler alternative to -lpxl=s --- CHANGES.md | 4 + bin/perltidy | 126 ++++++++++++++------------ lib/Perl/Tidy.pm | 1 + lib/Perl/Tidy/Formatter.pm | 170 ++++++++++++++++++++++------------- t/snippets/expect/lpxl.lpxl6 | 61 +++++++++++++ t/snippets/lpxl6.par | 2 + t/snippets/packing_list.txt | 1 + t/snippets26.t | 140 ++++++++++++++++++++++++++++- 8 files changed, 383 insertions(+), 122 deletions(-) create mode 100644 t/snippets/expect/lpxl.lpxl6 create mode 100644 t/snippets/lpxl6.par diff --git a/CHANGES.md b/CHANGES.md index d053725e..b11ed093 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -61,6 +61,10 @@ They can be changed with the flag -gaxl=s, -grep-alias-exclusion-list=s + - A new flag -lpil=s, --line-up-parentheses-inclusion-list=s, has been added + as an alternative to -lpxl=s, --line-up-parentheses-exclusion-list=s. + It supplies equivalent information but is easier to describe and use. + - A new flag -xlp has been added which can be set to avoid most of the limitations of the -lp flag regarding side comments, blank lines, and code blocks. This is off by default to avoid changing existing coding, diff --git a/bin/perltidy b/bin/perltidy index 9dae6249..df7d6aee 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -893,58 +893,57 @@ Some things that can be done to minimize these problems are: (1) Increase B<--maximum-line-length=n> above the default B characters if necessary. -(2) Apply this style in a limited way. By default, it applies to all list +(2) If you use B<-xlp> then long side comments can limit the indentation over +multiple lines. Consider adding the flag B<--ignore-side-comment-lengths> to +prevent this, or minimizing the use of side comments. + +(3) Apply this style in a limited way. By default, it applies to all list containers (not just lists in parentheses). The next section describes how to limit this style to, for example, just function calls. The default indentation method will be applied elsewhere. -(3) If you use B<-xlp> then long side comments can limit the indentation over -multiple lines. Consider adding the flag B<--ignore-side-comment-lengths> to -prevent this, or minimizing the use of side comments. - -=item B<-lpxl=s>, B<--line-up-parentheses-exclusion-list> +=item B<-lpil=s>, B<--line-up-parentheses-inclusion-list> and B<-lpxl=s>, B<--line-up-parentheses-exclusion-list> -The following discussion mentions B<-lp> but applies equally to B<-xlp>. +These parameters can be used to restrict the application of the B<-lp> or B<-xlp> styles. +The following discussion is written for B<-lp> but applies equally to the newer B<-xlp> version. The B<-lp> indentation style works well for some types of coding but can produce very long lines when variables have long names and/or containers are -very deeply nested. The B<-lpxl=s> flag is intended to help mitigate this problem by -providing control over the containers to which the B<-lp> indentation style is -applied. The B<-lp> flag by default is "greedy" and applies to as many -containers as possible. This flag specifies a list of things which should -B be use B<-lp> indentation. +very deeply nested. One solution to this problem is to limit the application +of this style to just certain containers. By default, the B<-lp> flag applies +to as many containers as possible. The set of containers to which it applies +can be reduced by either one of these two flags: -This list is a string with space-separated items. Each item consists of up to -three pieces of information in this order: (1) an optional letter code (2) a -required container type, and (3) an optional numeric code. +The B<-lpil=s> flag to specifies the containers to which B<-lp> applies. -The only required piece of information is a container type, which is one of -'(', '[', or '{'. For example the string +The B<-lpxl=s> flag to specifies the containers to which B<-lp> does NOT apply. - -lpxl='[ {' +Only one of these two flags may be used. Both flags can achieve the same +result, but the B<-lpil=s> flag is much easier to describe and use and is +recommended. The B<-lpxl=s> flag was the original implementation and is +retained for backwards compatibility. -means do B include use -lp formatting within square-bracets or braces. The only unspecified -container is '(', so this string means that only the contents within parens will use -lp indentation. +This list B for these parametes is a string with space-separated items. +Each item consists of up to three pieces of information in this order: (1) an +optional letter code (2) a required container type, and (3) an optional numeric +code. -An optional numeric code may follow any of the container types to further refine the selection based -on container contents. The numeric codes are: +The only required piece of information is a container type, which is one of +'(', '[', or '{'. For example the string - '0' or blank: no check on contents - '1' reject -lp unless the contents is a simple list without sublists - '2' reject -lp unless the contents is a simple list without sublists, without - code blocks, and without ternary operators + -lpil='(' -For example, +means use -lp formatting only on lists within parentheses, not lists in square-bracets or braces. +The same thing could alternatively be specified with - -lpxl = '[ { (2' + -lpxl = '[ {' -means only apply -lp to parenthesized lists which do not contain any sublists, -code blocks or ternary expressions. +which says to exclude lists within square-brackets and braces. So what remains is lists within parentheses. -A third optional item of information which can be given for parens is an alphanumeric +A second B item of information which can be given for parentheses is an alphanumeric letter which is used to limit the selection further depending on the type of token immediately before the paren. The possible letters are currently 'k', -'K', 'f', 'F', 'w', and 'W', with these meanings: +'K', 'f', 'F', 'w', and 'W', with these meanings for matching whatever precedes an opening paren: 'k' matches if the previous nonblank token is a perl builtin keyword (such as 'if', 'while'), 'K' matches if 'k' does not, meaning that the previous token is not a keyword. @@ -953,24 +952,37 @@ token immediately before the paren. The possible letters are currently 'k', 'w' matches if either 'k' or 'f' match. 'W' matches if 'w' does not. -The logic of writing these codes is somewhat counter-intuitive because they -describe what is not getting the -lp indentation. So the 'F' indicates that -non-function calls are not getting -lp, or in other words that function calls -are getting the -lp indentation. In practice, one of the following examples -is likely to be appropriate: +For example: + + -lpil = 'f(' + +means only apply -lp to function calls, and - -lpxl = '[ { F(' + -lpil = 'w(' -means only apply -lp to parenthesized lists which follow a function call. +means only apply -lp to parenthesized lists which follow a function or a keyword. + +This last example could alternatively be written using the B<-lpxl=s> flag as -lpxl = '[ { W(' -means only apply -lp to parenthesized lists which follow a keyword or function call. +which says exclude B<-lp> for lists within square-brackets, braces, and parens NOT preceded by +a keyword or function. Clearly, the B<-lpil=s> method is easier to understand. + +An optional numeric code may follow any of the container types to further refine the selection based +on container contents. The numeric codes are: + + '0' or blank: no check on contents is made + '1' exclude B<-lp> unless the contents is a simple list without sublists + '2' exclude B<-lp> unless the contents is a simple list without sublists, without + code blocks, and without ternary operators - -lpxl = '[ { F(2' +For example, -means only apply -lp to parenthesized lists which follow a function call and -which do not contain any sublists, code blocks or ternary expressions. + -lpil = 'f(2' + +means only apply -lp to function call lists which do not contain any sublists, +code blocks or ternary expressions. =item B<-cti=n>, B<--closing-token-indentation> @@ -4050,6 +4062,8 @@ style overrides the default style with the following parameters: -lp -bl -noll -pt=2 -bt=2 -sbt=2 -icp +To use this style with B<-xlp> instead of B<-lp> use B<-gnu -xlp>. + =item B<-pbp>, B<--perl-best-practices> B<-pbp> is an abbreviation for the parameters in the book B @@ -4981,19 +4995,19 @@ The following list shows all short parameter names which allow a prefix baao bar bbao bbb bbc bbs bl bli boa boc bok bol bom bos bot cblx ce conv cs csc cscb cscw dac dbc dcbl dcsc ddf dln dnl dop - dp dpro dsc dsm dsn dtt dwls dwrs dws f - fll fpva frm fs fso gcs hbc hbcm hbco hbh - hbhh hbi hbj hbk hbm hbn hbp hbpd hbpu hbq - hbs hbsc hbv hbw hent hic hicm hico hih hihh - hii hij hik him hin hip hipd hipu hiq his - hisc hiv hiw hsc html ibc icb icp iob isbc - iscl kgb kgbd kgbi kis lal log lop lp lsl - mem nib ohbr okw ola olc oll olq opr opt - osbc osbr otr ple pod pvl q sac sbc sbl - scbb schb scp scsb sct se sfp sfs skp sob - sobb sohb sop sosb sot ssc st sts t tac - tbc toc tp tqw trp ts tsc tso vbc vc - vmll vsc w wn x xci xs + dp dpro dsc dsm dsn dtt dwls dwrs dws eos + f fll fpva frm fs fso gcs hbc hbcm hbco + hbh hbhh hbi hbj hbk hbm hbn hbp hbpd hbpu + hbq hbs hbsc hbv hbw hent hic hicm hico hih + hihh hii hij hik him hin hip hipd hipu hiq + his hisc hiv hiw hsc html ibc icb icp iob + isbc iscl kgb kgbd kgbi kis lal log lop lp + lsl mem nib ohbr okw ola olc oll olq opr + opt osbc osbr otr ple pod pvl q sac sbc + sbl scbb schb scp scsb sct se sfp sfs skp + sob sobb sohb sop sosb sot ssc st sts t + tac tbc toc tp tqw trp ts tsc tso vbc + vc vmll vsc w wn x xci xlp xs Equivalently, the prefix 'no' or 'no-' on the corresponding long names may be used. diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index 3693b91c..33018ee9 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -2334,6 +2334,7 @@ sub generate_options { $add_option->( 'line-up-parentheses', 'lp', '!' ); $add_option->( 'extended-line-up-parentheses', 'xlp', '!' ); $add_option->( 'line-up-parentheses-exclusion-list', 'lpxl', '=s' ); + $add_option->( 'line-up-parentheses-inclusion-list', 'lpil', '=s' ); $add_option->( 'outdent-keyword-list', 'okwl', '=s' ); $add_option->( 'outdent-keywords', 'okw', '!' ); $add_option->( 'outdent-labels', 'ola', '!' ); diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index 72fafad5..d8abcb38 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -283,7 +283,8 @@ my ( %stack_closing_token, %weld_nested_exclusion_rules, - %line_up_parentheses_exclusion_rules, + %line_up_parentheses_control_hash, + $line_up_parentheses_control_is_lxpl, # regex patterns for text identification. # Most are initialized in a sub make_**_pattern during configuration. @@ -1945,7 +1946,27 @@ EOM } initialize_weld_nested_exclusion_rules($rOpts); - initialize_line_up_parentheses_exclusion_rules($rOpts); + + %line_up_parentheses_control_hash = (); + $line_up_parentheses_control_is_lxpl = 1; + my $lpxl = $rOpts->{'line-up-parentheses-exclusion-list'}; + my $lpil = $rOpts->{'line-up-parentheses-inclusion-list'}; + if ( $lpxl && $lpil ) { + Warn( <{'line-up-parentheses-exclusion-list'}, 'lpxl' ); + } + elsif ($lpil) { + $line_up_parentheses_control_is_lxpl = 0; + initialize_line_up_parentheses_control_hash( + $rOpts->{'line-up-parentheses-inclusion-list'}, 'lpil' ); + } + return; } @@ -2139,11 +2160,8 @@ EOM return; } -sub initialize_line_up_parentheses_exclusion_rules { - my ($rOpts) = @_; - %line_up_parentheses_exclusion_rules = (); - my $opt_name = 'line-up-parentheses-exclusion-list'; - my $str = $rOpts->{$opt_name}; +sub initialize_line_up_parentheses_control_hash { + my ( $str, $opt_name ) = @_; return unless ($str); $str =~ s/^\s+//; $str =~ s/\s+$//; @@ -2198,13 +2216,13 @@ sub initialize_line_up_parentheses_exclusion_rules { next; } - if ( !defined( $line_up_parentheses_exclusion_rules{$key} ) ) { - $line_up_parentheses_exclusion_rules{$key} = [ $flag1, $flag2 ]; + if ( !defined( $line_up_parentheses_control_hash{$key} ) ) { + $line_up_parentheses_control_hash{$key} = [ $flag1, $flag2 ]; next; } # check for multiple conflicting specifications - my $rflags = $line_up_parentheses_exclusion_rules{$key}; + my $rflags = $line_up_parentheses_control_hash{$key}; my $err; if ( defined( $rflags->[0] ) && $rflags->[0] ne $flag1 ) { $err = 1; @@ -2232,17 +2250,19 @@ EOM } # Speedup: we can turn off -lp if it is not actually used - my $all_off = 1; - foreach my $key (qw# ( { [ #) { - my $rflags = $line_up_parentheses_exclusion_rules{$key}; - if ( defined($rflags) ) { - my ( $flag1, $flag2 ) = @{$rflags}; - if ( $flag1 && $flag1 ne '*' ) { $all_off = 0; last } - if ($flag2) { $all_off = 0; last } + if ($line_up_parentheses_control_is_lxpl) { + my $all_off = 1; + foreach my $key (qw# ( { [ #) { + my $rflags = $line_up_parentheses_control_hash{$key}; + if ( defined($rflags) ) { + my ( $flag1, $flag2 ) = @{$rflags}; + if ( $flag1 && $flag1 ne '*' ) { $all_off = 0; last } + if ($flag2) { $all_off = 0; last } + } + } + if ($all_off) { + $rOpts->{'line-up-parentheses'} = ""; } - } - if ($all_off) { - $rOpts->{'line-up-parentheses'} = ""; } return; @@ -11183,61 +11203,82 @@ EOM sub is_excluded_lp { - # decide if this container is excluded by user request - # returns true if this token is excluded (i.e., may not use -lp) - # returns false otherwise + # Decide if this container is excluded by user request: + # returns true if this token is excluded (i.e., may not use -lp) + # returns false otherwise + + # The control hash can either describe: + # what to exclude: $line_up_parentheses_control_is_lxpl = 1, or + # what to include: $line_up_parentheses_control_is_lxpl = 0 - # note similarity with sub 'is_excluded_weld' my ( $self, $KK ) = @_; my $rLL = $self->[_rLL_]; my $rtoken_vars = $rLL->[$KK]; my $token = $rtoken_vars->[_TOKEN_]; - my $rflags = $line_up_parentheses_exclusion_rules{$token}; - return 0 unless ( defined($rflags) ); + my $rflags = $line_up_parentheses_control_hash{$token}; + + #----------------------------------------------- + # TEST #1: check match to listed container types + #----------------------------------------------- + if ( !defined($rflags) ) { + + # There is no entry for this container, so we are done + return !$line_up_parentheses_control_is_lxpl; + } + my ( $flag1, $flag2 ) = @{$rflags}; - # There are two flags: - # flag1 excludes based on the preceding nonblank word - # flag2 excludes based on the contents of the container - return 0 unless ( defined($flag1) ); - return 1 if $flag1 eq '*'; + #----------------------------------------------------------- + # TEST #2: check match to flag1, the preceding nonblank word + #----------------------------------------------------------- + my $match_flag1 = !defined($flag1) || $flag1 eq '*'; + if ( !$match_flag1 ) { - # Find the previous token - my ( $is_f, $is_k, $is_w ); - my $Kp = $self->K_previous_nonblank($KK); - if ( defined($Kp) ) { - my $type_p = $rLL->[$Kp]->[_TYPE_]; - my $seqno = $rtoken_vars->[_TYPE_SEQUENCE_]; + # Find the previous token + my ( $is_f, $is_k, $is_w ); + my $Kp = $self->K_previous_nonblank($KK); + if ( defined($Kp) ) { + my $type_p = $rLL->[$Kp]->[_TYPE_]; + my $seqno = $rtoken_vars->[_TYPE_SEQUENCE_]; - # keyword? - $is_k = $type_p eq 'k'; + # keyword? + $is_k = $type_p eq 'k'; - # function call? - $is_f = $self->[_ris_function_call_paren_]->{$seqno}; + # function call? + $is_f = $self->[_ris_function_call_paren_]->{$seqno}; - # either keyword or function call? - $is_w = $is_k || $is_f; + # either keyword or function call? + $is_w = $is_k || $is_f; + } + + # Check for match based on flag1 and the previous token: + if ( $flag1 eq 'k' ) { $match_flag1 = $is_k } + elsif ( $flag1 eq 'K' ) { $match_flag1 = !$is_k } + elsif ( $flag1 eq 'f' ) { $match_flag1 = $is_f } + elsif ( $flag1 eq 'F' ) { $match_flag1 = !$is_f } + elsif ( $flag1 eq 'w' ) { $match_flag1 = $is_w } + elsif ( $flag1 eq 'W' ) { $match_flag1 = !$is_w } } - # Check for exclusion based on flag1 and the previous token: - my $match; - if ( $flag1 eq 'k' ) { $match = $is_k } - elsif ( $flag1 eq 'K' ) { $match = !$is_k } - elsif ( $flag1 eq 'f' ) { $match = $is_f } - elsif ( $flag1 eq 'F' ) { $match = !$is_f } - elsif ( $flag1 eq 'w' ) { $match = $is_w } - elsif ( $flag1 eq 'W' ) { $match = !$is_w } - return $match if ($match); - - # Check for exclusion based on flag2 and the container contents - # Current options to filter on contents: - # 0 or blank: ignore container contents - # 1 exclude non-lists or lists with sublists - # 2 same as 1 but also exclude lists with code blocks - - # Note: - # Containers with multiline-qw containers are automatically - # excluded so do not need to be checked. + # See if we can exclude this based on the flag1 test... + if ($line_up_parentheses_control_is_lxpl) { + return 1 if ($match_flag1); + } + else { + return 1 if ( !$match_flag1 ); + } + + #------------------------------------------------------------- + # TEST #3: exclusion based on flag2 and the container contents + #------------------------------------------------------------- + + # Note that this is an exclusion test for both -lpxl or -lpil input methods + # The options are: + # 0 or blank: ignore container contents + # 1 exclude non-lists or lists with sublists + # 2 same as 1 but also exclude lists with code blocks + + my $match_flag2; if ($flag2) { my $seqno = $rtoken_vars->[_TYPE_SEQUENCE_]; @@ -11246,14 +11287,15 @@ sub is_excluded_lp { my $has_list = $self->[_rhas_list_]->{$seqno}; my $has_code_block = $self->[_rhas_code_block_]->{$seqno}; my $has_ternary = $self->[_rhas_ternary_]->{$seqno}; + if ( !$is_list || $has_list || $flag2 eq '2' && ( $has_code_block || $has_ternary ) ) { - $match = 1; + $match_flag2 = 1; } } - return $match; + return $match_flag2; } sub set_excluded_lp_containers { diff --git a/t/snippets/expect/lpxl.lpxl6 b/t/snippets/expect/lpxl.lpxl6 new file mode 100644 index 00000000..de0dfa6a --- /dev/null +++ b/t/snippets/expect/lpxl.lpxl6 @@ -0,0 +1,61 @@ +# simple function call +my $loanlength = getLoanLength( + $borrower->{'categorycode'}, # sc1 + $iteminformation->{'itemtype'}, + $borrower->{'branchcode'} # sc3 +); + +# function call, more than one level deep +my $o = very::long::class::name->new( + { + propA => "a", + propB => "b", + propC => "c", + } +); + +# function call with sublist +debug( + "Connecting to DB.", + "Extra-Parameters: " . join( "<->", $extra_parms ), + "Config: " . join( "<->", %config ) +); + +# simple function call with code block +$m->command( + -label => 'Save', + -command => sub { print "DOS\n"; save_dialog($win); } +); + +# function call, ternary in list +return OptArgs2::Result->usage( + $style == OptArgs2::STYLE_FULL ? 'FullUsage' : 'NormalUsage', + 'usage: ' . $usage . "\n" ); + +# not a function call +%blastparam = ( + -run => \%runparam, + -file => '', + -parse => 1, + -signif => 1e-5, +); + +# 'local' is a keyword, not a user function +local ( + $len, $pts, @colspec, $char, $cols, + $repeat, $celldata, $at_text, $after_text +); + +# square bracket with sublists +$data = [ + ListElem->new( id => 0, val => 100 ), + ListElem->new( id => 2, val => 50 ), + ListElem->new( id => 1, val => 10 ), +]; + +# curly brace with sublists +$behaviour = { + cat => { nap => "lap", eat => "meat" }, + dog => { prowl => "growl", pool => "drool" }, + mouse => { nibble => "kibble" }, +}; diff --git a/t/snippets/lpxl6.par b/t/snippets/lpxl6.par new file mode 100644 index 00000000..5f58daed --- /dev/null +++ b/t/snippets/lpxl6.par @@ -0,0 +1,2 @@ +# equivalent to -lpxl='{ [ F(2' +-lp -lpil='f(2' diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt index 79792a54..1749d9ad 100644 --- a/t/snippets/packing_list.txt +++ b/t/snippets/packing_list.txt @@ -488,3 +488,4 @@ ../snippets9.t rt98902.def ../snippets9.t rt98902.rt98902 ../snippets9.t rt99961.def +../snippets26.t lpxl.lpxl6 diff --git a/t/snippets26.t b/t/snippets26.t index 7fa76d1f..d46fcf1f 100644 --- a/t/snippets26.t +++ b/t/snippets26.t @@ -3,6 +3,7 @@ # Contents: #1 bal.bal2 #2 bal.def +#3 lpxl.lpxl6 # To locate test #13 you can search for its name or the string '#13' @@ -20,8 +21,12 @@ BEGIN { # BEGIN SECTION 1: Parameter combinations # ########################################### $rparams = { - 'bal2' => "-bal=2", - 'def' => "", + 'bal2' => "-bal=2", + 'def' => "", + 'lpxl6' => <<'----------', +# equivalent to -lpxl='{ [ F(2' +-lp -lpil='f(2' +---------- }; ############################ @@ -35,6 +40,69 @@ BEGIN { L2: L3: return; }; +---------- + + 'lpxl' => <<'----------', +# simple function call +my $loanlength = getLoanLength( + $borrower->{'categorycode'}, # sc1 + $iteminformation->{'itemtype'}, + $borrower->{'branchcode'} # sc3 +); + +# function call, more than one level deep +my $o = very::long::class::name->new( + { + propA => "a", + propB => "b", + propC => "c", + } +); + +# function call with sublist +debug( + "Connecting to DB.", + "Extra-Parameters: " . join("<->", $extra_parms), + "Config: " . join("<->", %config) + ); + +# simple function call with code block +$m->command(-label => 'Save', + -command => sub { print "DOS\n"; save_dialog($win); }); + +# function call, ternary in list +return + OptArgs2::Result->usage( + $style == OptArgs2::STYLE_FULL ? 'FullUsage' : 'NormalUsage', + 'usage: ' . $usage . "\n" ); + +# not a function call +%blastparam = ( + -run => \%runparam, + -file => '', + -parse => 1, + -signif => 1e-5, +); + +# 'local' is a keyword, not a user function + local ( + $len, $pts, @colspec, $char, $cols, + $repeat, $celldata, $at_text, $after_text + ); + +# square bracket with sublists +$data = [ + ListElem->new(id => 0, val => 100), + ListElem->new(id => 2, val => 50), + ListElem->new(id => 1, val => 10), + ]; + +# curly brace with sublists +$behaviour = { + cat => {nap => "lap", eat => "meat"}, + dog => {prowl => "growl", pool => "drool"}, + mouse => {nibble => "kibble"}, + }; ---------- }; @@ -64,6 +132,74 @@ BEGIN { }; #2........... }, + + 'lpxl.lpxl6' => { + source => "lpxl", + params => "lpxl6", + expect => <<'#3...........', +# simple function call +my $loanlength = getLoanLength( + $borrower->{'categorycode'}, # sc1 + $iteminformation->{'itemtype'}, + $borrower->{'branchcode'} # sc3 +); + +# function call, more than one level deep +my $o = very::long::class::name->new( + { + propA => "a", + propB => "b", + propC => "c", + } +); + +# function call with sublist +debug( + "Connecting to DB.", + "Extra-Parameters: " . join( "<->", $extra_parms ), + "Config: " . join( "<->", %config ) +); + +# simple function call with code block +$m->command( + -label => 'Save', + -command => sub { print "DOS\n"; save_dialog($win); } +); + +# function call, ternary in list +return OptArgs2::Result->usage( + $style == OptArgs2::STYLE_FULL ? 'FullUsage' : 'NormalUsage', + 'usage: ' . $usage . "\n" ); + +# not a function call +%blastparam = ( + -run => \%runparam, + -file => '', + -parse => 1, + -signif => 1e-5, +); + +# 'local' is a keyword, not a user function +local ( + $len, $pts, @colspec, $char, $cols, + $repeat, $celldata, $at_text, $after_text +); + +# square bracket with sublists +$data = [ + ListElem->new( id => 0, val => 100 ), + ListElem->new( id => 2, val => 50 ), + ListElem->new( id => 1, val => 10 ), +]; + +# curly brace with sublists +$behaviour = { + cat => { nap => "lap", eat => "meat" }, + dog => { prowl => "growl", pool => "drool" }, + mouse => { nibble => "kibble" }, +}; +#3........... + }, }; my $ntests = 0 + keys %{$rtests}; -- 2.39.5