comments will remain aligned and be outdented by the same amount. This coordinated
alignment will not occur if B<-nvbc> is set. The default is B<-vbc>.
+=item B<Finer alignment control with --valign-exclusion-list=s or -vxl=s and --valign-inclusion-list=s or -vil=s>
+
+More detailed control of alignment types is available with these two parameters.
+Most of the alignments in typical programs occur at one of the tokens ',' '=',
+and '=>', but many others are possible. The complete list of token types where
+vertical alignment can occur is:
+
+ = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=
+ { ( ? : , ; => && || ~~ !~~ =~ !~ // <=> ->
+ if unless and or err for foreach while until
+
+These alignments are all enabled by default, but they can be selectively disabled by including one or more of these tokens in the list B<valign-exclusion-list=s>. For example, the following would prevent alignment at B<=> and B<if>:
+
+ --valign-exclusion-list='= if'
+
+If it is simpler to specify only the token types which are to be aligned, use the special symbol B<*> for this list and include the types which are to be aligned in the list of B<--valign-inclusion-list>. For example,
+the following parameters enable alignment only at commas and 'fat commas':
+
+ --valign-exclusion-list='*'
+ --valign-inclusion-list=', =>'
+
+These parameter lists should consist of space-separated tokens from the above
+list of possible alignment tokens. If an unrecognized parameter appears, it is
+simply ignored. And if a parameter is entered in both lists (it should
+not), then the exclusion list has priority.
+
+Note that control of side comment alignment is not done with these parameters but
+rather with the B<--valign-side_comments> listed above.
+
=back
=head2 Other Controls
Perl::Tidy::Formatter::check_options($rOpts);
Perl::Tidy::Tokenizer::check_options($rOpts);
+ Perl::Tidy::VerticalAligner::check_options($rOpts);
if ( $rOpts->{'format'} eq 'html' ) {
Perl::Tidy::HtmlWriter->check_options($rOpts);
}
$add_option->( 'valign-code', 'vc', '!' );
$add_option->( 'valign-block-comments', 'vbc', '!' );
$add_option->( 'valign-side-comments', 'vsc', '!' );
+ $add_option->( 'valign-exclusion-list', 'vxl', '=s' );
+ $add_option->( 'valign-inclusion-list', 'vil', '=s' );
########################################
$category = 4; # Comment controls
};
DEBUG_TABS && $debug_warning->('TABS');
+}
+
+# GLOBAL variables
+my (
+
+ %valign_control_hash,
+ $valign_control_default,
+
+);
+
+sub check_options {
+
+ # This routine is called to check the user-supplied run parameters
+ # and to configure the control hashes to them.
+ my ($rOpts) = @_;
+
+ %valign_control_hash = ();
+ $valign_control_default = 1;
+
+ if ( $rOpts->{'valign-inclusion-list'} ) {
+ my @list = split /\s+/, $rOpts->{'valign-inclusion-list'};
+ @valign_control_hash{@list} = (1) x scalar(@list);
+ }
+ # Note that the -vxl list is done after -vil, so -vxl has priority
+ # in the event of duplicate entries.
+ if ( $rOpts->{'valign-exclusion-list'} ) {
+ my @list = split /\s+/, $rOpts->{'valign-exclusion-list'};
+ @valign_control_hash{@list} = (0) x scalar(@list);
+ }
+
+ # '$valign_control_default' applies to types not in the hash:
+ # - If a '*' was entered then set it to be that default type
+ # - Otherwise, leave it set it to 1
+ if ( defined( $valign_control_hash{'*'} ) ) {
+ $valign_control_default = $valign_control_hash{'*'};
+ }
+
+ # Side comments are controlled separately and must be removed if specified
+ if ( defined( $valign_control_hash{'#'} ) ) {
+ delete $valign_control_hash{'#'};
+ }
+
+ return;
}
sub new {
my $rfield_lengths = $new_line->get_rfield_lengths();
my $padding_available = $old_line->get_available_space_on_right();
my $jmax_old = $old_line->get_jmax();
+ my $rtokens_old = $old_line->get_rtokens();
# Safety check ... only lines with equal array sizes should arrive here
# from sub check_match. So if this error occurs, look at recent changes in
$pad += $leading_space_count;
}
- # Keep going if this field does not need any space.
- next if $pad < 0;
+ # Give up if not enough space is available
+ my $revert = $pad > $padding_available;
+
+ # Apply any user-defined vertical alignment controls in top-down sweep
+ if ( !$revert
+ && $j < $jmax
+ && %valign_control_hash )
+ {
- # See if it needs too much space.
- if ( $pad > $padding_available ) {
+ # FIXME: This call is a little inefficient; need to do profiling
+ # to see if it should be avoided.
+ my $tok = $rtokens_old->[$j];
+ my ( $raw_tok, $lev, $tag, $tok_count ) =
+ decode_alignment_token($tok);
+
+ my $align_ok = $valign_control_hash{$raw_tok};
+ $align_ok = $valign_control_default unless defined($align_ok);
+
+ if ( !$align_ok && $pad != 0 ) {
+ $revert = 1;
+ }
+ }
+
+ # Revert to the starting state if does not fit
+ if ($revert) {
################################################
# Line does not fit -- revert to starting state
return;
}
+ # Keep going if this field does not need any space.
+ next if ( $pad < 0 );
+
# make room for this field
$old_line->increase_field_width( $j, $pad );
$padding_available -= $pad;
&& $col > $col_want + $short_pad * $factor;
}
+ # Apply user-defined vertical alignment controls in l-r sweep
+ if ( !$is_big_gap && %valign_control_hash ) {
+
+ my $align_ok = $valign_control_hash{$raw_tok};
+ $align_ok = $valign_control_default
+ unless defined($align_ok);
+
+ # Note that the following definition of $pad is not the
+ # total pad because we are working at group boundaries. But
+ # we can still see if it is zero or not.
+ if ( !$align_ok && $col_want != $col ) {
+ $is_big_gap = 1;
+ }
+ }
+
# if match is limited by gap size, stop aligning at this level
if ($is_big_gap) {
$blocking_level[$ng] = $lev - 1;