From: Steve Hancock Date: Mon, 25 May 2020 00:59:08 +0000 (-0700) Subject: added parameter -kpit=n and kpitl=s, see git#26 discussion X-Git-Tag: 20200619~21 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=b85db2ca604e851288a037520a92144244f6da4b;p=perltidy.git added parameter -kpit=n and kpitl=s, see git#26 discussion --- diff --git a/CHANGES.md b/CHANGES.md index 21d6a974..ea121a66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,9 @@ ## 2020 01 10.01 + - Added a parameter -kpit=n to control spaces inside of parens following + certain keywords, requested in git#26. This flag is off by default. + - Added fix for git#25, improve vertical alignment for long lists with varying numbers of items per line. diff --git a/bin/perltidy b/bin/perltidy index 89d9dcce..2a9577c9 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -1168,6 +1168,48 @@ applying the different options would be: sub usage(); # n=1 [default; follows input] sub usage (); # n=2 [space] +=item B<-kpit=n> or B<--keyword-paren-inner-tightness=n> + +The space inside of an opening paren, which itself follows a certain keyword, +can be controlled by this parameter. The space on the inside of the +corresponding closing paren will be treated in the same (balanced) manner. +This parameter has precedence over any other paren spacing rules. The values +of B are as follows: + + -kpit=0 means always put a space (not tight) + -kpit=1 means ignore this parameter [default] + -kpit=2 means never put a space (tight) + +To illustrate, the following snippet is shown formatted in three ways: + + if ( seek( DATA, 0, 0 ) ) { ... } # perltidy (default) + if (seek(DATA, 0, 0)) { ... } # perltidy -pt=2 + if ( seek(DATA, 0, 0) ) { ... } # perltidy -pt=2 -kpit=0 + +In the second case the -pt=2 parameter makes all of the parens tight. In the +third case the -kpit=0 flag causes the space within the 'if' parens to have a +space, since 'if' is one of the keywords to which the -kpit flag applies by +default. The remaining parens are still tight because of the -pt=2 parameter. + +The set of keywords to which this parameter applies are by default are: + + if elsif unless while until for foreach + +These can be changed with the parameter B<-kpitl=s> described in the next section. + + +=item B<-kpitl=string> or B<--keyword-paren-inner-tightness=string> + +This command can be used to change the keywords to which the the B<-kpit=n> +command applies. The parameter B is a required list either keywords or +functions, which should be placed in quotes if there are more than one. By +itself, this parameter does not cause any change in spacing, so the B<-kpit=n> +command is still required. + +For example, the commands C<-kpitl="if else while" -kpit=2> will cause the just +the spaces inside parens following 'if', 'else', and 'while' keywords to +follow the tightness value indicated by the B<-kpit=2> flag. + =item Trimming whitespace around C quotes B<-tqw> or B<--trim-qw> provide the default behavior of trimming diff --git a/docs/ChangeLog.html b/docs/ChangeLog.html index 54ae6383..094d0071 100644 --- a/docs/ChangeLog.html +++ b/docs/ChangeLog.html @@ -2,7 +2,15 @@

2020 01 10.01

-
- add option --break-at-old-semicolon-breakpoints', -bos, requested 
+
- Added fix for git#25, improve vertical alignment for long lists with
+  varying numbers of items per line.
+
+- calls to the module Perl::Tidy can now capture any output produced
+  by a debug flag or one of the 'tee' flags through the new 'debugfile' and
+  'teefile' call parameters.  These output streams are rarely used but
+  they are now treated the same as any 'logfile' stream.
+
+- add option --break-at-old-semicolon-breakpoints', -bos, requested 
   in RT#131644.  This flag will keep lines beginning with a semicolon.
 
 - Added --use-unicode-gcstring to control use of Unicode::GCString for
diff --git a/docs/Tidy.html b/docs/Tidy.html
index 412c2bae..00cdf7d4 100644
--- a/docs/Tidy.html
+++ b/docs/Tidy.html
@@ -43,6 +43,8 @@
         perltidyrc        => $perltidyrc,
         logfile           => $logfile,
         errorfile         => $errorfile,
+        teefile           => $teefile,
+        debugfile         => $debugfile,
         formatter         => $formatter,           # callback object (see below)
         dump_options      => $dump_options,
         dump_options_type => $dump_options_type,
