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,
(1) Increase B<--maximum-line-length=n> above the default B<n=80> 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<not> 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<NOT> 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<s> 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<optional> 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.
'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>
-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<Perl Best Practices>
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.
$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', '!' );
%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.
}
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( <<EOM );
+You entered values for both -lpxl=s and -lpil=s; the -lpil list will be ignored
+EOM
+ }
+ if ($lpxl) {
+ $line_up_parentheses_control_is_lxpl = 1;
+ initialize_line_up_parentheses_control_hash(
+ $rOpts->{'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;
}
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+$//;
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;
}
# 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;
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_];
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 {
--- /dev/null
+# 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" },
+};
--- /dev/null
+# equivalent to -lpxl='{ [ F(2'
+-lp -lpil='f(2'
../snippets9.t rt98902.def
../snippets9.t rt98902.rt98902
../snippets9.t rt99961.def
+../snippets26.t lpxl.lpxl6
# Contents:
#1 bal.bal2
#2 bal.def
+#3 lpxl.lpxl6
# To locate test #13 you can search for its name or the string '#13'
# BEGIN SECTION 1: Parameter combinations #
###########################################
$rparams = {
- 'bal2' => "-bal=2",
- 'def' => "",
+ 'bal2' => "-bal=2",
+ 'def' => "",
+ 'lpxl6' => <<'----------',
+# equivalent to -lpxl='{ [ F(2'
+-lp -lpil='f(2'
+----------
};
############################
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"},
+ };
----------
};
};
#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};