## 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
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<signature> rather than a sub B<prototype>.
+
+For example, consider the following line:
+
+ sub circle( $xc, $yc, $rad )
+
+This space before the opening paren can be controlled with integer B<n> 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,
'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', ' ' ],
$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', '!' );
'keyword-group-blanks-after' => [ 0, 2 ],
'space-prototype-paren' => [ 0, 2 ],
+ 'space-signature-paren' => [ 0, 2 ],
'break-after-labels' => [ 0, 2 ],
);
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
$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,
$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'};
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';
# 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 '('
{
$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
}
}
# 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;
}
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
--- /dev/null
+sub Add ( $x, $y );
+sub Sub( $x, $y );
--- /dev/null
+sub Add( $x, $y );
+sub Sub( $x, $y );
# 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;
}
--- /dev/null
+sub Add ( $x, $y );
+sub Sub( $x, $y );
../snippets9.t rt98902.def
../snippets9.t rt98902.rt98902
../snippets9.t rt99961.def
+../snippets28.t git125.def
+../snippets29.t git125.git125
# 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;
}
#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'
}
];
}
+----------
+
+ 'git125' => <<'----------',
+sub Add ( $x, $y );
+sub Sub( $x, $y );
----------
'lrt' => <<'----------',
}
#18...........
},
+
+ 'git125.def' => {
+ source => "git125",
+ params => "def",
+ expect => <<'#19...........',
+sub Add ( $x, $y );
+sub Sub( $x, $y );
+#19...........
+ },
};
my $ntests = 0 + keys %{$rtests};
--- /dev/null
+# 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 "<<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";
+ }
+ }
+ }
+}