@@ -127,6 +129,18 @@
 
 

The logfile parameter allows the calling program to capture the log stream. This stream is only created if requested with a -g parameter. It contains detailed diagnostic information about a script which may be useful for debugging.

+ +
teefile
+
+ +

The teefile parameter allows the calling program to capture the tee stream. This stream is only created if requested with one of the 'tee' parameters, a --tee-pod , --tee-block-comments, --tee-side-commnts, or --tee-all-comments.

+ +
+
debugfile
+
+ +

The debugfile parameter allows the calling program to capture the stream produced by the --DEBUG parameter. This parameter is mainly used for debugging perltidy itself.

+
argv
diff --git a/docs/perltidy.html b/docs/perltidy.html index 44f05206..bfb16504 100644 --- a/docs/perltidy.html +++ b/docs/perltidy.html @@ -927,6 +927,38 @@ sub usage(); # n=1 [default; follows input] sub usage (); # n=2 [space]
+ +
-kpit=n or --keyword-paren-inner-tightness=n
+
+ +

The space inside of an opening paren, which itself follows a certain keyword, can be controlled by this parameter. The space on the inside of the corresponding closing paren will be treated in the same (balanced) manner. This parameter has precedence over any other paren spacing rules. The values of n are as follows:

+ +
   -kpit=0 means always put a space (not tight)
+   -kpit=1 means ignore this parameter [default]
+   -kpit=2 means never put a space (tight)
+ +

To illustrate, the following snippet is shown formatted in three ways:

+ +
    if ( seek( DATA, 0, 0 ) ) { ... }    # perltidy (default)
+    if (seek(DATA, 0, 0)) { ... }        # perltidy -pt=2
+    if ( seek(DATA, 0, 0) ) { ... }      # perltidy -pt=2 -kpit=0
+ +

In the second case the -pt=2 parameter makes all of the parens tight. In the third case the -kpit=0 flag causes the space within the 'if' parens to have a space, since 'if' is one of the keywords to which the -kpit flag applies by default. The remaining parens are still tight because of the -pt=2 parameter.

+ +

The set of keywords to which this parameter applies are by default are:

+ +
   if elsif unless while until for foreach
+ +

These can be changed with the parameter -kpitl=s described in the next section.

+ +
+
-kpitl=string or --keyword-paren-inner-tightness=string
+
+ +

This command can be used to change the keywords to which the the -kpit=n command applies. The parameter string is a required list either keywords or functions, which should be placed in quotes if there are more than one. By itself, this parameter does not cause any change in spacing, so the -kpit=n command is still required.

+ +

For example, the commands -kpitl="if else while" -kpit=2 will cause the just the spaces inside parens following 'if', 'else', and 'while' keywords to follow the tightness value indicated by the -kpit=2 flag.

