]> git.donarmstrong.com Git - perltidy.git/commitdiff
Add flags -lpxl=s and simplified form -lfp, requested in git #56
authorSteve Hancock <perltidy@users.sourceforge.net>
Thu, 25 Mar 2021 15:13:22 +0000 (08:13 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Thu, 25 Mar 2021 15:13:22 +0000 (08:13 -0700)
19 files changed:
CHANGES.md
bin/perltidy
lib/Perl/Tidy.pm
lib/Perl/Tidy/Formatter.pm
local-docs/BugLog.pod
t/snippets/expect/lpxl.def [new file with mode: 0644]
t/snippets/expect/lpxl.lpxl1 [new file with mode: 0644]
t/snippets/expect/lpxl.lpxl2 [new file with mode: 0644]
t/snippets/expect/lpxl.lpxl3 [new file with mode: 0644]
t/snippets/expect/lpxl.lpxl4 [new file with mode: 0644]
t/snippets/expect/lpxl.lpxl5 [new file with mode: 0644]
t/snippets/lpxl.in [new file with mode: 0644]
t/snippets/lpxl1.par [new file with mode: 0644]
t/snippets/lpxl2.par [new file with mode: 0644]
t/snippets/lpxl3.par [new file with mode: 0644]
t/snippets/lpxl4.par [new file with mode: 0644]
t/snippets/lpxl5.par [new file with mode: 0644]
t/snippets/packing_list.txt
t/snippets24.t

index b9b32959dce3edc63d00541ed7f96195be456aff..2dac997a92ad93ed8c7e5dbbbe902f881341cb9a 100644 (file)
@@ -2,6 +2,11 @@
 
 ## 2021 01 xx
 
+    - Fixed issue git #57 regarding uninitialized warning flag.
+
+    - Added flag -lpxl for issue git #56, providing some control over which
+    containers get -lp indentation. 
+
     - Fixed issue git #55 regarding lack of coordination of the --break-before-xxx
     flags and the --line-up-parens flag.
 
index 7a240df312bce8e02e86de3047e46b8191927741..0ddb9529ba72fab52520d0f19b0123894abb00f8 100755 (executable)
@@ -842,6 +842,92 @@ B<-ndnl>.  The reason is that the B<-lp> indentation style can require
 the careful coordination of an arbitrary number of break points in
 hierarchical lists, and these flags may prevent that.
 
+=item B<-lpxl=s>,  B<--line-up-parentheses-exclusion-list>
+
+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 can 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<not> be use B<-lp> indentation.
+
+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 only required piece of information is a container type, which is one of
+'(', '[', or '{'.  For example the string
+
+  -lpxl='[ {'
+
+means do B<NOT> include use -lp formatting within square-bracets or braces.  The only unspecified
+container is '(', so this string means that only the contens within parens will use -lp indentation.
+
+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
+  '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
+
+For example,
+
+  -lpxl = '[ { (2'
+
+means only apply -lp to parenthesized lists which do not contain any sublists,
+code blocks or ternary expressions.
+
+A third optional item of information which can be given for parens 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' 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.
+ 'f' matches if the previous token is a function other than a keyword.
+ 'F' matches if 'f' does not.
+ 'w' matches if either 'k' or 'f' match.
+ 'W' matches if 'w' does not.
+
+For example,
+
+  -lpxl = '[ { F(2'
+
+means only apply -lp to parenthesized lists which follow a function call and
+which do not contain any sublists, code blocks or ternary expressions.  The logic
+of writing these codes is 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.
+To simplify things, the next section has a shortcut form for the previous
+example, since it is expected to be the most useful.
+
+=item B<-lfp>,  B<--line-up-function-parentheses>
+
+This is a shortcut for
+
+  -lp -lpxl = '[ { F(2'
+
+which means only apply -lp to parenthesized lists which follow a function call
+and which do not contain any sublists, code blocks or ternary expressions. For
+example,
+
+    # perltidy -lfp
+    my $loanlength = getLoanLength(
+                                    $borrower->{'categorycode'},
+                                    $iteminformation->{'itemtype'},
+                                    $borrower->{'branchcode'}
+    );
+
+    # perltidy -lfp
+    @month_of_year = (
+        'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
+    );
+
+The first of these examples is a simple function call, but the second is not.
+
 =item B<-cti=n>, B<--closing-token-indentation>
 
 The B<-cti=n> flag controls the indentation of a line beginning with 
@@ -2484,7 +2570,7 @@ Here is an example illustrating a welded container within a welded containers:
 
 The welded closing tokens are by default on a separate line but this can be
 modified with the B<-vtc=n> flag (described in the next section).  For example,
-the same example adding B<-vtc-2> is
+the same example adding B<-vtc=2> is
 
        # perltidy -wn -vtc=2
         $x->badd( bmul(
@@ -2517,7 +2603,7 @@ token is being considered for joining a weld, any exclusion rules are consulted
 and used to reject the weld if necessary.
 
 This list is a string with space-separated items.  Each item consists of up to
-three pieces of information: (1) an optional positiion, (2) an optional
+three pieces of information: (1) an optional position, (2) an optional
 preceding type, and (3) a container type.
 
 The only required piece of information is a container type, which is one of
@@ -2563,7 +2649,7 @@ token immediately before the container.  If given, it goes just before the
 container symbol.  The possible letters are currently 'k', 'K', 'f', 'F',
 'w', and 'W', with these meanings:
 
- 'k' matches if the previous nonblank token is a perl builtin keyword (such as 'if', 'while'), 
+ '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.
  'f' matches if the previous token is a function other than a keyword.
  'F' matches if 'f' does not.
index 19344d026eda8fe538a7543f9662bcb7b76def62..3eac01bf7802a34070d1c895da91efa992a5f052 100644 (file)
@@ -1491,7 +1491,7 @@ EOM
 
                             # Blinking (oscillating) between two or more stable
                             # end states.  This is unlikely to occur with normal
-                            # parameters, but it can occur in stress testing 
+                            # parameters, but it can occur in stress testing
                             # with extreme parameter values, such as very short
                             # maximum line lengths.  We want to catch and fix
                             # them when they happen.
@@ -2251,6 +2251,7 @@ sub generate_options {
     $add_option->( 'continuation-indentation',           'ci',   '=i' );
     $add_option->( 'extended-continuation-indentation',  'xci',  '!' );
     $add_option->( 'line-up-parentheses',                'lp',   '!' );
+    $add_option->( 'line-up-parentheses-exclusion-list', 'lpxl', '=s' );
     $add_option->( 'outdent-keyword-list',               'okwl', '=s' );
     $add_option->( 'outdent-keywords',                   'okw',  '!' );
     $add_option->( 'outdent-labels',                     'ola',  '!' );
@@ -2783,6 +2784,9 @@ sub generate_options {
         'conv'       => [qw(it=4)],
         'nconv'      => [qw(it=1)],
 
+        'line-up-function-parentheses' => [ qw(lp), q#lpxl=[ { F(2# ],
+        'lfp'                          => [qw(line-up-function-parentheses)],
+
         # 'mangle' originally deleted pod and comments, but to keep it
         # reversible, it no longer does.  But if you really want to
         # delete them, just use:
index 9a20b468eae21eba1e76fd6a401013422aa40491..4899bc3fd3f0b0e3e7129b60c035ac1504fb6de5 100644 (file)
@@ -254,6 +254,7 @@ my (
     %stack_closing_token,
 
     %weld_nested_exclusion_rules,
+    %line_up_parentheses_exclusion_rules,
 
     # regex patterns for text identification.
     # Most are initialized in a sub make_**_pattern during configuration.
@@ -351,12 +352,17 @@ BEGIN {
         _K_first_seq_item_                 => $i++,
         _rK_phantom_semicolons_            => $i++,
         _rtype_count_by_seqno_             => $i++,
+        _ris_function_call_paren_          => $i++,
         _rlec_count_by_seqno_              => $i++,
         _ris_broken_container_             => $i++,
         _ris_permanently_broken_container_ => $i++,
         _rhas_list_                        => $i++,
         _rhas_broken_list_                 => $i++,
         _rhas_broken_list_with_lec_        => $i++,
+        _rhas_code_block_                  => $i++,
+        _rhas_broken_code_block_           => $i++,
+        _rhas_ternary_                     => $i++,
+        _ris_excluded_lp_container_        => $i++,
         _rwant_reduced_ci_                 => $i++,
         _ris_bli_container_                => $i++,
         _rparent_of_seqno_                 => $i++,
@@ -698,12 +704,17 @@ sub new {
     $self->[_rK_phantom_semicolons_] =
       undef;    # for undoing phantom semicolons if iterating
     $self->[_rtype_count_by_seqno_]             = {};
+    $self->[_ris_function_call_paren_]          = {};
     $self->[_rlec_count_by_seqno_]              = {};
     $self->[_ris_broken_container_]             = {};
     $self->[_ris_permanently_broken_container_] = {};
     $self->[_rhas_list_]                        = {};
     $self->[_rhas_broken_list_]                 = {};
     $self->[_rhas_broken_list_with_lec_]        = {};
+    $self->[_rhas_code_block_]                  = {};
+    $self->[_rhas_broken_code_block_]           = {};
+    $self->[_rhas_ternary_]                     = {};
+    $self->[_ris_excluded_lp_container_]        = {};
     $self->[_rwant_reduced_ci_]                 = {};
     $self->[_ris_bli_container_]                = {};
     $self->[_rparent_of_seqno_]                 = {};
@@ -1578,6 +1589,7 @@ EOM
     }
 
     initialize_weld_nested_exclusion_rules($rOpts);
+    initialize_line_up_parentheses_exclusion_rules($rOpts);
     return;
 }
 
@@ -1693,7 +1705,7 @@ EOM
     }
     if ($msg2) {
         Warn(<<EOM);
-Multiple specifications were encountered in the --weld-nested-exclusion-list at:
+Multiple specifications were encountered in the --weld-nested-exclusion-list for:
 $msg2
 Only the last will be used.
 EOM
@@ -1701,6 +1713,115 @@ 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};
+    return unless ($str);
+    $str =~ s/^\s+//;
+    $str =~ s/\s+$//;
+    return unless ($str);
+
+    # The format is space separated items, where each item must consist of a
+    # string with a token type preceded by an optional text token and followed
+    # by an integer:
+    # For example:
+    #    W(1
+    #  = (flag1)(key)(flag2), where
+    #    flag1 = 'W'
+    #    key = '('
+    #    flag2 = '1'
+
+    my @items = split /\s+/, $str;
+    my $msg1;
+    my $msg2;
+    foreach my $item (@items) {
+        my $item_save = $item;
+        my ( $flag1, $key, $flag2 );
+        if ( $item =~ /^([^\(\]\{]*)?([\(\{\[])(\d)?$/ ) {
+            $flag1 = $1 if $1;
+            $key   = $2 if $2;
+            $flag2 = $3 if $3;
+        }
+        else {
+            $msg1 .= " '$item_save'";
+            next;
+        }
+
+        if ( !defined($key) ) {
+            $msg1 .= " '$item_save'";
+            next;
+        }
+
+        # Check for valid flag1
+        if    ( !defined($flag1) ) { $flag1 = '*' }
+        elsif ( $flag1 !~ /^[kKfFwW\*]$/ ) {
+            $msg1 .= " '$item_save'";
+            next;
+        }
+
+        # Check for valid flag2
+        # 0 or blank: ignore container contents
+        # 1 all containers with sublists match
+        # 2 all containers with sublists, code blocks or ternary operators match
+        # ... this could be extended in the future
+        if    ( !defined($flag2) ) { $flag2 = 0 }
+        elsif ( $flag2 !~ /^[012]$/ ) {
+            $msg1 .= " '$item_save'";
+            next;
+        }
+
+        if ( !defined( $line_up_parentheses_exclusion_rules{$key} ) ) {
+            $line_up_parentheses_exclusion_rules{$key} = [ $flag1, $flag2 ];
+            next;
+        }
+
+        # check for multiple conflicting specifications
+        my $rflags = $line_up_parentheses_exclusion_rules{$key};
+        my $err;
+        if ( defined( $rflags->[0] ) && $rflags->[0] ne $flag1 ) {
+            $err = 1;
+            $rflags->[0] = $flag1;
+        }
+        if ( defined( $rflags->[1] ) && $rflags->[1] ne $flag2 ) {
+            $err = 1;
+            $rflags->[1] = $flag2;
+        }
+        $msg2 .= " '$item_save'" if ($err);
+        next;
+    }
+    if ($msg1) {
+        Warn(<<EOM);
+Unexpecting symbol(s) encountered in --$opt_name will be ignored:
+$msg1
+EOM
+    }
+    if ($msg2) {
+        Warn(<<EOM);
+Multiple specifications were encountered in the $opt_name at:
+$msg2
+Only the last will be used.
+EOM
+    }
+
+    # Speedup: Turn off -lp if it is not 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 ($all_off) {
+        $rOpts->{'line-up-parentheses'} = "";
+    }
+
+    return;
+}
+
 sub initialize_whitespace_hashes {
 
     # This is called once before formatting begins to initialize these global
@@ -1855,7 +1976,8 @@ sub set_whitespace_flags {
     my $rOpts_space_backslash_quote = $rOpts->{'space-backslash-quote'};
     my $rOpts_space_function_paren  = $rOpts->{'space-function-paren'};
 
-    my $rwhitespace_flags = [];
+    my $rwhitespace_flags       = [];
+    my $ris_function_call_paren = {};
 
     my %is_for_foreach = ( 'for' => 1, 'foreach' => 1 );
 
@@ -2169,12 +2291,19 @@ sub set_whitespace_flags {
             # 'w' and 'i' checks for something like:
             #   myfun(    &myfun(   ->myfun(
             # -----------------------------------------------------
+
+            # Note that at this point an identifier may still have a leading
+            # arrow, but the arrow will be split off during token respacing.
+            # After that, the token may become a bare word without leading
+            # arrow.  The point is, it is best to mark function call parens
+            # right here before that happens.
             # Patch: added 'C' to prevent blinker, case b934, i.e. 'pi()'
             elsif (( $last_type =~ /^[wCUG]$/ )
                 || ( $last_type =~ /^[wi]$/ && $last_token =~ /^(\&|->)/ ) )
             {
                 $ws = WS_NO unless ($rOpts_space_function_paren);
                 $set_container_ws_by_keyword->( $last_token, $seqno );
+                $ris_function_call_paren->{$seqno} = 1;
             }
 
             # space between something like $i and ( in <<snippets/space2.in>>
@@ -2360,6 +2489,7 @@ sub set_whitespace_flags {
     if ( $rOpts->{'tight-secret-operators'} ) {
         new_secret_operator_whitespace( $rLL, $rwhitespace_flags );
     }
+    $self->[_ris_function_call_paren_] = $ris_function_call_paren;
     return $rwhitespace_flags;
 
 } ## end sub set_whitespace_flags
@@ -4734,6 +4864,8 @@ EOM
 
     $self->adjust_indentation_levels();
 
+    $self->set_excluded_lp_containers();
+
     # Finishes formatting and write the result to the line sink.
     # Eventually this call should just change the 'rlines' data according to the
     # new line breaks and then return so that we can do an internal iteration
@@ -4826,9 +4958,14 @@ sub respace_tokens {
     my $rlec_count_by_seqno              = {};
     my $ris_broken_container             = {};
     my $ris_permanently_broken_container = {};
+    my $ris_list_by_seqno                = {};
     my $rhas_list                        = {};
     my $rhas_broken_list                 = {};
     my $rhas_broken_list_with_lec        = {};
+    my $rhas_code_block                  = {};
+    my $rhas_broken_code_block           = {};
+    my $rhas_ternary                     = {};
+    my $ris_excluded_lp_container        = {};
     my $rparent_of_seqno                 = {};
     my $rchildren_of_seqno               = {};
 
@@ -5494,6 +5631,13 @@ sub respace_tokens {
                     # the correct container.
                     $depth_next--;
                 }
+
+                # For ternary, note parent but do not include as child
+                else {
+                    my $seqno_parent = $seqno_stack{ $depth_next - 1 };
+                    $seqno_parent = SEQ_ROOT unless defined($seqno_parent);
+                    $rparent_of_seqno->{$type_sequence} = $seqno_parent;
+                }
             }
 
             # Modify certain tokens here for whitespace
@@ -5788,7 +5932,6 @@ sub respace_tokens {
     }
 
     # Find and remember lists by sequence number
-    my $ris_list_by_seqno = {};
     foreach my $seqno ( keys %{$K_opening_container} ) {
         my $K_opening = $K_opening_container->{$seqno};
         next unless defined($K_opening);
@@ -5802,10 +5945,24 @@ sub respace_tokens {
         my $line_diff = $lx_close - $lx_open;
         $ris_broken_container->{$seqno} = $line_diff;
 
-        # The rest is only for lists, not for code blocks
+        # Handle code blocks
         my $block_type = $rLL_new->[$K_opening]->[_BLOCK_TYPE_];
-        next if ($block_type);
+        if ($block_type) {
+
+            # The -lp option needs to know if a container holds a code block
+            next unless ($rOpts_line_up_parentheses);
+
+            my $seqno_parent = $rparent_of_seqno->{$seqno};
+            while ( defined($seqno_parent) && $seqno_parent ne SEQ_ROOT ) {
+                $rhas_code_block->{$seqno_parent}        = 1;
+                $rhas_broken_code_block->{$seqno_parent} = $line_diff;
+                $seqno_parent = $rparent_of_seqno->{$seqno_parent};
+            }
+
+            next;
+        }
 
+        # Handle lists
         my $rtype_count = $rtype_count_by_seqno->{$seqno};
         next unless ($rtype_count);
         my $comma_count     = $rtype_count->{','};
@@ -5818,7 +5975,7 @@ sub respace_tokens {
         if ($is_list) {
             $ris_list_by_seqno->{$seqno} = $seqno;
             my $seqno_parent = $rparent_of_seqno->{$seqno};
-            if ( defined($seqno_parent) && $seqno_parent ne SEQ_ROOT ) {
+            while ( defined($seqno_parent) && $seqno_parent ne SEQ_ROOT ) {
                 $rhas_list->{$seqno_parent} = 1;
                 if ($line_diff) {
                     $rhas_broken_list->{$seqno_parent} = 1;
@@ -5830,10 +5987,20 @@ sub respace_tokens {
                     $rhas_broken_list_with_lec->{$seqno_parent} = 1
                       if ( $rlec_count_by_seqno->{$seqno} );
                 }
+                $seqno_parent = $rparent_of_seqno->{$seqno_parent};
             }
         }
     }
 
+    # Find containers with ternaries, needed for -lp formatting.
+    foreach my $seqno ( keys %{$K_opening_ternary} ) {
+        my $seqno_parent = $rparent_of_seqno->{$seqno};
+        while ( defined($seqno_parent) && $seqno_parent ne SEQ_ROOT ) {
+            $rhas_ternary->{$seqno_parent} = 1;
+            $seqno_parent = $rparent_of_seqno->{$seqno_parent};
+        }
+    }
+
     # Reset memory to be the new array
     $self->[_rLL_] = $rLL_new;
     my $Klimit;
@@ -5850,6 +6017,9 @@ sub respace_tokens {
     $self->[_rhas_list_]                 = $rhas_list;
     $self->[_rhas_broken_list_]          = $rhas_broken_list;
     $self->[_rhas_broken_list_with_lec_] = $rhas_broken_list_with_lec;
+    $self->[_rhas_code_block_]           = $rhas_code_block;
+    $self->[_rhas_broken_code_block_]    = $rhas_broken_code_block;
+    $self->[_rhas_ternary_]              = $rhas_ternary;
     $self->[_rparent_of_seqno_]          = $rparent_of_seqno;
     $self->[_rchildren_of_seqno_]        = $rchildren_of_seqno;
     $self->[_ris_list_by_seqno_]         = $ris_list_by_seqno;
@@ -6770,18 +6940,14 @@ sub is_excluded_weld {
     my ( $is_f, $is_k, $is_w );
     my $Kp = $self->K_previous_nonblank($KK);
     if ( defined($Kp) ) {
-        my $type_p  = $rLL->[$Kp]->[_TYPE_];
-        my $token_p = $rLL->[$Kp]->[_TOKEN_];
+        my $seqno  = $rtoken_vars->[_TYPE_SEQUENCE_];
+        my $type_p = $rLL->[$Kp]->[_TYPE_];
 
         # keyword?
         $is_k = $type_p eq 'k';
 
-        # function call? Use the same definition as used for
-        # the parameter 'space-function-paren'
-        $is_f =
-             $type_p =~ /^[wUG]$/
-          || $type_p eq '->'
-          || $type_p =~ /^[wi]$/ && $token_p =~ /^(\&|->)/;
+        # function call?
+        $is_f = $self->[_ris_function_call_paren_]->{$seqno};
 
         # either keyword or function call?
         $is_w = $is_k || $is_f;
@@ -8004,7 +8170,9 @@ sub break_before_list_opening_containers {
 
         # This must be a list (this will exclude all code blocks)
         # or contain a list.
-        # Note: switched from testing has_broken_list to has_list to fix b1024.
+        # Note1: switched from 'has_broken_list' to 'has_list' to fix b1024.
+        # Note2: 'has_list' previously was just one level deep, but has been
+        #  changed to include all levels. This does not change much formatting.
         next unless ( $is_list || $has_list );
 
         # Only for types of container tokens with a non-default break option
@@ -8557,6 +8725,106 @@ EOM
     return;
 }
 
+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
+
+    # 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 ( $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 '*';
+
+    # 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';
+
+        # function call?
+        $is_f = $self->[_ris_function_call_paren_]->{$seqno};
+
+        # either keyword or function call?
+        $is_w = $is_k || $is_f;
+    }
+
+    # 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.
+    if ($flag2) {
+
+        my $seqno = $rtoken_vars->[_TYPE_SEQUENCE_];
+
+        my $is_list        = $self->[_ris_list_by_seqno_]->{$seqno};
+        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;
+        }
+    }
+    return $match;
+}
+
+sub set_excluded_lp_containers {
+
+    my ($self) = @_;
+    return unless ($rOpts_line_up_parentheses);
+    my $rLL = $self->[_rLL_];
+    return unless ( defined($rLL) && @{$rLL} );
+
+    my $K_opening_container       = $self->[_K_opening_container_];
+    my $ris_excluded_lp_container = $self->[_ris_excluded_lp_container_];
+
+    foreach my $seqno ( keys %{$K_opening_container} ) {
+        my $KK = $K_opening_container->{$seqno};
+        next unless defined($KK);
+
+        # code blocks are always excluded by the -lp coding so we can skip them
+        next if ( $rLL->[$KK]->[_BLOCK_TYPE_] );
+
+        # see if a user exclusion rule turns off -lp for this container
+        if ( $self->is_excluded_lp($KK) ) {
+            $ris_excluded_lp_container->{$seqno} = 1;
+        }
+    }
+    return;
+}
+
 ######################################
 # CODE SECTION 6: Process line-by-line
 ######################################
@@ -17118,9 +17386,10 @@ sub get_available_spaces_to_go {
         return unless ($rOpts_line_up_parentheses);
         return unless ( defined($max_index_to_go) && $max_index_to_go >= 0 );
 
-        my $rbreak_container = $self->[_rbreak_container_];
-        my $rshort_nested    = $self->[_rshort_nested_];
-        my $rLL              = $self->[_rLL_];
+        my $rbreak_container          = $self->[_rbreak_container_];
+        my $rshort_nested             = $self->[_rshort_nested_];
+        my $ris_excluded_lp_container = $self->[_ris_excluded_lp_container_];
+        my $rLL                       = $self->[_rLL_];
         my $rbreak_before_container_by_seqno =
           $self->[_rbreak_before_container_by_seqno_];
 
@@ -17398,6 +17667,13 @@ sub get_available_spaces_to_go {
                 $space_count += $standard_increment;
             }
 
+            # add the standard increment for containers excluded by user rules
+            elsif ( defined($last_nonblank_seqno)
+                && $ris_excluded_lp_container->{$last_nonblank_seqno} )
+            {
+                $space_count += $standard_increment;
+            }
+
             # if last nonblank token was not structural indentation,
             # just use standard increment
             elsif ( $last_nonblank_type ne '{' ) {
index defb4be28da62a7360be43e8fa7a0d3a6d1cdbc1..516392a664d87d814a16a2c617c999bc1ec54b16 100644 (file)
@@ -2,12 +2,20 @@
 
 =over 4
 
+=item B<Add flag -lpxl=s to provide control over -lp formatting>
+
+The flag -lpxl=s provides control over which containers get -lp formatting.
+A shortcut flag -lfp is also added for limiting -lp to simple function calls.
+
+Updated 25 Mar 2021.
+
+
 =item B<Fix error message for multiple conflicting specifications in -wnxl>
 
 There was an error in the coding for an error message which checks for
 conflicting requests in the -wnxl parameter.
 
-Fixed 21 Mar 2021.
+Fixed 21 Mar 2021, 2ef97a2.
 
 =item B<Fix issue git #57, Warn_count was not initialized>
 
diff --git a/t/snippets/expect/lpxl.def b/t/snippets/expect/lpxl.def
new file mode 100644 (file)
index 0000000..0bfd556
--- /dev/null
@@ -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/expect/lpxl.lpxl1 b/t/snippets/expect/lpxl.lpxl1
new file mode 100644 (file)
index 0000000..53cc2d8
--- /dev/null
@@ -0,0 +1,60 @@
+# 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/expect/lpxl.lpxl2 b/t/snippets/expect/lpxl.lpxl2
new file mode 100644 (file)
index 0000000..0c7a829
--- /dev/null
@@ -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/expect/lpxl.lpxl3 b/t/snippets/expect/lpxl.lpxl3
new file mode 100644 (file)
index 0000000..77e1e21
--- /dev/null
@@ -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/expect/lpxl.lpxl4 b/t/snippets/expect/lpxl.lpxl4
new file mode 100644 (file)
index 0000000..328f0e2
--- /dev/null
@@ -0,0 +1,60 @@
+# 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/expect/lpxl.lpxl5 b/t/snippets/expect/lpxl.lpxl5
new file mode 100644 (file)
index 0000000..0c7a829
--- /dev/null
@@ -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/lpxl.in b/t/snippets/lpxl.in
new file mode 100644 (file)
index 0000000..eb8902e
--- /dev/null
@@ -0,0 +1,60 @@
+# 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/lpxl1.par b/t/snippets/lpxl1.par
new file mode 100644 (file)
index 0000000..8daf886
--- /dev/null
@@ -0,0 +1 @@
+-lp
diff --git a/t/snippets/lpxl2.par b/t/snippets/lpxl2.par
new file mode 100644 (file)
index 0000000..eced01c
--- /dev/null
@@ -0,0 +1 @@
+-lfp
diff --git a/t/snippets/lpxl3.par b/t/snippets/lpxl3.par
new file mode 100644 (file)
index 0000000..68bcee6
--- /dev/null
@@ -0,0 +1 @@
+-lp -lpxl='{ [ ('
diff --git a/t/snippets/lpxl4.par b/t/snippets/lpxl4.par
new file mode 100644 (file)
index 0000000..f77ec0a
--- /dev/null
@@ -0,0 +1 @@
+-lp -lpxl='{ [ W(1'
diff --git a/t/snippets/lpxl5.par b/t/snippets/lpxl5.par
new file mode 100644 (file)
index 0000000..946a747
--- /dev/null
@@ -0,0 +1 @@
+-lp -lpxl='{ [ F(2'
index a2011422a32a354de0a0153c7566138daab1440c..fe98992e4b7666156fbe79dee968576d48069228 100644 (file)
 ../snippets23.t        qw.def
 ../snippets24.t        git54.def
 ../snippets24.t        git54.git54
+../snippets24.t        fpva.def
+../snippets24.t        fpva.fpva1
+../snippets24.t        fpva.fpva2
 ../snippets3.t ce_wn1.ce_wn
 ../snippets3.t ce_wn1.def
 ../snippets3.t colin.colin
 ../snippets9.t rt98902.def
 ../snippets9.t rt98902.rt98902
 ../snippets9.t rt99961.def
-../snippets24.t        fpva.def
-../snippets24.t        fpva.fpva1
-../snippets24.t        fpva.fpva2
+../snippets24.t        lpxl.def
+../snippets24.t        lpxl.lpxl1
+../snippets24.t        lpxl.lpxl2
+../snippets24.t        lpxl.lpxl3
+../snippets24.t        lpxl.lpxl4
+../snippets24.t        lpxl.lpxl5
index 2da12fe8a686de6c67b8449f9460a1e6756dcf34..36c2c886455ebb2f22c13672fc6c01475cd3a443 100644 (file)
@@ -6,6 +6,12 @@
 #3 fpva.def
 #4 fpva.fpva1
 #5 fpva.fpva2
+#6 lpxl.def
+#7 lpxl.lpxl1
+#8 lpxl.lpxl2
+#9 lpxl.lpxl3
+#10 lpxl.lpxl4
+#11 lpxl.lpxl5
 
 # To locate test #13 you can search for its name or the string '#13'
 
@@ -27,6 +33,17 @@ BEGIN {
         'fpva1' => "-sfp",
         'fpva2' => "-sfp -nfpva",
         'git54' => "-bbp=3 -bbpi=2 -ci=4 -lp",
+        'lpxl1' => "-lp",
+        'lpxl2' => "-lfp",
+        'lpxl3' => <<'----------',
+-lp -lpxl='{ [ ('
+----------
+        'lpxl4' => <<'----------',
+-lp -lpxl='{ [ W(1'
+----------
+        'lpxl5' => <<'----------',
+-lp -lpxl='{ [ F(2'
+----------
     };
 
     ############################
@@ -97,6 +114,69 @@ my $list =
       }
     ) ;
 ----------
+
+        '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"},
+             };
+----------
     };
 
     ####################################
@@ -253,6 +333,412 @@ use File::Spec ();
 use File::Path ();
 #5...........
         },
+
+        'lpxl.def' => {
+            source => "lpxl",
+            params => "def",
+            expect => <<'#6...........',
+# 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" },
+};
+#6...........
+        },
+
+        'lpxl.lpxl1' => {
+            source => "lpxl",
+            params => "lpxl1",
+            expect => <<'#7...........',
+# 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" },
+};
+#7...........
+        },
+
+        'lpxl.lpxl2' => {
+            source => "lpxl",
+            params => "lpxl2",
+            expect => <<'#8...........',
+# 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" },
+};
+#8...........
+        },
+
+        'lpxl.lpxl3' => {
+            source => "lpxl",
+            params => "lpxl3",
+            expect => <<'#9...........',
+# 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" },
+};
+#9...........
+        },
+
+        'lpxl.lpxl4' => {
+            source => "lpxl",
+            params => "lpxl4",
+            expect => <<'#10...........',
+# 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" },
+};
+#10...........
+        },
+
+        'lpxl.lpxl5' => {
+            source => "lpxl",
+            params => "lpxl5",
+            expect => <<'#11...........',
+# 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" },
+};
+#11...........
+        },
     };
 
     my $ntests = 0 + keys %{$rtests};