From: Steve Hancock Date: Fri, 6 Oct 2023 14:32:22 +0000 (-0700) Subject: add -space-signature-paren=n, -ssp=n (see git #125) X-Git-Tag: 20230912.03~1 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=ba93333993417578ec5ec4ee7ccd19c649f628e3;p=perltidy.git add -space-signature-paren=n, -ssp=n (see git #125) --- diff --git a/CHANGES.md b/CHANGES.md index dfbfe9fe..4cfd51f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,24 @@ ## 2023 09 12.02 + - Added flag --space-signature-paren=n, or -ssp=n (issue git #125). + This flag works the same as the existing flag --space-prototype-paren=n + except that it applies to the space before the opening paren of a sub + signature instead of a sub prototype. Previously, there was no control + over this (a space always occurred). For example, given the following + line: + + sub circle( $xc, $yc, $rad ); + + The following results can now be obtained, according to the value of n: + + sub circle( $xc, $yc, $rad ); # n=0 [no space] + sub circle( $xc, $yc, $rad ); # n=1 [default; same as input] + sub circle ( $xc, $yc, $rad ); # n=2 [space] + + The spacing in previous versions of perltidy corresponded to n=2 (always + a space). The new default value, n=1, will produce a space if and only if there was a space in the input text. + - The dump-block-summary option can report an if-elsif-elsif-.. chain as a single line item with the notation -dbt='elsif3', for example, where the '3' is an integer which specifies the minimum number of elsif diff --git a/bin/perltidy b/bin/perltidy index 63836aa3..86c860b0 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -1599,6 +1599,28 @@ applying the different options would be: sub usage(); # n=1 [default; follows input] sub usage (); # n=2 [space] +=item B<-ssp=n> or B<--space-signature-paren=n> + +This flag is analogous to the previous except that it applies to the space before the opening paren of a sub B rather than a sub B. + +For example, consider the following line: + + sub circle( $xc, $yc, $rad ) + +This space before the opening paren can be controlled with integer B which +may have the value 0, 1, or 2 with these meanings: + + -ssp=0 means no space before the paren + -ssp=1 means follow the example of the source code [DEFAULT] + -ssp=2 means always put a space before the paren + +The default is B<-ssp=1>, meaning that will be a space in the output if, and only if, there is one in the input. Given the above line of code, the result of +applying the different options would be: + + sub circle( $xc, $yc, $rad ) # n=0 [no space] + sub circle( $xc, $yc, $rad ) # n=1 [default; same as input] + sub circle ( $xc, $yc, $rad ) # 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, diff --git a/dev-bin/perltidy_random_setup.pl b/dev-bin/perltidy_random_setup.pl index 92443d64..a3d0bb32 100755 --- a/dev-bin/perltidy_random_setup.pl +++ b/dev-bin/perltidy_random_setup.pl @@ -1165,6 +1165,7 @@ EOM 'keyword-group-blanks-after' => [ 0, 2 ], 'space-prototype-paren' => [ 0, 2 ], + 'space-signature-paren' => [ 0, 2 ], 'break-after-labels' => [ 0, 2 ], 'want-trailing-commas' => [ '0', '*', 'm', 'b', 'h', 'i', ' ' ], diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index c1fc82ac..5913e921 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -3463,6 +3463,7 @@ sub generate_options { $add_option->( 'want-right-space', 'wrs', '=s' ); $add_option->( 'want-trailing-commas', 'wtc', '=s' ); $add_option->( 'space-prototype-paren', 'spp', '=i' ); + $add_option->( 'space-signature-paren', 'ssp', '=i' ); $add_option->( 'valign-code', 'vc', '!' ); $add_option->( 'valign-block-comments', 'vbc', '!' ); $add_option->( 'valign-side-comments', 'vsc', '!' ); @@ -3735,6 +3736,7 @@ sub generate_options { 'keyword-group-blanks-after' => [ 0, 2 ], 'space-prototype-paren' => [ 0, 2 ], + 'space-signature-paren' => [ 0, 2 ], 'break-after-labels' => [ 0, 2 ], ); @@ -3849,6 +3851,7 @@ sub generate_options { space-for-semicolon space-backslash-quote=1 space-prototype-paren=1 + space-signature-paren=1 square-bracket-tightness=1 square-bracket-vertical-tightness-closing=0 square-bracket-vertical-tightness=0 diff --git a/lib/Perl/Tidy/Formatter.pm b/lib/Perl/Tidy/Formatter.pm index 94ed836a..b2c4d700 100644 --- a/lib/Perl/Tidy/Formatter.pm +++ b/lib/Perl/Tidy/Formatter.pm @@ -251,6 +251,7 @@ my ( $rOpts_recombine, $rOpts_short_concatenation_item_length, $rOpts_space_prototype_paren, + $rOpts_space_signature_paren, $rOpts_stack_closing_block_brace, $rOpts_static_block_comments, $rOpts_add_missing_else, @@ -2512,6 +2513,7 @@ sub initialize_global_option_vars { $rOpts_short_concatenation_item_length = $rOpts->{'short-concatenation-item-length'}; $rOpts_space_prototype_paren = $rOpts->{'space-prototype-paren'}; + $rOpts_space_signature_paren = $rOpts->{'space-signature-paren'}; $rOpts_stack_closing_block_brace = $rOpts->{'stack-closing-block-brace'}; $rOpts_static_block_comments = $rOpts->{'static-block-comments'}; $rOpts_add_missing_else = $rOpts->{'add-missing-else'}; @@ -3035,6 +3037,27 @@ sub set_whitespace_flags { my %is_for_foreach = ( 'for' => 1, 'foreach' => 1 ); + # function to return $ws for a signature paren following a sub + my $ws_signature_paren = sub { + my ($jj) = @_; + my $ws; + if ( $rOpts_space_signature_paren == 1 ) { + + # is the previous token a blank? + my $have_blank = $rLL->[ $jj - 1 ]->[_TYPE_] eq 'b'; + + # or a newline? + $have_blank ||= + $rLL->[$jj]->[_LINE_INDEX_] != $rLL->[ $jj - 1 ]->[_LINE_INDEX_]; + + $ws = $have_blank ? WS_YES : WS_NO; + } + else { + $ws = $rOpts_space_signature_paren == 0 ? WS_NO : WS_YES; + } + return $ws; + }; + my $last_token = SPACE; my $last_type = 'b'; @@ -3330,12 +3353,18 @@ sub set_whitespace_flags { # Space between keyword and '(' elsif ( $last_type eq 'k' ) { - $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 ); + if ( $last_token eq 'sub' ) { + $ws = $ws_signature_paren->($j); + } + else { + $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 '(' @@ -3401,8 +3430,14 @@ sub set_whitespace_flags { { $ws = WS_NO; } + + # a paren after a sub definition starts signature + elsif ( $last_type eq 'S' ) { + $ws = $ws_signature_paren->($j); + } + else { - # ok - opening paren not covered by a special rule + # no special rule for this opening paren type } } @@ -3418,7 +3453,10 @@ sub set_whitespace_flags { # keep space between 'sub' and '{' for anonymous sub definition, # be sure type = 'k' (added for c140) if ( $type eq '{' ) { - if ( $last_token eq 'sub' && $last_type eq 'k' ) { + if ( $last_token eq 'sub' + && $last_type eq 'k' + && $token ne '(' ) + { $ws = WS_YES; } diff --git a/t/filter_example.t b/t/filter_example.t index bdecf449..1e7e8607 100755 --- a/t/filter_example.t +++ b/t/filter_example.t @@ -48,7 +48,8 @@ ENDE my $output; my $stderr_string; my $errorfile_string; -my $params = ""; +# -ssp=2 is needed to keep formatting unchanged with new -ssp parameter +my $params = "-ssp=2"; my $err = Perl::Tidy::perltidy( #argv => '-npro', # fix for RT#127679, avoid reading unwanted .perltidyrc diff --git a/t/snippets/expect/git125.def b/t/snippets/expect/git125.def new file mode 100644 index 00000000..9ef474bf --- /dev/null +++ b/t/snippets/expect/git125.def @@ -0,0 +1,2 @@ +sub Add ( $x, $y ); +sub Sub( $x, $y ); diff --git a/t/snippets/expect/git125.git125 b/t/snippets/expect/git125.git125 new file mode 100644 index 00000000..1278116e --- /dev/null +++ b/t/snippets/expect/git125.git125 @@ -0,0 +1,2 @@ +sub Add( $x, $y ); +sub Sub( $x, $y ); diff --git a/t/snippets/expect/signature.def b/t/snippets/expect/signature.def index b33d07e2..e2d1e901 100644 --- a/t/snippets/expect/signature.def +++ b/t/snippets/expect/signature.def @@ -1,12 +1,12 @@ # git22: Preserve function signature on a single line # This behavior is controlled by 'sub weld_signature_parens' -sub foo ( $x, $y = "abcd" ) { +sub foo( $x, $y = "abcd" ) { $x . $y; } # do not break after closing do brace -sub foo ( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { +sub foo( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { $x . $y . $z; } diff --git a/t/snippets/git125.in b/t/snippets/git125.in new file mode 100644 index 00000000..9ef474bf --- /dev/null +++ b/t/snippets/git125.in @@ -0,0 +1,2 @@ +sub Add ( $x, $y ); +sub Sub( $x, $y ); diff --git a/t/snippets/git125.par b/t/snippets/git125.par new file mode 100644 index 00000000..e8fd3066 --- /dev/null +++ b/t/snippets/git125.par @@ -0,0 +1 @@ +-ssp=0 diff --git a/t/snippets/packing_list.txt b/t/snippets/packing_list.txt index 12afe1e2..65ef0cbc 100644 --- a/t/snippets/packing_list.txt +++ b/t/snippets/packing_list.txt @@ -542,3 +542,5 @@ ../snippets9.t rt98902.def ../snippets9.t rt98902.rt98902 ../snippets9.t rt99961.def +../snippets28.t git125.def +../snippets29.t git125.git125 diff --git a/t/snippets17.t b/t/snippets17.t index 16e8fb64..4abdf24c 100644 --- a/t/snippets17.t +++ b/t/snippets17.t @@ -1054,12 +1054,12 @@ $i++; # git22: Preserve function signature on a single line # This behavior is controlled by 'sub weld_signature_parens' -sub foo ( $x, $y = "abcd" ) { +sub foo( $x, $y = "abcd" ) { $x . $y; } # do not break after closing do brace -sub foo ( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { +sub foo( $x, $y = do { {} }, $z = 42, $w = do { "abcd" } ) { $x . $y . $z; } diff --git a/t/snippets28.t b/t/snippets28.t index 38e8b95d..f9873fac 100644 --- a/t/snippets28.t +++ b/t/snippets28.t @@ -19,6 +19,7 @@ #16 git124.def #17 c269.c269 #18 c269.def +#19 git125.def # To locate test #13 you can search for its name or the string '#13' @@ -91,6 +92,11 @@ sub git124 { } ]; } +---------- + + 'git125' => <<'----------', +sub Add ( $x, $y ); +sub Sub( $x, $y ); ---------- 'lrt' => <<'----------', @@ -448,6 +454,15 @@ elsif ($zzzzz) { } #18........... }, + + 'git125.def' => { + source => "git125", + params => "def", + expect => <<'#19...........', +sub Add ( $x, $y ); +sub Sub( $x, $y ); +#19........... + }, }; my $ntests = 0 + keys %{$rtests}; diff --git a/t/snippets29.t b/t/snippets29.t new file mode 100644 index 00000000..66c1c15d --- /dev/null +++ b/t/snippets29.t @@ -0,0 +1,107 @@ +# Created with: ./make_t.pl + +# Contents: +#1 git125.git125 + +# To locate test #13 you can search for its name or the string '#13' + +use strict; +use Test::More; +use Carp; +use Perl::Tidy; +my $rparams; +my $rsources; +my $rtests; + +BEGIN { + + ########################################### + # BEGIN SECTION 1: Parameter combinations # + ########################################### + $rparams = { 'git125' => "-ssp=0", }; + + ############################ + # BEGIN SECTION 2: Sources # + ############################ + $rsources = { + + 'git125' => <<'----------', +sub Add ( $x, $y ); +sub Sub( $x, $y ); +---------- + }; + + #################################### + # BEGIN SECTION 3: Expected output # + #################################### + $rtests = { + + 'git125.git125' => { + source => "git125", + params => "git125", + expect => <<'#1...........', +sub Add( $x, $y ); +sub Sub( $x, $y ); +#1........... + }, + }; + + my $ntests = 0 + keys %{$rtests}; + plan tests => $ntests; +} + +############### +# EXECUTE TESTS +############### + +foreach my $key ( sort keys %{$rtests} ) { + my $output; + my $sname = $rtests->{$key}->{source}; + my $expect = $rtests->{$key}->{expect}; + my $pname = $rtests->{$key}->{params}; + my $source = $rsources->{$sname}; + my $params = defined($pname) ? $rparams->{$pname} : ""; + my $stderr_string; + my $errorfile_string; + my $err = Perl::Tidy::perltidy( + source => \$source, + destination => \$output, + perltidyrc => \$params, + argv => '', # for safety; hide any ARGV from perltidy + stderr => \$stderr_string, + errorfile => \$errorfile_string, # not used when -se flag is set + ); + if ( $err || $stderr_string || $errorfile_string ) { + print STDERR "Error output received for test '$key'\n"; + if ($err) { + print STDERR "An error flag '$err' was returned\n"; + ok( !$err ); + } + if ($stderr_string) { + print STDERR "---------------------\n"; + print STDERR "<>\n$stderr_string\n"; + print STDERR "---------------------\n"; + ok( !$stderr_string ); + } + if ($errorfile_string) { + print STDERR "---------------------\n"; + print STDERR "<<.ERR file>>\n$errorfile_string\n"; + print STDERR "---------------------\n"; + ok( !$errorfile_string ); + } + } + else { + if ( !is( $output, $expect, $key ) ) { + my $leno = length($output); + my $lene = length($expect); + if ( $leno == $lene ) { + print STDERR +"#> Test '$key' gave unexpected output. Strings differ but both have length $leno\n"; + } + else { + print STDERR +"#> Test '$key' gave unexpected output. String lengths differ: output=$leno, expected=$lene\n"; + } + } + } +}