+
Trimming whitespace around qw quotes
diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index 205ac432..8f55ea03 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -1986,6 +1986,8 @@ sub generate_options { $add_option->( 'brace-tightness', 'bt', '=i' ); $add_option->( 'delete-old-whitespace', 'dws', '!' ); $add_option->( 'delete-semicolons', 'dsm', '!' ); + $add_option->( 'keyword-paren-inner-tightness', 'kpit', '=i' ); + $add_option->( 'keyword-paren-inner-tightness-list', 'kpitl', '=s' ); $add_option->( 'nospace-after-keyword', 'nsak', '=s' ); $add_option->( 'nowant-left-space', 'nwls', '=s' ); $add_option->( 'nowant-right-space', 'nwrs', '=s' ); @@ -2195,11 +2197,12 @@ sub generate_options { %option_range = ( 'format' => [ 'tidy', 'html', 'user' ], 'output-line-ending' => [ 'dos', 'win', 'mac', 'unix' ], - 'space-backslash-quote' => [ 0, 2 ], - 'block-brace-tightness' => [ 0, 2 ], - 'brace-tightness' => [ 0, 2 ], - 'paren-tightness' => [ 0, 2 ], - 'square-bracket-tightness' => [ 0, 2 ], + 'space-backslash-quote' => [ 0, 2 ], + 'block-brace-tightness' => [ 0, 2 ], + 'keyword-paren-inner-tightness' => [ 0, 2 ], + 'brace-tightness' => [ 0, 2 ], + 'paren-tightness' => [ 0, 2 ], + 'square-bracket-tightness' => [ 0, 2 ], 'block-brace-vertical-tightness' => [ 0, 2 ], 'brace-vertical-tightness' => [ 0, 2 ], @@ -2279,6 +2282,7 @@ sub generate_options { indent-columns=4 iterations=1 keep-old-blank-lines=1 + keyword-paren-inner-tightness=1 long-block-line-count=8 look-for-autoloader look-for-selfloader diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index b568457b..68d6b656 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -218,6 +218,7 @@ use vars qw{ %closing_vertical_tightness %closing_token_indentation $some_closing_token_indentation + %keyword_paren_inner_tightness %opening_token_right %stack_opening_token @@ -1824,17 +1825,23 @@ sub set_whitespace_flags { my $rwhitespace_flags = []; - my ( $last_token, $last_type, $last_block_type, $last_input_line_no, - $token, $type, $block_type, $input_line_no ); + my ( $token, $type, $block_type, $seqno, $input_line_no ); + my ( + $last_token, $last_type, $last_block_type, + $last_seqno, $last_input_line_no + ); + my $j_tight_closing_paren = -1; $token = ' '; $type = 'b'; $block_type = ''; + $seqno = ''; $input_line_no = 0; $last_token = ' '; $last_type = 'b'; $last_block_type = ''; + $last_seqno = ''; $last_input_line_no = 0; my $jmax = @{$rLL} - 1; @@ -1890,6 +1897,46 @@ sub set_whitespace_flags { return (WS_YES); }; + # Local hashes to set spaces around container tokens according to their + # sequence numbers. These are set as keywords are examined. + # They are controlled by the -kpit and -kpitl flags. + my %opening_container_inside_ws; + my %closing_container_inside_ws; + my $set_container_ws_by_keyword = sub { + my ( $word, $sequence_number ) = @_; + + # We just saw a keyword (or other function name) followed by an opening + # paren. Now check to see if the following paren should have special + # treatment for its inside space. If so we set a hash value using the + # sequence number as key. + if ($word) { + my $tightness = $keyword_paren_inner_tightness{$word}; + if ( defined($tightness) && $tightness != 1 ) { + my $ws_flag = $tightness == 0 ? WS_YES : WS_NO; + $opening_container_inside_ws{$sequence_number} = $ws_flag; + $closing_container_inside_ws{$sequence_number} = $ws_flag; + } + } + }; + + my $ws_opening_container_override = sub { + my ( $ws, $sequence_number ) = @_; + if ($sequence_number) { + my $ws_override = $opening_container_inside_ws{$sequence_number}; + if ($ws_override) { $ws = $ws_override } + } + return $ws; + }; + + my $ws_closing_container_override = sub { + my ( $ws, $sequence_number ) = @_; + if ($sequence_number) { + my $ws_override = $closing_container_inside_ws{$sequence_number}; + if ($ws_override) { $ws = $ws_override } + } + return $ws; + }; + # main loop over all tokens to define the whitespace flags for ( my $j = 0 ; $j <= $jmax ; $j++ ) { @@ -1907,10 +1954,12 @@ sub set_whitespace_flags { $last_token = $token; $last_type = $type; $last_block_type = $block_type; + $last_seqno = $seqno; $last_input_line_no = $input_line_no; $token = $rtokh->[_TOKEN_]; $type = $rtokh->[_TYPE_]; $block_type = $rtokh->[_BLOCK_TYPE_]; + $seqno = $rtokh->[_TYPE_SEQUENCE_]; $input_line_no = $rtokh->[_LINE_INDEX_]; #--------------------------------------------------------------- @@ -1976,6 +2025,10 @@ sub set_whitespace_flags { $ws = $ws_in_container->($j); } } + + # check for special cases which override the above rules + $ws = $ws_opening_container_override->( $ws, $last_seqno ); + } # end setting space flag inside opening tokens my $ws_1; $ws_1 = $ws @@ -2007,6 +2060,10 @@ sub set_whitespace_flags { $ws = ( $tightness > 1 ) ? WS_NO : WS_YES; } } + + # check for special cases which override the above rules + $ws = $ws_closing_container_override->( $ws, $seqno ); + } # end setting space flag inside closing tokens my $ws_2; @@ -2051,6 +2108,9 @@ sub set_whitespace_flags { $ws = WS_NO unless ( $rOpts_space_keyword_paren || $space_after_keyword{$last_token} ); + + # Set inside space flag if requested + $set_container_ws_by_keyword->( $last_token, $seqno ); } # Space between function and '(' @@ -2062,6 +2122,7 @@ sub set_whitespace_flags { || ( $last_type =~ /^[wi]$/ && $last_token =~ /^(\&|->)/ ) ) { $ws = WS_NO unless ($rOpts_space_function_paren); + $set_container_ws_by_keyword->( $last_token, $seqno ); } # space between something like $i and ( in <> @@ -5783,6 +5844,19 @@ EOM } } + # setup hash for -kpit option + %keyword_paren_inner_tightness = (); + my @kpit = split_words( $rOpts->{'keyword-paren-inner-tightness-list'} ); + unless (@kpit) { + @kpit = qw(if elsif unless while until for foreach); # defaults + } + + # we will allow keywords and user-defined identifiers + foreach (@kpit) { + $keyword_paren_inner_tightness{$_} = + $rOpts->{'keyword-paren-inner-tightness'}; + } + # implement user whitespace preferences if ( my @q = split_words( $rOpts->{'want-left-space'} ) ) { @want_left_space{@q} = (1) x scalar(@q); @@ -7103,6 +7177,7 @@ sub copy_token_as_type { $K_last_nonblank_code = undef; $K_last_last_nonblank_code = undef; $looking_for_else = 0; + return; } # batch variables @@ -7115,6 +7190,7 @@ sub copy_token_as_type { $rbrace_follower = undef; $comma_count_in_batch = 0; destroy_one_line_block(); + return; } sub create_one_line_block { diff --git a/t/snippets/expect/kpit.def b/t/snippets/expect/kpit.def new file mode 100644 index 00000000..8354af2e --- /dev/null +++ b/t/snippets/expect/kpit.def @@ -0,0 +1 @@ +if ( seek( DATA, 0, 0 ) ) { ... } diff --git a/t/snippets/expect/kpit.kpit b/t/snippets/expect/kpit.kpit new file mode 100644 index 00000000..5c640af3 --- /dev/null +++ b/t/snippets/expect/kpit.kpit @@ -0,0 +1 @@ +if ( seek(DATA, 0, 0) ) { ... } diff --git a/t/snippets/expect/kpitl.def b/t/snippets/expect/kpitl.def new file mode 100644 index 00000000..7da8ee3a --- /dev/null +++ b/t/snippets/expect/kpitl.def @@ -0,0 +1,7 @@ +return ( $r**$n ) * + ( pi**( $n / 2 ) ) / + ( + sqrt(pi) * + factorial( 2 * ( int( $n / 2 ) ) + 2 ) / + factorial( int( $n / 2 ) + 1 ) / + ( 4**( int( $n / 2 ) + 1 ) ) ); diff --git a/t/snippets/expect/kpitl.kpitl b/t/snippets/expect/kpitl.kpitl new file mode 100644 index 00000000..a1f28c22 --- /dev/null +++ b/t/snippets/expect/kpitl.kpitl @@ -0,0 +1,7 @@ +return ( $r**$n ) * + (pi**($n / 2)) / + ( + sqrt(pi) * + factorial( 2 * (int($n / 2)) + 2 ) / + factorial( int($n / 2) + 1 ) / + (4**(int($n / 2) + 1))); diff --git a/t/snippets/kpit.in b/t/snippets/kpit.in new file mode 100644 index 00000000..001886f4 --- /dev/null +++ b/t/snippets/kpit.in @@ -0,0 +1 @@ +if ( seek( DATA, 0, 0 ) ) { ... } diff --git a/t/snippets/kpit.par b/t/snippets/kpit.par new file mode 100644 index 00000000..dd5241cb --- /dev/null +++ b/t/snippets/kpit.par @@ -0,0 +1 @@ +-pt=2 -kpit=0 diff --git a/t/snippets/kpitl.in b/t/snippets/kpitl.in new file mode 100644 index 00000000..186a3d9f --- /dev/null +++ b/t/snippets/kpitl.in @@ -0,0 +1,3 @@ +return ( $r**$n ) * ( pi**( $n / 2 ) ) / ( sqrt(pi) * factorial( 2 * ( int( $n +/ 2 ) ) + 2 ) / factorial( int( $n / 2 ) + 1 ) / ( 4**( int( $n / 2 ) + 1 ) ) +); diff --git a/t/snippets/kpitl.par b/t/snippets/kpitl.par new file mode 100644 index 00000000..1290aab3 --- /dev/null +++ b/t/snippets/kpitl.par @@ -0,0 +1 @@ +-kpit=0 -kpitl='return factorial' -pt=2 diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt index f4ce326c..05dddc9e 100644 --- a/t/snippets/packing_list.txt +++ b/t/snippets/packing_list.txt @@ -244,6 +244,7 @@ ../snippets20.t gnu6.gnu ../snippets20.t git25.def ../snippets20.t git25.git25 +../snippets20.t outdent.outdent2 ../snippets3.t ce_wn1.ce_wn ../snippets3.t ce_wn1.def ../snippets3.t colin.colin @@ -384,4 +385,7 @@ ../snippets9.t rt98902.def ../snippets9.t rt98902.rt98902 ../snippets9.t rt99961.def -../snippets20.t outdent.outdent2 +../snippets20.t kpit.def +../snippets20.t kpit.kpit +../snippets20.t kpitl.def +../snippets20.t kpitl.kpitl diff --git a/t/snippets20.t b/t/snippets20.t index 6e201156..fbead065 100644 --- a/t/snippets20.t +++ b/t/snippets20.t @@ -14,6 +14,10 @@ #11 git25.def #12 git25.git25 #13 outdent.outdent2 +#14 kpit.def +#15 kpit.kpit +#16 kpitl.def +#17 kpitl.kpitl # To locate test #13 you can search for its name or the string '#13' @@ -31,10 +35,14 @@ BEGIN { # BEGIN SECTION 1: Parameter combinations # ########################################### $rparams = { - 'ce' => "-cuddled-blocks", - 'def' => "", - 'git25' => "-l=0", - 'gnu' => "-gnu", + 'ce' => "-cuddled-blocks", + 'def' => "", + 'git25' => "-l=0", + 'gnu' => "-gnu", + 'kpit' => "-pt=2 -kpit=0", + 'kpitl' => <<'----------', +-kpit=0 -kpitl='return factorial' -pt=2 +---------- 'outdent2' => <<'----------', # test -okw and -okwl -okw -okwl='next' @@ -106,6 +114,16 @@ my $mapping = [ 'foo10' => undef, }; +---------- + + 'kpit' => <<'----------', +if ( seek( DATA, 0, 0 ) ) { ... } +---------- + + 'kpitl' => <<'----------', +return ( $r**$n ) * ( pi**( $n / 2 ) ) / ( sqrt(pi) * factorial( 2 * ( int( $n +/ 2 ) ) + 2 ) / factorial( int( $n / 2 ) + 1 ) / ( 4**( int( $n / 2 ) + 1 ) ) +); ---------- 'outdent' => <<'----------', @@ -461,6 +479,50 @@ my $mapping = [ #13........... }, + + 'kpit.def' => { + source => "kpit", + params => "def", + expect => <<'#14...........', +if ( seek( DATA, 0, 0 ) ) { ... } +#14........... + }, + + 'kpit.kpit' => { + source => "kpit", + params => "kpit", + expect => <<'#15...........', +if ( seek(DATA, 0, 0) ) { ... } +#15........... + }, + + 'kpitl.def' => { + source => "kpitl", + params => "def", + expect => <<'#16...........', +return ( $r**$n ) * + ( pi**( $n / 2 ) ) / + ( + sqrt(pi) * + factorial( 2 * ( int( $n / 2 ) ) + 2 ) / + factorial( int( $n / 2 ) + 1 ) / + ( 4**( int( $n / 2 ) + 1 ) ) ); +#16........... + }, + + 'kpitl.kpitl' => { + source => "kpitl", + params => "kpitl", + expect => <<'#17...........', +return ( $r**$n ) * + (pi**($n / 2)) / + ( + sqrt(pi) * + factorial( 2 * (int($n / 2)) + 2 ) / + factorial( int($n / 2) + 1 ) / + (4**(int($n / 2) + 1))); +#17........... + }, }; my $ntests = 0 + keys %{$rtests};