]> git.donarmstrong.com Git - perltidy.git/commitdiff
added parameter -kpit=n and kpitl=s, see git#26 discussion
authorSteve Hancock <perltidy@users.sourceforge.net>
Mon, 25 May 2020 00:59:08 +0000 (17:59 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Mon, 25 May 2020 00:59:08 +0000 (17:59 -0700)
17 files changed:
CHANGES.md
bin/perltidy
docs/ChangeLog.html
docs/Tidy.html
docs/perltidy.html
lib/Perl/Tidy.pm
lib/Perl/Tidy/Formatter.pm
t/snippets/expect/kpit.def [new file with mode: 0644]
t/snippets/expect/kpit.kpit [new file with mode: 0644]
t/snippets/expect/kpitl.def [new file with mode: 0644]
t/snippets/expect/kpitl.kpitl [new file with mode: 0644]
t/snippets/kpit.in [new file with mode: 0644]
t/snippets/kpit.par [new file with mode: 0644]
t/snippets/kpitl.in [new file with mode: 0644]
t/snippets/kpitl.par [new file with mode: 0644]
t/snippets/packing_list.txt
t/snippets20.t

index 21d6a974f39512f8c14670dfccada830b7358952..ea121a66cdfef146e3607d396c2c1774f95c087c 100644 (file)
@@ -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.
 
index 89d9dcce759c41d5d42b159affb83574c6988545..2a9577c96fbb900a68337acb6c7aa849c962f40d 100755 (executable)
@@ -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<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 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<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 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<qw> quotes
 
 B<-tqw> or B<--trim-qw> provide the default behavior of trimming
index 54ae638397a8d7fc05e64b6b3afc2e8e3d852d97..094d007167bde0a162bf44799965e96b381c4382 100644 (file)
@@ -2,7 +2,15 @@
 
 <h2>2020 01 10.01</h2>
 
-<pre><code>- add option --break-at-old-semicolon-breakpoints', -bos, requested 
+<pre><code>- 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
index 412c2bae7cd6ca240252a8a5b92e6ea3d777e33b..00cdf7d4830a8ad5fd02bdcd7b9fc9247b4da9f1 100644 (file)
@@ -43,6 +43,8 @@
         perltidyrc        =&gt; $perltidyrc,
         logfile           =&gt; $logfile,
         errorfile         =&gt; $errorfile,
+        teefile           =&gt; $teefile,
+        debugfile         =&gt; $debugfile,
         formatter         =&gt; $formatter,           # callback object (see below)
         dump_options      =&gt; $dump_options,
         dump_options_type =&gt; $dump_options_type,
 
 <p>The <b>logfile</b> parameter allows the calling program to capture the log stream. This stream is only created if requested with a <b>-g</b> parameter. It contains detailed diagnostic information about a script which may be useful for debugging.</p>
 
+</dd>
+<dt id="teefile">teefile</dt>
+<dd>
+
+<p>The <b>teefile</b> parameter allows the calling program to capture the tee stream. This stream is only created if requested with one of the &#39;tee&#39; parameters, a <b>--tee-pod</b> , <b>--tee-block-comments</b>, <b>--tee-side-commnts</b>, or <b>--tee-all-comments</b>.</p>
+
+</dd>
+<dt id="debugfile">debugfile</dt>
+<dd>
+
+<p>The <b>debugfile</b> parameter allows the calling program to capture the stream produced by the <b>--DEBUG</b> parameter. This parameter is mainly used for debugging perltidy itself.</p>
+
 </dd>
 <dt id="argv">argv</dt>
 <dd>
index 44f052062e6e20d2423d2a86507d6504baa8b977..bfb16504fe61c3875f27a315a491b15e29f8a09d 100644 (file)
         sub usage();    # n=1 [default; follows input]
         sub usage ();   # n=2 [space]</code></pre>
 
+</dd>
+<dt id="kpit-n-or---keyword-paren-inner-tightness-n"><b>-kpit=n</b> or <b>--keyword-paren-inner-tightness=n</b></dt>
+<dd>
+
+<p>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>n</b> are as follows:</p>
+
+<pre><code>   -kpit=0 means always put a space (not tight)
+   -kpit=1 means ignore this parameter [default]
+   -kpit=2 means never put a space (tight)</code></pre>
+
+<p>To illustrate, the following snippet is shown formatted in three ways:</p>
+
+<pre><code>    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</code></pre>
+
+<p>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 &#39;if&#39; parens to have a space, since &#39;if&#39; 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.</p>
+
+<p>The set of keywords to which this parameter applies are by default are:</p>
+
+<pre><code>   if elsif unless while until for foreach</code></pre>
+
+<p>These can be changed with the parameter <b>-kpitl=s</b> described in the next section.</p>
+
+</dd>
+<dt id="kpitl-string-or---keyword-paren-inner-tightness-string"><b>-kpitl=string</b> or <b>--keyword-paren-inner-tightness=string</b></dt>
+<dd>
+
+<p>This command can be used to change the keywords to which the the <b>-kpit=n</b> command applies. The parameter <b>string</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</b> command is still required.</p>
+
+<p>For example, the commands <code>-kpitl=&quot;if else while&quot; -kpit=2</code> will cause the just the spaces inside parens following &#39;if&#39;, &#39;else&#39;, and &#39;while&#39; keywords to follow the tightness value indicated by the <b>-kpit=2</b> flag.</p>
+
 </dd>
 <dt id="Trimming-whitespace-around-qw-quotes">Trimming whitespace around <code>qw</code> quotes</dt>
 <dd>
index 205ac432a51836c917e2cac5339843d82f4036ba..8f55ea033ad0436c145d7ea25ebd9fca3f2833a0 100644 (file)
@@ -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
index b568457bdfefcb9b5ae8a0bf59f92885deace9b7..68d6b6569143ddb217cbca396cf284d6ea0dff4c 100644 (file)
@@ -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 <<snippets/space2.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 (file)
index 0000000..8354af2
--- /dev/null
@@ -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 (file)
index 0000000..5c640af
--- /dev/null
@@ -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 (file)
index 0000000..7da8ee3
--- /dev/null
@@ -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 (file)
index 0000000..a1f28c2
--- /dev/null
@@ -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 (file)
index 0000000..001886f
--- /dev/null
@@ -0,0 +1 @@
+if ( seek( DATA, 0, 0 ) ) { ... } 
diff --git a/t/snippets/kpit.par b/t/snippets/kpit.par
new file mode 100644 (file)
index 0000000..dd5241c
--- /dev/null
@@ -0,0 +1 @@
+-pt=2 -kpit=0
diff --git a/t/snippets/kpitl.in b/t/snippets/kpitl.in
new file mode 100644 (file)
index 0000000..186a3d9
--- /dev/null
@@ -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 (file)
index 0000000..1290aab
--- /dev/null
@@ -0,0 +1 @@
+-kpit=0 -kpitl='return factorial' -pt=2
index f4ce326c1913198f33a99412eb18828034c6d9c1..05dddc9ea11676f26ce0d6be9f7a2d53143c0510 100644 (file)
 ../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
 ../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
index 6e201156ddbda416eff85a0034771bd2340117fb..fbead06517675a8a4b3adc364be94c0672adae07 100644 (file)
 #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};