]> git.donarmstrong.com Git - perltidy.git/commitdiff
restructure sub get_final_indentation
authorSteve Hancock <perltidy@users.sourceforge.net>
Tue, 23 Aug 2022 01:02:05 +0000 (18:02 -0700)
committerSteve Hancock <perltidy@users.sourceforge.net>
Tue, 23 Aug 2022 01:02:05 +0000 (18:02 -0700)
lib/Perl/Tidy/Formatter.pm

index 63ea9556648a71f07b947ed76fee78199523577a..5f60f74843e80036daacbd6dfe6ad0d2f760d5fc 100644 (file)
@@ -25197,7 +25197,7 @@ sub make_paren_name {
             $rpatterns,  $ri_first,
             $ri_last,    $rindentation_list,
             $level_jump, $starting_in_quote,
-            $is_static_block_comment,
+            $is_static_block_comment
         ) = @_;
 
         # Find the last code token of this line
@@ -25222,9 +25222,6 @@ sub make_paren_name {
         my $seqno_beg           = $type_sequence_to_go[$ibeg];
         my $is_closing_type_beg = $is_closing_type{$type_beg};
 
-        my $ris_bli_container = $self->[_ris_bli_container_];
-        my $is_bli_beg = $seqno_beg ? $ris_bli_container->{$seqno_beg} : 0;
-
         # QW INDENTATION PATCH 3:
         my $seqno_qw_closing;
         if ( $type_beg eq 'q' && $ibeg == 0 ) {
@@ -25275,663 +25272,761 @@ sub make_paren_name {
         #       2 - vertically align with opening token
         #       3 - indent
         #---------------------------------------------------------
+
         my $adjust_indentation         = 0;
-        my $default_adjust_indentation = $adjust_indentation;
+        my $default_adjust_indentation = 0;
 
+        # Parameters needed for option 2, aligning with opening token:
         my (
             $opening_indentation, $opening_offset,
             $is_leading,          $opening_exists
         );
 
-        # Honor any flag to reduce -ci set by the -bbxi=n option
-        if ( $seqno_beg && $self->[_rwant_reduced_ci_]->{$seqno_beg} ) {
+        #-------------------------------------
+        # Section 1A:
+        # if line starts with a sequenced item
+        #-------------------------------------
+        if ( $seqno_beg || $seqno_qw_closing ) {
 
-            # if this is an opening, it must be alone on the line ...
-            if ( $is_closing_type{$type_beg} || $ibeg == $i_terminal ) {
-                $adjust_indentation = 1;
-            }
+            # This can be tedious so we let a sub do it
+            (
+                $adjust_indentation,  $default_adjust_indentation,
+                $opening_indentation, $opening_offset,
+                $is_leading,          $opening_exists
+              )
+              = $self->get_closing_token_indentation(
+
+                $ibeg,
+                $iend,
+                $ri_first,
+                $ri_last,
+                $rindentation_list,
+                $level_jump,
+                $i_terminal,
+                $is_semicolon_terminated,
+                $seqno_qw_closing,
 
-            # ... or a single welded unit (fix for b1173)
-            elsif ($total_weld_count) {
-                my $K_beg      = $K_to_go[$ibeg];
-                my $Kterm      = $K_to_go[$i_terminal];
-                my $Kterm_test = $self->[_rK_weld_left_]->{$Kterm};
-                if ( defined($Kterm_test) && $Kterm_test >= $K_beg ) {
-                    $Kterm = $Kterm_test;
-                }
-                if ( $Kterm == $K_beg ) { $adjust_indentation = 1 }
-            }
+              );
         }
 
-        # Update the $is_bli flag as we go. It is initially 1.
-        # We note seeing a leading opening brace by setting it to 2.
-        # If we get to the closing brace without seeing the opening then we
-        # turn it off.  This occurs if the opening brace did not get output
-        # at the start of a line, so we will then indent the closing brace
-        # in the default way.
-        if ( $is_bli_beg && $is_bli_beg == 1 ) {
-            my $K_opening_container = $self->[_K_opening_container_];
-            my $K_opening           = $K_opening_container->{$seqno_beg};
-            my $K_beg               = $K_to_go[$ibeg];
-            if ( $K_beg eq $K_opening ) {
-                $ris_bli_container->{$seqno_beg} = $is_bli_beg = 2;
+        #--------------------------------------------------------
+        # Section 1B:
+        # if at ');', '};', '>;', and '];' of a terminal qw quote
+        #--------------------------------------------------------
+        elsif (
+               substr( $rpatterns->[0], 0, 2 ) eq 'qb'
+            && substr( $rfields->[0], -1, 1 ) eq ';'
+            ##         $rpatterns->[0] =~ /^qb*;$/
+            && $rfields->[0] =~ /^([\)\}\]\>]);$/
+          )
+        {
+            if ( $closing_token_indentation{$1} == 0 ) {
+                $adjust_indentation = 1;
             }
-            else { $is_bli_beg = 0 }
-        }
-
-        # QW PATCH for the combination -lp -wn
-        # For -lp formatting use $ibeg_weld_fix to get around the problem
-        # that with -lp type formatting the opening and closing tokens to not
-        # have sequence numbers.
-        my $ibeg_weld_fix = $ibeg;
-        if ( $seqno_qw_closing && $total_weld_count ) {
-            my $i_plus = $inext_to_go[$ibeg];
-            if ( $i_plus <= $max_index_to_go ) {
-                my $K_plus = $K_to_go[$i_plus];
-                if ( defined( $self->[_rK_weld_left_]->{$K_plus} ) ) {
-                    $ibeg_weld_fix = $i_plus;
-                }
+            else {
+                $adjust_indentation = 3;
             }
         }
 
-        # if we are at a closing token of some type..
-        if ( $is_closing_type_beg || $seqno_qw_closing ) {
-
-            my $K_beg = $K_to_go[$ibeg];
-
-            # get the indentation of the line containing the corresponding
-            # opening token
-            (
-                $opening_indentation, $opening_offset,
-                $is_leading,          $opening_exists
-              )
-              = $self->get_opening_indentation( $ibeg_weld_fix, $ri_first,
-                $ri_last, $rindentation_list, $seqno_qw_closing );
-
-            my $terminal_is_in_list = $self->is_in_list_by_i($i_terminal);
-
-            # First set the default behavior:
-            if (
+        #---------------------------------------------------------
+        # Section 2: set indentation according to flag set above
+        #
+        # Select the indentation object to define leading
+        # whitespace.  If we are outdenting something like '} } );'
+        # then we want to use one level below the last token
+        # ($i_terminal) in order to get it to fully outdent through
+        # all levels.
+        #---------------------------------------------------------
+        my $indentation;
+        my $lev;
+        my $level_end = $levels_to_go[$iend];
 
-                # default behavior is to outdent closing lines
-                # of the form:   ");  };  ];  )->xxx;"
-                $is_semicolon_terminated
+        #------------------------------------
+        # Section 2A: adjust_indentation == 0
+        # No change in indentation
+        #------------------------------------
+        if ( $adjust_indentation == 0 ) {
+            $indentation = $leading_spaces_beg;
+            $lev         = $level_beg;
+        }
 
-                # and 'cuddled parens' of the form:   ")->pack("
-                # Bug fix for RT #123749]: the types here were
-                # incorrectly '(' and ')'.  Corrected to be '{' and '}'
-                || (
-                       $terminal_type eq '{'
-                    && $type_beg eq '}'
-                    && ( $nesting_depth_to_go[$iend] + 1 ==
-                        $nesting_depth_to_go[$ibeg] )
-                )
+        #-------------------------------------------------------------------
+        # Secton 2B: adjust_indentation == 1
+        # Change the indentation to be that of a different token on the line
+        #-------------------------------------------------------------------
+        elsif ( $adjust_indentation == 1 ) {
 
-                # remove continuation indentation for any line like
-                #       } ... {
-                # or without ending '{' and unbalanced, such as
-                #       such as '}->{$operator}'
-                || (
-                    $type_beg eq '}'
+            # Previously, the indentation of the terminal token was used:
+            # OLD CODING:
+            # $indentation = $reduced_spaces_to_go[$i_terminal];
+            # $lev         = $levels_to_go[$i_terminal];
 
-                    && (   $types_to_go[$iend] eq '{'
-                        || $levels_to_go[$iend] < $level_beg )
-                )
+            # Generalization for MOJO patch:
+            # Use the lowest level indentation of the tokens on the line.
+            # For example, here we can use the indentation of the ending ';':
+            #    } until ($selection > 0 and $selection < 10);   # ok to use ';'
+            # But this will not outdent if we use the terminal indentation:
+            #    )->then( sub {      # use indentation of the ->, not the {
+            # Warning: reduced_spaces_to_go[] may be a reference, do not
+            # do numerical checks with it
 
-                # and when the next line is at a lower indentation level...
+            my $i_ind = $ibeg;
+            $indentation = $reduced_spaces_to_go[$i_ind];
+            $lev         = $levels_to_go[$i_ind];
+            while ( $i_ind < $i_terminal ) {
+                $i_ind++;
+                if ( $levels_to_go[$i_ind] < $lev ) {
+                    $indentation = $reduced_spaces_to_go[$i_ind];
+                    $lev         = $levels_to_go[$i_ind];
+                }
+            }
+        }
 
-                # PATCH #1: and only if the style allows undoing continuation
-                # for all closing token types. We should really wait until
-                # the indentation of the next line is known and then make
-                # a decision, but that would require another pass.
+        #--------------------------------------------------------------
+        # Secton 2C: adjust_indentation == 2
+        # Handle indented closing token which aligns with opening token
+        #--------------------------------------------------------------
+        elsif ( $adjust_indentation == 2 ) {
 
-                # PATCH #2: and not if this token is under -xci control
-                || (   $level_jump < 0
-                    && !$some_closing_token_indentation
-                    && !$self->[_rseqno_controlling_my_ci_]->{$K_beg} )
+            # handle option to align closing token with opening token
+            $lev = $level_beg;
 
-                # Patch for -wn=2, multiple welded closing tokens
-                || (   $i_terminal > $ibeg
-                    && $is_closing_type{ $types_to_go[$iend] } )
+            # calculate spaces needed to align with opening token
+            my $space_count =
+              get_spaces($opening_indentation) + $opening_offset;
 
-                # Alternate Patch for git #51, isolated closing qw token not
-                # outdented if no-delete-old-newlines is set. This works, but
-                # a more general patch elsewhere fixes the real problem: ljump.
-                # || ( $seqno_qw_closing && $ibeg == $i_terminal )
+            # Indent less than the previous line.
+            #
+            # Problem: For -lp we don't exactly know what it was if there
+            # were recoverable spaces sent to the aligner.  A good solution
+            # would be to force a flush of the vertical alignment buffer, so
+            # that we would know.  For now, this rule is used for -lp:
+            #
+            # When the last line did not start with a closing token we will
+            # be optimistic that the aligner will recover everything wanted.
+            #
+            # This rule will prevent us from breaking a hierarchy of closing
+            # tokens, and in a worst case will leave a closing paren too far
+            # indented, but this is better than frequently leaving it not
+            # indented enough.
+            my $last_spaces = get_spaces($last_indentation_written);
 
-              )
+            if ( ref($last_indentation_written)
+                && !$is_closing_token{$last_leading_token} )
             {
-                $adjust_indentation = 1;
+                $last_spaces +=
+                  get_recoverable_spaces($last_indentation_written);
             }
 
-            # outdent something like '),'
-            if (
-                $terminal_type eq ','
-
-                # Removed this constraint for -wn
-                # OLD: allow just one character before the comma
-                # && $i_terminal == $ibeg + 1
+            # reset the indentation to the new space count if it works
+            # only options are all or none: nothing in-between looks good
+            $lev = $level_beg;
 
-                # require LIST environment; otherwise, we may outdent too much -
-                # this can happen in calls without parentheses (overload.t);
-                && $terminal_is_in_list
-              )
-            {
-                $adjust_indentation = 1;
+            my $diff = $last_spaces - $space_count;
+            if ( $diff > 0 ) {
+                $indentation = $space_count;
             }
+            else {
 
-            # undo continuation indentation of a terminal closing token if
-            # it is the last token before a level decrease.  This will allow
-            # a closing token to line up with its opening counterpart, and
-            # avoids an indentation jump larger than 1 level.
-            my $rLL    = $self->[_rLL_];
-            my $Klimit = $self->[_Klimit_];
-            if (   $i_terminal == $ibeg
-                && $is_closing_type_beg
-                && defined($K_beg)
-                && $K_beg < $Klimit )
-            {
-                my $K_plus    = $K_beg + 1;
-                my $type_plus = $rLL->[$K_plus]->[_TYPE_];
+                # We need to fix things ... but there is no good way to do it.
+                # The best solution is for the user to use a longer maximum
+                # line length.  We could get a smooth variation if we just move
+                # the paren in using
+                #    $space_count -= ( 1 - $diff );
+                # But unfortunately this can give a rather unbalanced look.
 
-                if ( $type_plus eq 'b' && $K_plus < $Klimit ) {
-                    $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
+                # For -xlp we currently allow a tolerance of one indentation
+                # level and then revert to a simpler default.  This will jump
+                # suddenly but keeps a balanced look.
+                if (   $rOpts_extended_line_up_parentheses
+                    && $diff >= -$rOpts_indent_columns
+                    && $space_count > $leading_spaces_beg )
+                {
+                    $indentation = $space_count;
                 }
 
-                if ( $type_plus eq '#' && $K_plus < $Klimit ) {
-                    $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
-                    if ( $type_plus eq 'b' && $K_plus < $Klimit ) {
-                        $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
-                    }
-
-                    # Note: we have skipped past just one comment (perhaps a
-                    # side comment).  There could be more, and we could easily
-                    # skip past all the rest with the following code, or with a
-                    # while loop.  It would be rare to have to do this, and
-                    # those block comments would still be indented, so it would
-                    # to leave them indented.  So it seems best to just stop at
-                    # a maximum of one comment.
-                    ##if ($type_plus eq '#') {
-                    ##   $K_plus = $self->K_next_code($K_plus);
-                    ##}
+                # Otherwise revert to defaults
+                elsif ( $default_adjust_indentation == 0 ) {
+                    $indentation = $leading_spaces_beg;
                 }
+                elsif ( $default_adjust_indentation == 1 ) {
+                    $indentation = $reduced_spaces_to_go[$i_terminal];
+                    $lev         = $levels_to_go[$i_terminal];
+                }
+            }
+        }
 
-                if ( !$is_bli_beg && defined($K_plus) ) {
-                    my $lev        = $level_beg;
-                    my $level_next = $rLL->[$K_plus]->[_LEVEL_];
+        #-------------------------------------------------------------
+        # Secton 2D: adjust_indentation == 3
+        # Full indentation of closing tokens (-icb and -icp or -cti=2)
+        #-------------------------------------------------------------
+        else {
 
-                    # and do not undo ci if it was set by the -xci option
-                    $adjust_indentation = 1
-                      if ( $level_next < $lev
-                        && !$self->[_rseqno_controlling_my_ci_]->{$K_beg} );
-                }
+            # handle -icb (indented closing code block braces)
+            # Updated method for indented block braces: indent one full level if
+            # there is no continuation indentation.  This will occur for major
+            # structures such as sub, if, else, but not for things like map
+            # blocks.
+            #
+            # Note: only code blocks without continuation indentation are
+            # handled here (if, else, unless, ..). In the following snippet,
+            # the terminal brace of the sort block will have continuation
+            # indentation as shown so it will not be handled by the coding
+            # here.  We would have to undo the continuation indentation to do
+            # this, but it probably looks ok as is.  This is a possible future
+            # update for semicolon terminated lines.
+            #
+            #     if ($sortby eq 'date' or $sortby eq 'size') {
+            #         @files = sort {
+            #             $file_data{$a}{$sortby} <=> $file_data{$b}{$sortby}
+            #                 or $a cmp $b
+            #                 } @files;
+            #         }
+            #
+            if (   $block_type_beg
+                && $ci_levels_to_go[$i_terminal] == 0 )
+            {
+                my $spaces = get_spaces( $leading_spaces_to_go[$i_terminal] );
+                $indentation = $spaces + $rOpts_indent_columns;
 
-                # Patch for RT #96101, in which closing brace of anonymous subs
-                # was not outdented.  We should look ahead and see if there is
-                # a level decrease at the next token (i.e., a closing token),
-                # but right now we do not have that information.  For now
-                # we see if we are in a list, and this works well.
-                # See test files 'sub*.t' for good test cases.
-                if (   $terminal_is_in_list
-                    && !$rOpts_indent_closing_brace
-                    && $block_type_beg
-                    && $block_type_beg =~ /$ASUB_PATTERN/ )
+                # NOTE: for -lp we could create a new indentation object, but
+                # there is probably no need to do it
+            }
+
+            # handle -icp and any -icb block braces which fall through above
+            # test such as the 'sort' block mentioned above.
+            else {
+
+                # There are currently two ways to handle -icp...
+                # One way is to use the indentation of the previous line:
+                # $indentation = $last_indentation_written;
+
+                # The other way is to use the indentation that the previous line
+                # would have had if it hadn't been adjusted:
+                $indentation = $last_unadjusted_indentation;
+
+                # Current method: use the minimum of the two. This avoids
+                # inconsistent indentation.
+                if ( get_spaces($last_indentation_written) <
+                    get_spaces($indentation) )
                 {
-                    (
-                        $opening_indentation, $opening_offset,
-                        $is_leading,          $opening_exists
-                      )
-                      = $self->get_opening_indentation( $ibeg, $ri_first,
-                        $ri_last, $rindentation_list );
-                    my $indentation = $leading_spaces_beg;
-                    if ( defined($opening_indentation)
-                        && get_spaces($indentation) >
-                        get_spaces($opening_indentation) )
-                    {
-                        $adjust_indentation = 1;
-                    }
+                    $indentation = $last_indentation_written;
                 }
             }
 
-            # YVES patch 1 of 2:
-            # Undo ci of line with leading closing eval brace,
-            # but not beyond the indentation of the line with
-            # the opening brace.
-            if (   $block_type_beg eq 'eval'
-                && !ref($leading_spaces_beg)
-                && !$rOpts_indent_closing_brace )
+            # use previous indentation but use own level
+            # to cause list to be flushed properly
+            $lev = $level_beg;
+        }
+
+        #-------------------------------------------------------------
+        # Remember indentation except for multi-line quotes, which get
+        # no indentation
+        #-------------------------------------------------------------
+        if ( !( $ibeg == 0 && $starting_in_quote ) ) {
+            $last_indentation_written    = $indentation;
+            $last_unadjusted_indentation = $leading_spaces_beg;
+            $last_leading_token          = $token_beg;
+
+            # Patch to make a line which is the end of a qw quote work with the
+            # -lp option.  Make $token_beg look like a closing token as some
+            # type even if it is not.  This variable will become
+            # $last_leading_token at the end of this loop.  Then, if the -lp
+            # style is selected, and the next line is also a
+            # closing token, it will not get more indentation than this line.
+            # We need to do this because qw quotes (at present) only get
+            # continuation indentation, not one level of indentation, so we
+            # need to turn off the -lp indentation.
+
+            # ... a picture is worth a thousand words:
+
+            # perltidy -wn -gnu (Without this patch):
+            #   ok(defined(
+            #       $seqio = $gb->get_Stream_by_batch([qw(J00522 AF303112
+            #       2981014)])
+            #             ));
+
+            # perltidy -wn -gnu (With this patch):
+            #  ok(defined(
+            #      $seqio = $gb->get_Stream_by_batch([qw(J00522 AF303112
+            #      2981014)])
+            #  ));
+            if ( $seqno_qw_closing
+                && ( length($token_beg) > 1 || $token_beg eq '>' ) )
             {
-                (
-                    $opening_indentation, $opening_offset,
-                    $is_leading,          $opening_exists
-                  )
-                  = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
-                    $rindentation_list );
-                my $indentation = $leading_spaces_beg;
-                if ( defined($opening_indentation)
-                    && get_spaces($indentation) >
-                    get_spaces($opening_indentation) )
-                {
-                    $adjust_indentation = 1;
-                }
+                $last_leading_token = ')';
             }
+        }
 
-            # patch for issue git #40: -bli setting has priority
-            $adjust_indentation = 0 if ($is_bli_beg);
+        #---------------------------------------------------------------------
+        # Rule: lines with leading closing tokens should not be outdented more
+        # than the line which contained the corresponding opening token.
+        #---------------------------------------------------------------------
 
-            $default_adjust_indentation = $adjust_indentation;
+        # Updated per bug report in alex_bug.pl: we must not
+        # mess with the indentation of closing logical braces, so
+        # we must treat something like '} else {' as if it were
+        # an isolated brace
+        my $is_isolated_block_brace = $block_type_beg
+          && ( $i_terminal == $ibeg
+            || $is_if_elsif_else_unless_while_until_for_foreach{$block_type_beg}
+          );
 
-            # Now modify default behavior according to user request:
-            # handle option to indent non-blocks of the form );  };  ];
-            # But don't do special indentation to something like ')->pack('
-            if ( !$block_type_beg ) {
+        # only do this for a ':; which is aligned with its leading '?'
+        my $is_unaligned_colon = $type_beg eq ':' && !$is_leading;
 
-                # Note that logical padding has already been applied, so we may
-                # need to remove some spaces to get a valid hash key.
-                my $tok = $token_beg;
-                my $cti = $closing_token_indentation{$tok};
+        if (
+            defined($opening_indentation)
+            && !$leading_paren_arrow    # MOJO patch
+            && !$is_isolated_block_brace
+            && !$is_unaligned_colon
+          )
+        {
+            if ( get_spaces($opening_indentation) > get_spaces($indentation) ) {
+                $indentation = $opening_indentation;
+            }
+        }
 
-                # Fix the value of 'cti' for an isolated non-welded closing qw
-                # delimiter.
-                if ( $seqno_qw_closing && $ibeg_weld_fix == $ibeg ) {
+        #----------------------------------------------------
+        # remember the indentation of each line of this batch
+        #----------------------------------------------------
+        push @{$rindentation_list}, $indentation;
 
-                    # A quote delimiter which is not a container will not have
-                    # a cti value defined.  In this case use the style of a
-                    # paren. For example
-                    #   my @fars = (
-                    #      qw<
-                    #        far
-                    #        farfar
-                    #        farfars-far
-                    #      >,
-                    #   );
-                    if ( !defined($cti) && length($tok) == 1 ) {
+        #---------------------------------------------
+        # outdent lines with certain leading tokens...
+        #---------------------------------------------
+        if (
 
-                        # something other than ')', '}', ']' ; use flag for ')'
-                        $cti = $closing_token_indentation{')'};
+            # must be first word of this batch
+            $ibeg == 0
 
-                        # But for now, do not outdent non-container qw
-                        # delimiters because it would would change existing
-                        # formatting.
-                        if ( $tok ne '>' ) { $cti = 3 }
-                    }
+            # and ...
+            && (
 
-                    # A non-welded closing qw cannot currently use -cti=1
-                    # because that option requires a sequence number to find
-                    # the opening indentation, and qw quote delimiters are not
-                    # sequenced items.
-                    if ( defined($cti) && $cti == 1 ) { $cti = 0 }
-                }
+                # certain leading keywords if requested
+                $rOpts_outdent_keywords
+                && $type_beg eq 'k'
+                && $outdent_keyword{$token_beg}
 
-                if ( !defined($cti) ) {
+                # or labels if requested
+                || $rOpts_outdent_labels && $type_beg eq 'J'
 
-                    # $cti may not be defined for several reasons.
-                    # -padding may have been applied so the character
-                    #  has a length > 1
-                    # - we may have welded to a closing quote token.
-                    #   Here is an example (perltidy -wn):
-                    #       __PACKAGE__->load_components( qw(
-                    #  >         Core
-                    #  >
-                    #  >     ) );
-                    $adjust_indentation = 0;
+                # or static block comments if requested
+                || $is_static_block_comment
+                && $rOpts_outdent_static_block_comments
+            )
+          )
+        {
+            my $space_count = leading_spaces_to_go($ibeg);
+            if ( $space_count > 0 ) {
+                $space_count -= $rOpts_continuation_indentation;
+                $is_outdented_line = 1;
+                if ( $space_count < 0 ) { $space_count = 0 }
 
+                # do not promote a spaced static block comment to non-spaced;
+                # this is not normally necessary but could be for some
+                # unusual user inputs (such as -ci = -i)
+                if ( $type_beg eq '#' && $space_count == 0 ) {
+                    $space_count = 1;
                 }
-                elsif ( $cti == 1 ) {
-                    if (   $i_terminal <= $ibeg + 1
-                        || $is_semicolon_terminated )
-                    {
-                        $adjust_indentation = 2;
-                    }
-                    else {
-                        $adjust_indentation = 0;
-                    }
-                }
-                elsif ( $cti == 2 ) {
-                    if ($is_semicolon_terminated) {
-                        $adjust_indentation = 3;
-                    }
-                    else {
-                        $adjust_indentation = 0;
-                    }
-                }
-                elsif ( $cti == 3 ) {
-                    $adjust_indentation = 3;
-                }
+
+                $indentation = $space_count;
             }
+        }
 
-            # handle option to indent blocks
-            else {
-                if (
-                    $rOpts_indent_closing_brace
-                    && (
-                        $i_terminal == $ibeg    #  isolated terminal '}'
-                        || $is_semicolon_terminated
-                    )
-                  )                             #  } xxxx ;
-                {
-                    $adjust_indentation = 3;
+        return ( $indentation, $lev, $level_end, $i_terminal,
+            $is_outdented_line );
+    } ## end sub get_final_indentation
+
+    sub get_closing_token_indentation {
+
+        # Determine indentation adjustment for a line with a leading closing
+        # token - i.e. one of these:     ) ] } :
+
+        my (
+            $self,
+
+            $ibeg,
+            $iend,
+            $ri_first,
+            $ri_last,
+            $rindentation_list,
+            $level_jump,
+            $i_terminal,
+            $is_semicolon_terminated,
+            $seqno_qw_closing,
+
+        ) = @_;
+
+        my $adjust_indentation         = 0;
+        my $default_adjust_indentation = $adjust_indentation;
+        my $terminal_type              = $types_to_go[$i_terminal];
+
+        my $type_beg            = $types_to_go[$ibeg];
+        my $token_beg           = $tokens_to_go[$ibeg];
+        my $level_beg           = $levels_to_go[$ibeg];
+        my $block_type_beg      = $block_type_to_go[$ibeg];
+        my $leading_spaces_beg  = $leading_spaces_to_go[$ibeg];
+        my $seqno_beg           = $type_sequence_to_go[$ibeg];
+        my $is_closing_type_beg = $is_closing_type{$type_beg};
+
+        my (
+            $opening_indentation, $opening_offset,
+            $is_leading,          $opening_exists
+        );
+
+        # Honor any flag to reduce -ci set by the -bbxi=n option
+        if ( $seqno_beg && $self->[_rwant_reduced_ci_]->{$seqno_beg} ) {
+
+            # if this is an opening, it must be alone on the line ...
+            if ( $is_closing_type{$type_beg} || $ibeg == $i_terminal ) {
+                $adjust_indentation = 1;
+            }
+
+            # ... or a single welded unit (fix for b1173)
+            elsif ($total_weld_count) {
+                my $K_beg      = $K_to_go[$ibeg];
+                my $Kterm      = $K_to_go[$i_terminal];
+                my $Kterm_test = $self->[_rK_weld_left_]->{$Kterm};
+                if ( defined($Kterm_test) && $Kterm_test >= $K_beg ) {
+                    $Kterm = $Kterm_test;
                 }
+                if ( $Kterm == $K_beg ) { $adjust_indentation = 1 }
             }
-        } ## end if ( $is_closing_type_beg || $seqno_qw_closing )
+        }
 
-        # if at ');', '};', '>;', and '];' of a terminal qw quote
-        elsif (
-               substr( $rpatterns->[0], 0, 2 ) eq 'qb'
-            && substr( $rfields->[0], -1, 1 ) eq ';'
-            ##&& $rpatterns->[0] =~ /^qb*;$/
-            && $rfields->[0] =~ /^([\)\}\]\>]);$/
-          )
-        {
-            if ( $closing_token_indentation{$1} == 0 ) {
-                $adjust_indentation = 1;
+        my $ris_bli_container = $self->[_ris_bli_container_];
+        my $is_bli_beg = $seqno_beg ? $ris_bli_container->{$seqno_beg} : 0;
+
+        # Update the $is_bli flag as we go. It is initially 1.
+        # We note seeing a leading opening brace by setting it to 2.
+        # If we get to the closing brace without seeing the opening then we
+        # turn it off.  This occurs if the opening brace did not get output
+        # at the start of a line, so we will then indent the closing brace
+        # in the default way.
+        if ( $is_bli_beg && $is_bli_beg == 1 ) {
+            my $K_opening_container = $self->[_K_opening_container_];
+            my $K_opening           = $K_opening_container->{$seqno_beg};
+            my $K_beg               = $K_to_go[$ibeg];
+            if ( $K_beg eq $K_opening ) {
+                $ris_bli_container->{$seqno_beg} = $is_bli_beg = 2;
             }
-            else {
-                $adjust_indentation = 3;
+            else { $is_bli_beg = 0 }
+        }
+
+        # QW PATCH for the combination -lp -wn
+        # For -lp formatting use $ibeg_weld_fix to get around the problem
+        # that with -lp type formatting the opening and closing tokens to not
+        # have sequence numbers.
+        my $ibeg_weld_fix = $ibeg;
+        if ( $seqno_qw_closing && $total_weld_count ) {
+            my $i_plus = $inext_to_go[$ibeg];
+            if ( $i_plus <= $max_index_to_go ) {
+                my $K_plus = $K_to_go[$i_plus];
+                if ( defined( $self->[_rK_weld_left_]->{$K_plus} ) ) {
+                    $ibeg_weld_fix = $i_plus;
+                }
             }
         }
 
-        # if line begins with a ':', align it with any
-        # previous line leading with corresponding ?
-        elsif ( $type_beg eq ':' ) {
+        # if we are at a closing token of some type..
+        if ( $is_closing_type_beg || $seqno_qw_closing ) {
+
+            my $K_beg = $K_to_go[$ibeg];
+
+            # get the indentation of the line containing the corresponding
+            # opening token
             (
                 $opening_indentation, $opening_offset,
                 $is_leading,          $opening_exists
               )
-              = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
-                $rindentation_list );
-            if ($is_leading) { $adjust_indentation = 2; }
-        }
+              = $self->get_opening_indentation( $ibeg_weld_fix, $ri_first,
+                $ri_last, $rindentation_list, $seqno_qw_closing );
 
-        #---------------------------------------------------------
-        # Section 2: set indentation according to flag set above
-        #
-        # Select the indentation object to define leading
-        # whitespace.  If we are outdenting something like '} } );'
-        # then we want to use one level below the last token
-        # ($i_terminal) in order to get it to fully outdent through
-        # all levels.
-        #---------------------------------------------------------
-        my $indentation;
-        my $lev;
-        my $level_end = $levels_to_go[$iend];
+            my $terminal_is_in_list = $self->is_in_list_by_i($i_terminal);
 
-        if ( $adjust_indentation == 0 ) {
-            $indentation = $leading_spaces_beg;
-            $lev         = $level_beg;
-        }
-        elsif ( $adjust_indentation == 1 ) {
+            # First set the default behavior:
+            if (
 
-            # Change the indentation to be that of a different token on the line
-            # Previously, the indentation of the terminal token was used:
-            # OLD CODING:
-            # $indentation = $reduced_spaces_to_go[$i_terminal];
-            # $lev         = $levels_to_go[$i_terminal];
+                # default behavior is to outdent closing lines
+                # of the form:   ");  };  ];  )->xxx;"
+                $is_semicolon_terminated
 
-            # Generalization for MOJO patch:
-            # Use the lowest level indentation of the tokens on the line.
-            # For example, here we can use the indentation of the ending ';':
-            #    } until ($selection > 0 and $selection < 10);   # ok to use ';'
-            # But this will not outdent if we use the terminal indentation:
-            #    )->then( sub {      # use indentation of the ->, not the {
-            # Warning: reduced_spaces_to_go[] may be a reference, do not
-            # do numerical checks with it
+                # and 'cuddled parens' of the form:   ")->pack("
+                # Bug fix for RT #123749]: the types here were
+                # incorrectly '(' and ')'.  Corrected to be '{' and '}'
+                || (
+                       $terminal_type eq '{'
+                    && $type_beg eq '}'
+                    && ( $nesting_depth_to_go[$iend] + 1 ==
+                        $nesting_depth_to_go[$ibeg] )
+                )
 
-            my $i_ind = $ibeg;
-            $indentation = $reduced_spaces_to_go[$i_ind];
-            $lev         = $levels_to_go[$i_ind];
-            while ( $i_ind < $i_terminal ) {
-                $i_ind++;
-                if ( $levels_to_go[$i_ind] < $lev ) {
-                    $indentation = $reduced_spaces_to_go[$i_ind];
-                    $lev         = $levels_to_go[$i_ind];
-                }
-            }
-        }
+                # remove continuation indentation for any line like
+                #       } ... {
+                # or without ending '{' and unbalanced, such as
+                #       such as '}->{$operator}'
+                || (
+                    $type_beg eq '}'
 
-        # handle indented closing token which aligns with opening token
-        elsif ( $adjust_indentation == 2 ) {
+                    && (   $types_to_go[$iend] eq '{'
+                        || $levels_to_go[$iend] < $level_beg )
+                )
 
-            # handle option to align closing token with opening token
-            $lev = $level_beg;
+                # and when the next line is at a lower indentation level...
 
-            # calculate spaces needed to align with opening token
-            my $space_count =
-              get_spaces($opening_indentation) + $opening_offset;
+                # PATCH #1: and only if the style allows undoing continuation
+                # for all closing token types. We should really wait until
+                # the indentation of the next line is known and then make
+                # a decision, but that would require another pass.
 
-            # Indent less than the previous line.
-            #
-            # Problem: For -lp we don't exactly know what it was if there
-            # were recoverable spaces sent to the aligner.  A good solution
-            # would be to force a flush of the vertical alignment buffer, so
-            # that we would know.  For now, this rule is used for -lp:
-            #
-            # When the last line did not start with a closing token we will
-            # be optimistic that the aligner will recover everything wanted.
-            #
-            # This rule will prevent us from breaking a hierarchy of closing
-            # tokens, and in a worst case will leave a closing paren too far
-            # indented, but this is better than frequently leaving it not
-            # indented enough.
-            my $last_spaces = get_spaces($last_indentation_written);
+                # PATCH #2: and not if this token is under -xci control
+                || (   $level_jump < 0
+                    && !$some_closing_token_indentation
+                    && !$self->[_rseqno_controlling_my_ci_]->{$K_beg} )
 
-            if ( ref($last_indentation_written)
-                && !$is_closing_token{$last_leading_token} )
-            {
-                $last_spaces +=
-                  get_recoverable_spaces($last_indentation_written);
-            }
+                # Patch for -wn=2, multiple welded closing tokens
+                || (   $i_terminal > $ibeg
+                    && $is_closing_type{ $types_to_go[$iend] } )
 
-            # reset the indentation to the new space count if it works
-            # only options are all or none: nothing in-between looks good
-            $lev = $level_beg;
+                # Alternate Patch for git #51, isolated closing qw token not
+                # outdented if no-delete-old-newlines is set. This works, but
+                # a more general patch elsewhere fixes the real problem: ljump.
+                # || ( $seqno_qw_closing && $ibeg == $i_terminal )
 
-            my $diff = $last_spaces - $space_count;
-            if ( $diff > 0 ) {
-                $indentation = $space_count;
+              )
+            {
+                $adjust_indentation = 1;
             }
-            else {
 
-                # We need to fix things ... but there is no good way to do it.
-                # The best solution is for the user to use a longer maximum
-                # line length.  We could get a smooth variation if we just move
-                # the paren in using
-                #    $space_count -= ( 1 - $diff );
-                # But unfortunately this can give a rather unbalanced look.
+            # outdent something like '),'
+            if (
+                $terminal_type eq ','
 
-                # For -xlp we currently allow a tolerance of one indentation
-                # level and then revert to a simpler default.  This will jump
-                # suddenly but keeps a balanced look.
-                if (   $rOpts_extended_line_up_parentheses
-                    && $diff >= -$rOpts_indent_columns
-                    && $space_count > $leading_spaces_beg )
-                {
-                    $indentation = $space_count;
-                }
+                # Removed this constraint for -wn
+                # OLD: allow just one character before the comma
+                # && $i_terminal == $ibeg + 1
 
-                # Otherwise revert to defaults
-                elsif ( $default_adjust_indentation == 0 ) {
-                    $indentation = $leading_spaces_beg;
-                }
-                elsif ( $default_adjust_indentation == 1 ) {
-                    $indentation = $reduced_spaces_to_go[$i_terminal];
-                    $lev         = $levels_to_go[$i_terminal];
-                }
+                # require LIST environment; otherwise, we may outdent too much -
+                # this can happen in calls without parentheses (overload.t);
+                && $terminal_is_in_list
+              )
+            {
+                $adjust_indentation = 1;
             }
-        }
-
-        # Full indentation of closing tokens (-icb and -icp or -cti=2)
-        else {
 
-            # handle -icb (indented closing code block braces)
-            # Updated method for indented block braces: indent one full level if
-            # there is no continuation indentation.  This will occur for major
-            # structures such as sub, if, else, but not for things like map
-            # blocks.
-            #
-            # Note: only code blocks without continuation indentation are
-            # handled here (if, else, unless, ..). In the following snippet,
-            # the terminal brace of the sort block will have continuation
-            # indentation as shown so it will not be handled by the coding
-            # here.  We would have to undo the continuation indentation to do
-            # this, but it probably looks ok as is.  This is a possible future
-            # update for semicolon terminated lines.
-            #
-            #     if ($sortby eq 'date' or $sortby eq 'size') {
-            #         @files = sort {
-            #             $file_data{$a}{$sortby} <=> $file_data{$b}{$sortby}
-            #                 or $a cmp $b
-            #                 } @files;
-            #         }
-            #
-            if (   $block_type_beg
-                && $ci_levels_to_go[$i_terminal] == 0 )
+            # undo continuation indentation of a terminal closing token if
+            # it is the last token before a level decrease.  This will allow
+            # a closing token to line up with its opening counterpart, and
+            # avoids an indentation jump larger than 1 level.
+            my $rLL    = $self->[_rLL_];
+            my $Klimit = $self->[_Klimit_];
+            if (   $i_terminal == $ibeg
+                && $is_closing_type_beg
+                && defined($K_beg)
+                && $K_beg < $Klimit )
             {
-                my $spaces = get_spaces( $leading_spaces_to_go[$i_terminal] );
-                $indentation = $spaces + $rOpts_indent_columns;
+                my $K_plus    = $K_beg + 1;
+                my $type_plus = $rLL->[$K_plus]->[_TYPE_];
 
-                # NOTE: for -lp we could create a new indentation object, but
-                # there is probably no need to do it
-            }
+                if ( $type_plus eq 'b' && $K_plus < $Klimit ) {
+                    $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
+                }
 
-            # handle -icp and any -icb block braces which fall through above
-            # test such as the 'sort' block mentioned above.
-            else {
+                if ( $type_plus eq '#' && $K_plus < $Klimit ) {
+                    $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
+                    if ( $type_plus eq 'b' && $K_plus < $Klimit ) {
+                        $type_plus = $rLL->[ ++$K_plus ]->[_TYPE_];
+                    }
+
+                    # Note: we have skipped past just one comment (perhaps a
+                    # side comment).  There could be more, and we could easily
+                    # skip past all the rest with the following code, or with a
+                    # while loop.  It would be rare to have to do this, and
+                    # those block comments would still be indented, so it would
+                    # to leave them indented.  So it seems best to just stop at
+                    # a maximum of one comment.
+                    ##if ($type_plus eq '#') {
+                    ##   $K_plus = $self->K_next_code($K_plus);
+                    ##}
+                }
 
-                # There are currently two ways to handle -icp...
-                # One way is to use the indentation of the previous line:
-                # $indentation = $last_indentation_written;
+                if ( !$is_bli_beg && defined($K_plus) ) {
+                    my $lev        = $level_beg;
+                    my $level_next = $rLL->[$K_plus]->[_LEVEL_];
 
-                # The other way is to use the indentation that the previous line
-                # would have had if it hadn't been adjusted:
-                $indentation = $last_unadjusted_indentation;
+                    # and do not undo ci if it was set by the -xci option
+                    $adjust_indentation = 1
+                      if ( $level_next < $lev
+                        && !$self->[_rseqno_controlling_my_ci_]->{$K_beg} );
+                }
 
-                # Current method: use the minimum of the two. This avoids
-                # inconsistent indentation.
-                if ( get_spaces($last_indentation_written) <
-                    get_spaces($indentation) )
+                # Patch for RT #96101, in which closing brace of anonymous subs
+                # was not outdented.  We should look ahead and see if there is
+                # a level decrease at the next token (i.e., a closing token),
+                # but right now we do not have that information.  For now
+                # we see if we are in a list, and this works well.
+                # See test files 'sub*.t' for good test cases.
+                if (   $terminal_is_in_list
+                    && !$rOpts_indent_closing_brace
+                    && $block_type_beg
+                    && $block_type_beg =~ /$ASUB_PATTERN/ )
                 {
-                    $indentation = $last_indentation_written;
+                    (
+                        $opening_indentation, $opening_offset,
+                        $is_leading,          $opening_exists
+                      )
+                      = $self->get_opening_indentation( $ibeg, $ri_first,
+                        $ri_last, $rindentation_list );
+                    my $indentation = $leading_spaces_beg;
+                    if ( defined($opening_indentation)
+                        && get_spaces($indentation) >
+                        get_spaces($opening_indentation) )
+                    {
+                        $adjust_indentation = 1;
+                    }
                 }
             }
 
-            # use previous indentation but use own level
-            # to cause list to be flushed properly
-            $lev = $level_beg;
-        }
-
-        # remember indentation except for multi-line quotes, which get
-        # no indentation
-        unless ( $ibeg == 0 && $starting_in_quote ) {
-            $last_indentation_written    = $indentation;
-            $last_unadjusted_indentation = $leading_spaces_beg;
-            $last_leading_token          = $token_beg;
-
-            # Patch to make a line which is the end of a qw quote work with the
-            # -lp option.  Make $token_beg look like a closing token as some
-            # type even if it is not.  This variable will become
-            # $last_leading_token at the end of this loop.  Then, if the -lp
-            # style is selected, and the next line is also a
-            # closing token, it will not get more indentation than this line.
-            # We need to do this because qw quotes (at present) only get
-            # continuation indentation, not one level of indentation, so we
-            # need to turn off the -lp indentation.
-
-            # ... a picture is worth a thousand words:
-
-            # perltidy -wn -gnu (Without this patch):
-            #   ok(defined(
-            #       $seqio = $gb->get_Stream_by_batch([qw(J00522 AF303112
-            #       2981014)])
-            #             ));
-
-            # perltidy -wn -gnu (With this patch):
-            #  ok(defined(
-            #      $seqio = $gb->get_Stream_by_batch([qw(J00522 AF303112
-            #      2981014)])
-            #  ));
-            if ( $seqno_qw_closing
-                && ( length($token_beg) > 1 || $token_beg eq '>' ) )
+            # YVES patch 1 of 2:
+            # Undo ci of line with leading closing eval brace,
+            # but not beyond the indentation of the line with
+            # the opening brace.
+            if (   $block_type_beg eq 'eval'
+                && !ref($leading_spaces_beg)
+                && !$rOpts_indent_closing_brace )
             {
-                $last_leading_token = ')';
+                (
+                    $opening_indentation, $opening_offset,
+                    $is_leading,          $opening_exists
+                  )
+                  = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
+                    $rindentation_list );
+                my $indentation = $leading_spaces_beg;
+                if ( defined($opening_indentation)
+                    && get_spaces($indentation) >
+                    get_spaces($opening_indentation) )
+                {
+                    $adjust_indentation = 1;
+                }
             }
-        }
 
-        # be sure lines with leading closing tokens are not outdented more
-        # than the line which contained the corresponding opening token.
+            # patch for issue git #40: -bli setting has priority
+            $adjust_indentation = 0 if ($is_bli_beg);
 
-        #--------------------------------------------------------
-        # updated per bug report in alex_bug.pl: we must not
-        # mess with the indentation of closing logical braces so
-        # we must treat something like '} else {' as if it were
-        # an isolated brace
-        #--------------------------------------------------------
-        my $is_isolated_block_brace = $block_type_beg
-          && ( $i_terminal == $ibeg
-            || $is_if_elsif_else_unless_while_until_for_foreach{$block_type_beg}
-          );
+            $default_adjust_indentation = $adjust_indentation;
 
-        # only do this for a ':; which is aligned with its leading '?'
-        my $is_unaligned_colon = $type_beg eq ':' && !$is_leading;
+            # Now modify default behavior according to user request:
+            # handle option to indent non-blocks of the form );  };  ];
+            # But don't do special indentation to something like ')->pack('
+            if ( !$block_type_beg ) {
 
-        if (
-            defined($opening_indentation)
-            && !$leading_paren_arrow    # MOJO patch
-            && !$is_isolated_block_brace
-            && !$is_unaligned_colon
-          )
-        {
-            if ( get_spaces($opening_indentation) > get_spaces($indentation) ) {
-                $indentation = $opening_indentation;
-            }
-        }
+                # Note that logical padding has already been applied, so we may
+                # need to remove some spaces to get a valid hash key.
+                my $tok = $token_beg;
+                my $cti = $closing_token_indentation{$tok};
 
-        # remember the indentation of each line of this batch
-        push @{$rindentation_list}, $indentation;
+                # Fix the value of 'cti' for an isolated non-welded closing qw
+                # delimiter.
+                if ( $seqno_qw_closing && $ibeg_weld_fix == $ibeg ) {
 
-        # outdent lines with certain leading tokens...
-        if (
+                    # A quote delimiter which is not a container will not have
+                    # a cti value defined.  In this case use the style of a
+                    # paren. For example
+                    #   my @fars = (
+                    #      qw<
+                    #        far
+                    #        farfar
+                    #        farfars-far
+                    #      >,
+                    #   );
+                    if ( !defined($cti) && length($tok) == 1 ) {
 
-            # must be first word of this batch
-            $ibeg == 0
+                        # something other than ')', '}', ']' ; use flag for ')'
+                        $cti = $closing_token_indentation{')'};
 
-            # and ...
-            && (
+                        # But for now, do not outdent non-container qw
+                        # delimiters because it would would change existing
+                        # formatting.
+                        if ( $tok ne '>' ) { $cti = 3 }
+                    }
 
-                # certain leading keywords if requested
-                $rOpts_outdent_keywords
-                && $type_beg eq 'k'
-                && $outdent_keyword{$token_beg}
+                    # A non-welded closing qw cannot currently use -cti=1
+                    # because that option requires a sequence number to find
+                    # the opening indentation, and qw quote delimiters are not
+                    # sequenced items.
+                    if ( defined($cti) && $cti == 1 ) { $cti = 0 }
+                }
 
-                # or labels if requested
-                || $rOpts_outdent_labels && $type_beg eq 'J'
+                if ( !defined($cti) ) {
 
-                # or static block comments if requested
-                || $is_static_block_comment
-                && $rOpts_outdent_static_block_comments
-            )
-          )
-        {
-            my $space_count = leading_spaces_to_go($ibeg);
-            if ( $space_count > 0 ) {
-                $space_count -= $rOpts_continuation_indentation;
-                $is_outdented_line = 1;
-                if ( $space_count < 0 ) { $space_count = 0 }
+                    # $cti may not be defined for several reasons.
+                    # -padding may have been applied so the character
+                    #  has a length > 1
+                    # - we may have welded to a closing quote token.
+                    #   Here is an example (perltidy -wn):
+                    #       __PACKAGE__->load_components( qw(
+                    #  >         Core
+                    #  >
+                    #  >     ) );
+                    $adjust_indentation = 0;
 
-                # do not promote a spaced static block comment to non-spaced;
-                # this is not normally necessary but could be for some
-                # unusual user inputs (such as -ci = -i)
-                if ( $type_beg eq '#' && $space_count == 0 ) {
-                    $space_count = 1;
                 }
+                elsif ( $cti == 1 ) {
+                    if (   $i_terminal <= $ibeg + 1
+                        || $is_semicolon_terminated )
+                    {
+                        $adjust_indentation = 2;
+                    }
+                    else {
+                        $adjust_indentation = 0;
+                    }
+                }
+                elsif ( $cti == 2 ) {
+                    if ($is_semicolon_terminated) {
+                        $adjust_indentation = 3;
+                    }
+                    else {
+                        $adjust_indentation = 0;
+                    }
+                }
+                elsif ( $cti == 3 ) {
+                    $adjust_indentation = 3;
+                }
+            }
 
-                $indentation = $space_count;
+            # handle option to indent blocks
+            else {
+                if (
+                    $rOpts_indent_closing_brace
+                    && (
+                        $i_terminal == $ibeg    #  isolated terminal '}'
+                        || $is_semicolon_terminated
+                    )
+                  )                             #  } xxxx ;
+                {
+                    $adjust_indentation = 3;
+                }
             }
+        } ## end if ( $is_closing_type_beg || $seqno_qw_closing )
+
+        # if line begins with a ':', align it with any
+        # previous line leading with corresponding ?
+        elsif ( $type_beg eq ':' ) {
+            (
+                $opening_indentation, $opening_offset,
+                $is_leading,          $opening_exists
+              )
+              = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
+                $rindentation_list );
+            if ($is_leading) { $adjust_indentation = 2; }
         }
 
-        return ( $indentation, $lev, $level_end, $i_terminal,
-            $is_outdented_line );
-    } ## end sub get_final_indentation
+        return ( $adjust_indentation, $default_adjust_indentation,
+            $opening_indentation, $opening_offset,
+            $is_leading,          $opening_exists );
+    }
+
 } ## end closure get_final_indentation
 
 sub get_opening_indentation {