2 ###########################################################
4 # perltidy - a perl script indenter and formatter
6 # Copyright (c) 2000-2025 by Steve Hancock
7 # Distributed under the GPL license agreement; see file COPYING
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License along
20 # with this program; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 # For brief instructions, try 'perltidy -h'.
24 # For more complete documentation, try 'man perltidy'
25 # or visit the GitHub site https://perltidy.github.io/perltidy/
27 # This script is an example of the default style. It was formatted with:
31 # Code Contributions: See ChangeLog.html for a complete history.
32 # Michael Cartmell supplied code for adaptation to VMS and helped with
34 # Hugh S. Myers supplied sub streamhandle and the supporting code to
35 # create a Perl::Tidy module which can operate on strings, arrays, etc.
36 # Yves Orton supplied coding to help detect Windows versions.
37 # Axel Rose supplied a patch for MacPerl.
38 # Sebastien Aperghis-Tramoni supplied a patch for the defined or operator.
39 # Dan Tyrell contributed a patch for binary I/O.
40 # Ueli Hugenschmidt contributed a patch for -fpsc
41 # Sam Kington supplied a patch to identify the initial indentation of
43 # jonathan swartz supplied patches for:
44 # * .../ pattern, which looks upwards from directory
45 # * --notidy, to be used in directories where we want to avoid
46 # accidentally tidying
47 # * prefilter and postfilter
50 # Many others have supplied key ideas, suggestions, and bug reports;
51 # see the CHANGES file.
53 ############################################################
57 # perlver reports minimum version needed is 5.8.1
58 # 5.004 needed for IO::File
59 # 5.008 needed for wide characters
60 # 5.008001 needed for utf8::is_utf8
61 # 5.008001 needed for Scalar::Util::refaddr
67 use English qw( -no_match_vars );
68 use Digest::MD5 qw(md5_hex);
69 use Perl::Tidy::Debugger;
70 use Perl::Tidy::Diagnostics;
71 use Perl::Tidy::FileWriter;
72 use Perl::Tidy::Formatter;
73 use Perl::Tidy::HtmlWriter;
74 use Perl::Tidy::IOScalar;
75 use Perl::Tidy::IOScalarArray;
76 use Perl::Tidy::IndentationItem;
77 use Perl::Tidy::Logger;
78 use Perl::Tidy::Tokenizer;
79 use Perl::Tidy::VerticalAligner;
80 local $OUTPUT_AUTOFLUSH = 1;
82 # DEVEL_MODE can be turned on for extra checking during development
83 use constant DEVEL_MODE => 0;
84 use constant DIAGNOSTICS => 0;
85 use constant EMPTY_STRING => q{};
86 use constant SPACE => q{ };
87 use constant CONST_1024 => 1024; # bytes per kb; 2**10
95 @ISA = qw( Exporter );
96 @EXPORT = qw( &perltidy );
106 # perl stat function index names, based on
107 # https://perldoc.perl.org/functions/stat
110 _mode_ => 2, # file mode (type and permissions)
111 _uid_ => 4, # numeric user ID of file's owner
112 _gid_ => 5, # numeric group ID of file's owner
113 _atime_ => 8, # last access time in seconds since the epoch
114 _mtime_ => 9, # last modify time in seconds since the epoch
116 ## _dev_ => 0, # device number of filesystem
117 ## _ino_ => 1, # inode number
118 ## _nlink_ => 3, # number of (hard) links to the file
119 ## _rdev_ => 6, # the device identifier (special files only)
120 ## _size_ => 7, # total size of file, in bytes
121 ## _ctime_ => 10, # inode change time in seconds since the epoch (*)
122 ## _blksize_ => 11, # preferred I/O size in bytes for interacting with
123 ## # the file (may vary from file to file)
124 ## _blocks_ => 12, # actual number of system-specific blocks allocated
125 ## # on disk (often, but not always, 512 bytes each)
130 # Release version is the approximate YYYYMMDD of the release.
131 # Development version is (Last Release).(Development Number)
133 # To make the number continually increasing, the Development Number is a 2
134 # digit number starting at 01 after a release. It is continually bumped
135 # along at significant points during development. If it ever reaches 99
136 # then the Release version must be bumped, and it is probably past time for
139 $VERSION = '20250105';
145 # required to avoid call to AUTOLOAD in some versions of perl
151 # Catch any undefined sub calls so that we are sure to get
152 # some diagnostic information. This sub should never be called
153 # except for a programming error.
155 return if ( $AUTOLOAD =~ /\bDESTROY$/ );
156 my ( $pkg, $fname, $lno ) = caller();
157 print {*STDERR} <<EOM;
158 ======================================================================
159 Unexpected call to Autoload looking for sub $AUTOLOAD
160 Called from package: '$pkg'
161 Called from File '$fname' at line '$lno'
162 This error is probably due to a recent programming change
163 ======================================================================
166 } ## end sub AUTOLOAD
170 my ( $filename, $mode, ($is_encoded_data) ) = @_;
174 # $mode = 'r' or 'w' (only 'w' is used now, see note below)
175 # $is_encoded_data (optional flag)
177 # Create an object which:
178 # has a 'getline' method if mode='r', and
179 # has a 'print' method if mode='w'.
180 # The objects also need a 'close' method.
182 # How the object is made:
184 # if $filename is: Make object using:
185 # ---------------- -----------------
186 # '-' (STDIN if mode = 'r', STDOUT if mode='w')
188 # ARRAY ref Perl::Tidy::IOScalarArray (formerly IO::ScalarArray)
189 # STRING ref Perl::Tidy::IOScalar (formerly IO::Scalar)
191 # (check for 'print' method for 'w' mode)
192 # (check for 'getline' method for 'r' mode)
194 # An optional flag '$is_encoded_data' may be given, as follows:
195 # - true: encoded data is being transferred,
196 # set encoding to be utf8 for files and for stdin.
197 # - false: unencoded binary data is being transferred,
198 # set binary mode for files and for stdin.
200 # NOTE: mode 'r' works but is no longer used.
201 # Use sub stream_slurp instead for mode 'r', for efficiency.
203 if ( $mode ne 'w' ) {
204 if ( DEVEL_MODE || $mode ne 'r' ) {
205 Fault("streamhandle called in unexpected mode '$mode'\n");
209 my $ref = ref($filename);
217 if ( $ref eq 'ARRAY' ) {
218 $New = sub { Perl::Tidy::IOScalarArray->new( $filename, $mode ) };
220 elsif ( $ref eq 'SCALAR' ) {
221 $New = sub { Perl::Tidy::IOScalar->new( $filename, $mode ) };
225 # Accept an object with a getline method for reading. Note:
226 # IO::File is built-in and does not respond to the defined
227 # operator. If this causes trouble, the check can be
228 # skipped and we can just let it crash if there is no
230 if ( $mode eq 'r' ) {
232 # RT#97159; part 1 of 2: updated to use 'can'
233 if ( $ref->can('getline') ) {
234 $New = sub { $filename };
237 $New = sub { undef };
239 ------------------------------------------------------------------------
240 No 'getline' method is defined for object of class '$ref'
241 Please check your call to Perl::Tidy::perltidy. Trace follows.
242 ------------------------------------------------------------------------
247 # Accept an object with a print method for writing.
248 # See note above about IO::File
249 if ( $mode eq 'w' ) {
251 # RT#97159; part 2 of 2: updated to use 'can'
252 if ( $ref->can('print') ) {
253 $New = sub { $filename };
256 $New = sub { undef };
258 ------------------------------------------------------------------------
259 No 'print' method is defined for object of class '$ref'
260 Please check your call to Perl::Tidy::perltidy. Trace follows.
261 ------------------------------------------------------------------------
272 if ( $filename eq '-' ) {
273 $New = sub { $mode eq 'w' ? *STDOUT : *STDIN }
276 $New = sub { IO::File->new( $filename, $mode ) };
283 $fh = $New->( $filename, $mode );
286 Warn("Couldn't open file:'$filename' in mode:$mode : $OS_ERROR\n");
293 if ( ref($fh) eq 'IO::File' ) {
294 ## binmode object call not available in older perl versions
295 ## $fh->binmode(":raw:encoding(UTF-8)");
296 if ($is_encoded_data) { binmode $fh, ":raw:encoding(UTF-8)"; }
299 elsif ( $filename eq '-' ) {
300 if ($is_encoded_data) { binmode STDOUT, ":raw:encoding(UTF-8)"; }
301 else { binmode STDOUT }
307 my $ref_fh = ref($fh);
309 unexpected streamhandle state for file='$filename' mode='$mode' ref(fh)=$ref_fh
316 } ## end sub streamhandle
320 my ( $filename, ($timeout_in_seconds) ) = @_;
324 # $timeout_in_seconds (optional timeout, in seconds)
326 # Read the text in $filename and
328 # undef if read error, or
329 # $rinput_string = ref to string of text
331 # if $filename is: Read
332 # ---------------- -----------------
333 # ARRAY ref array ref
334 # SCALAR ref string ref
335 # object ref object with 'getline' method (exit if no 'getline')
337 # string file named $filename
339 # Note that any decoding from utf8 must be done by the caller
341 my $ref = ref($filename);
346 if ( $ref eq 'ARRAY' ) {
347 my $buf = join EMPTY_STRING, @{$filename};
348 $rinput_string = \$buf;
350 elsif ( $ref eq 'SCALAR' ) {
351 $rinput_string = $filename;
354 if ( $ref->can('getline') ) {
355 my $buf = EMPTY_STRING;
356 while ( defined( my $line = $filename->getline() ) ) {
359 $rinput_string = \$buf;
363 ------------------------------------------------------------------------
364 No 'getline' method is defined for object of class '$ref'
365 Please check your call to Perl::Tidy::perltidy. Trace follows.
366 ------------------------------------------------------------------------
374 if ( $filename eq '-' ) {
375 local $INPUT_RECORD_SEPARATOR = undef;
377 if ( $timeout_in_seconds && $timeout_in_seconds > 0 ) {
379 local $SIG{ALRM} = sub { die "alarm\n" };
380 alarm($timeout_in_seconds);
386 "Timeout reading stdin using -tos=$timeout_in_seconds seconds. Use -tos=0 to skip timeout check.\n"
392 $rinput_string = \$buf;
395 if ( open( my $fh, '<', $filename ) ) {
396 local $INPUT_RECORD_SEPARATOR = undef;
398 $fh->close() or Warn("Cannot close $filename\n");
399 $rinput_string = \$buf;
402 Warn("Cannot open $filename: $OS_ERROR\n");
408 return $rinput_string;
409 } ## end sub stream_slurp
411 # Here is a map of the flow of data from the input source to the output
414 # -->Tokenizer-->Formatter-->VerticalAligner-->FileWriter-->
415 # input groups output
416 # lines tokens lines of lines lines
419 # The names correspond to the package names responsible for the unit processes.
421 # The overall process is controlled by the "main" package.
423 # Tokenizer analyzes a line and breaks it into tokens, peeking ahead
424 # if necessary. A token is any section of the input line which should be
425 # manipulated as a single entity during formatting. For example, a single
426 # ',' character is a token, and so is an entire side comment. It handles
427 # the complexities of Perl syntax, such as distinguishing between '<<' as
428 # a shift operator and as a here-document, or distinguishing between '/'
429 # as a divide symbol and as a pattern delimiter.
431 # Formatter inserts and deletes whitespace between tokens, and breaks
432 # sequences of tokens at appropriate points as output lines. It bases its
433 # decisions on the default rules as modified by any command-line options.
435 # VerticalAligner collects groups of lines together and tries to line up
436 # certain tokens, such as '=>', '#', and '=' by adding whitespace.
438 # FileWriter simply writes lines to the output stream.
440 # The Logger package, not shown, records significant events and warning
441 # messages. It writes a .LOG file, which may be saved with a
442 # '-log' or a '-g' flag.
444 { #<<< (this side comment avoids excessive indentation in a closure)
448 my $loaded_unicode_gcstring;
451 # Bump Warn_count only: it is essential to bump the count on all warnings, even
452 # if no message goes out, so that the correct exit status is set.
453 sub Warn_count_bump { $Warn_count++; return }
455 # Output Warn message only
456 sub Warn_msg { my $msg = shift; $fh_stderr->print($msg); return }
458 # Output Warn message and bump Warn count
459 sub Warn { my $msg = shift; $fh_stderr->print($msg); $Warn_count++; return }
466 # true if $string is in Perl's internal character mode
467 # (also called the 'upgraded form', or UTF8=1)
468 # false if $string is in Perl's internal byte mode
470 # This function isolates the call to Perl's internal function
471 # utf8::is_utf8() which is true for strings represented in an 'upgraded
472 # form'. It is available AFTER Perl version 5.8.
473 # See https://perldoc.perl.org/Encode.
474 # See also comments in Carp.pm and other modules using this function
476 return 1 if ( utf8::is_utf8($string) );
478 } ## end sub is_char_mode
483 # Evaluate the MD5 sum for a string:
487 # $digest = its MD5 sum
489 # Patch for [rt.cpan.org #88020]
490 # Use utf8::encode since md5_hex() only operates on bytes.
491 # my $digest = md5_hex( utf8::encode($sink_buffer) );
493 # Note added 20180114: the above patch did not work correctly. I'm not
494 # sure why. But switching to the method recommended in the Perl 5
495 # documentation for Encode worked. According to this we can either use
496 # $octets = encode_utf8($string) or equivalently
497 # $octets = encode("utf8",$string)
498 # and then calculate the checksum. So:
499 my $octets = Encode::encode( "utf8", $buf );
500 my $digest = md5_hex($octets);
502 }; ## end $md5_hex = sub
504 sub get_iteration_count {
505 return $rstatus->{iteration_count};
510 # Array index names for $self.
511 # Do not combine with other BEGIN blocks (c101).
514 _actual_output_extension_ => $i++,
515 _debugfile_stream_ => $i++,
516 _decoded_input_as_ => $i++,
517 _destination_stream_ => $i++,
518 _diagnostics_object_ => $i++,
519 _display_name_ => $i++,
520 _file_extension_separator_ => $i++,
522 _is_encoded_data_ => $i++,
523 _length_function_ => $i++,
524 _line_separator_default_ => $i++,
525 _line_separator_ => $i++,
526 _line_tidy_begin_ => $i++,
527 _line_tidy_end_ => $i++,
528 _logger_object_ => $i++,
529 _output_file_ => $i++,
530 _postfilter_ => $i++,
534 _teefile_stream_ => $i++,
535 _user_formatter_ => $i++,
536 _input_copied_verbatim_ => $i++,
537 _input_output_difference_ => $i++,
538 _dump_to_stdout_ => $i++,
546 # This is the main perltidy routine
550 destination => undef,
559 dump_options => undef,
560 dump_options_type => undef,
561 dump_getopt_flags => undef,
562 dump_options_category => undef,
563 dump_options_range => undef,
564 dump_abbreviations => undef,
569 # Status information which can be returned for diagnostic purposes.
570 # NOTE: This is intended only for testing and subject to change.
572 # List of "key => value" hash entries:
574 # Some relevant user input parameters for convenience:
575 # opt_format => value of --format: 'tidy', 'html', or 'user'
576 # opt_encoding => value of -enc flag: 'utf8', 'none', or 'guess'
577 # opt_encode_output => value of -eos flag: 'eos' or 'neos'
578 # opt_max_iterations => value of --iterations=n
580 # file_count => number of files processed in this call
582 # If multiple files are processed, then the following values will be for
583 # the last file only:
585 # input_name => name of the input stream
586 # output_name => name of the output stream
588 # The following two variables refer to Perl's two internal string modes,
589 # and have the values 0 for 'byte' mode and 1 for 'char' mode:
590 # char_mode_source => true if source is in 'char' mode. Will be false
591 # unless we received a source string ref with utf8::is_utf8() set.
592 # char_mode_used => true if text processed by perltidy in 'char' mode.
593 # Normally true for text identified as utf8, otherwise false.
595 # This tells if Unicode::GCString was used
596 # gcs_used => true if -gcs and Unicode::GCString found & used
598 # These variables tell what utf8 decoding/encoding was done:
599 # input_decoded_as => non-blank if perltidy decoded the source text
600 # output_encoded_as => non-blank if perltidy encoded before return
602 # These variables are related to iterations and convergence testing:
603 # iteration_count => number of iterations done
604 # ( can be from 1 to opt_max_iterations )
605 # converged => true if stopped on convergence
606 # ( can only happen if opt_max_iterations > 1 )
607 # blinking => true if stopped on blinking states
608 # ( i.e., unstable formatting, should not happen )
613 opt_format => EMPTY_STRING,
614 opt_encoding => EMPTY_STRING,
615 opt_encode_output => EMPTY_STRING,
616 opt_max_iterations => EMPTY_STRING,
618 input_name => EMPTY_STRING,
619 output_name => EMPTY_STRING,
620 char_mode_source => 0,
622 input_decoded_as => EMPTY_STRING,
623 output_encoded_as => EMPTY_STRING,
625 iteration_count => 0,
630 # Fix for issue git #57
633 # don't overwrite callers ARGV
634 # Localization of @ARGV could be avoided by calling GetOptionsFromArray
635 # instead of GetOptions, but that is not available before perl 5.10
637 local *STDERR = *STDERR;
639 if ( my @bad_keys = grep { !exists $defaults{$_} } keys %input_hash ) {
640 local $LIST_SEPARATOR = ')(';
641 my @good_keys = sort keys %defaults;
642 @bad_keys = sort @bad_keys;
644 ------------------------------------------------------------------------
645 Unknown perltidy parameter : (@bad_keys)
646 perltidy only understands : (@good_keys)
647 ------------------------------------------------------------------------
652 my $get_hash_ref = sub {
654 my $hash_ref = $input_hash{$key};
655 if ( defined($hash_ref) ) {
656 if ( ref($hash_ref) ne 'HASH' ) {
657 my $what = ref($hash_ref);
659 $what ? "but is ref to $what" : "but is not a reference";
661 ------------------------------------------------------------------------
662 error in call to perltidy:
663 -$key must be reference to HASH $but_is
664 ------------------------------------------------------------------------
669 }; ## end $get_hash_ref = sub
671 %input_hash = ( %defaults, %input_hash );
672 my $argv = $input_hash{'argv'};
673 my $destination_stream = $input_hash{'destination'};
674 my $perltidyrc_stream = $input_hash{'perltidyrc'};
675 my $source_stream = $input_hash{'source'};
676 my $stderr_stream = $input_hash{'stderr'};
677 my $user_formatter = $input_hash{'formatter'};
678 my $prefilter = $input_hash{'prefilter'};
679 my $postfilter = $input_hash{'postfilter'};
681 if ($stderr_stream) {
682 $fh_stderr = Perl::Tidy::streamhandle( $stderr_stream, 'w' );
685 ------------------------------------------------------------------------
686 Unable to redirect STDERR to $stderr_stream
687 Please check value of -stderr in call to perltidy
688 ------------------------------------------------------------------------
693 $fh_stderr = *STDERR;
697 bless $self, __PACKAGE__;
701 if ($flag) { goto ERROR_EXIT }
702 else { goto NORMAL_EXIT }
703 croak "unexpected return to sub Exit";
710 croak "unexpected return from sub Exit";
716 # This routine is called for errors that really should not occur
717 # except if there has been a bug introduced by a recent program change.
718 # Please add comments at calls to Fault to explain why the call
719 # should not occur, and where to look to fix it.
720 my ( $package0_uu, $filename0_uu, $line0, $subroutine0_uu ) = caller(0);
721 my ( $package1_uu, $filename1, $line1, $subroutine1 ) = caller(1);
722 my ( $package2_uu, $filename2_uu, $line2_uu, $subroutine2 ) = caller(2);
723 my $pkg = __PACKAGE__;
725 my $input_stream_name = $rstatus->{'input_name'};
726 $input_stream_name = '(unknown)' unless ($input_stream_name);
728 ==============================================================================
729 While operating on input stream with name: '$input_stream_name'
730 A fault was detected at line $line0 of sub '$subroutine1'
732 which was called from line $line1 of sub '$subroutine2'
734 This is probably an error introduced by a recent programming change.
735 $pkg reports VERSION='$VERSION'.
736 ==============================================================================
739 croak "unexpected return from sub Die";
742 # extract various dump parameters
743 my $dump_options_type = $input_hash{'dump_options_type'};
744 my $dump_options = $get_hash_ref->('dump_options');
745 my $dump_getopt_flags = $get_hash_ref->('dump_getopt_flags');
746 my $dump_options_category = $get_hash_ref->('dump_options_category');
747 my $dump_abbreviations = $get_hash_ref->('dump_abbreviations');
748 my $dump_options_range = $get_hash_ref->('dump_options_range');
750 # validate dump_options_type
751 if ( defined($dump_options) ) {
752 if ( !defined($dump_options_type) ) {
753 $dump_options_type = 'perltidyrc';
755 if ( $dump_options_type ne 'perltidyrc'
756 && $dump_options_type ne 'full' )
759 ------------------------------------------------------------------------
760 Please check value of -dump_options_type in call to perltidy;
761 saw: '$dump_options_type'
762 expecting: 'perltidyrc' or 'full'
763 ------------------------------------------------------------------------
769 $dump_options_type = EMPTY_STRING;
772 if ($user_formatter) {
774 # if the user defines a formatter, there is no output stream,
775 # but we need a null stream to keep coding simple
776 $destination_stream = \my $tmp;
779 # see if ARGV is overridden
780 if ( defined($argv) ) {
782 my $rargv = ref($argv);
783 if ( $rargv eq 'SCALAR' ) { $argv = ${$argv}; $rargv = undef }
787 if ( $rargv eq 'ARRAY' ) {
792 ------------------------------------------------------------------------
793 Please check value of -argv in call to perltidy;
794 it must be a string or ref to ARRAY but is: $rargv
795 ------------------------------------------------------------------------
802 my ( $rargv_str, $msg ) = parse_args($argv);
805 Error parsing this string passed to to perltidy with 'argv':
809 @ARGV = @{$rargv_str};
813 # These string refs will hold any warnings and error messages to be written
814 # to the logfile object when it eventually gets created.
815 my $rpending_complaint;
816 ${$rpending_complaint} = EMPTY_STRING;
818 my $rpending_logfile_message;
819 ${$rpending_logfile_message} = EMPTY_STRING;
821 my ( $is_Windows, $Windows_type ) = look_for_Windows($rpending_complaint);
823 # VMS file names are restricted to a 40.40 format, so we append _tdy
824 # instead of .tdy, etc. (but see also sub check_vms_filename)
827 if ( $OSNAME eq 'VMS' ) {
833 $dot_pattern = '\.'; # must escape for use in regex
835 $self->[_file_extension_separator_] = $dot;
837 # save a copy of the last two input args for error checking later
840 @ARGV_saved = ( $ARGV[-2], $ARGV[-1] );
843 # see if -wvt was entered on the command line before @ARGV is changed
844 my $wvt_in_args = grep { /-(wvt|warn-variable-types)=/ } @ARGV;
846 #-------------------------
847 # get command line options
848 #-------------------------
849 my ( $rOpts, $config_file, $rraw_options, $roption_string,
850 $rexpansion, $roption_category, $roption_range, $rinteger_option_range )
851 = process_command_line(
852 $perltidyrc_stream, $is_Windows, $Windows_type,
853 $rpending_complaint, $dump_options_type,
856 # Only filenames should remain in @ARGV
857 my @Arg_files = @ARGV;
859 $self->[_rOpts_] = $rOpts;
862 grep { $_ eq '-pbp' || $_ eq '-perl-best-practices' } @{$rraw_options};
863 $self->[_saw_pbp_] = $saw_pbp;
865 #------------------------------------
866 # Handle requests to dump information
867 #------------------------------------
869 # return or exit immediately after all dumps
872 # Getopt parameters and their flags
873 if ( defined($dump_getopt_flags) ) {
875 foreach my $op ( @{$roption_string} ) {
877 my $flag = EMPTY_STRING;
884 if ( $opt =~ /(.*)(!|=.*|:.*)$/ ) {
888 $dump_getopt_flags->{$opt} = $flag;
892 if ( defined($dump_options_category) ) {
894 %{$dump_options_category} = %{$roption_category};
897 if ( defined($dump_options_range) ) {
899 %{$dump_options_range} = %{$roption_range};
902 if ( defined($dump_abbreviations) ) {
904 %{$dump_abbreviations} = %{$rexpansion};
907 if ( defined($dump_options) ) {
909 %{$dump_options} = %{$rOpts};
912 Exit(0) if ($quit_now);
914 # make printable string of options for this run as possible diagnostic
915 my $readable_options = readable_options( $rOpts, $roption_string );
917 # dump from command line
918 if ( $rOpts->{'dump-options'} ) {
919 print {*STDOUT} $readable_options;
923 # some dump options require one filename in the arg list. This is a safety
924 # precaution in case a user accidentally adds such an option to the command
925 # line parameters and is expecting formatted output to stdout. Another
926 # precaution, added elsewhere, is to ignore these in a .perltidyrc
927 my $num_files = @Arg_files;
928 foreach my $opt_name (
931 dump-unusual-variables
932 dump-mixed-call-parens
934 dump-mismatched-returns
939 if ( $rOpts->{$opt_name} ) {
940 $self->[_dump_to_stdout_] = 1;
941 if ( $num_files != 1 ) {
943 --$opt_name expects 1 filename in the arg list but saw $num_files filenames
949 #----------------------------------------
950 # check parameters and their interactions
951 #----------------------------------------
952 $self->check_options( $num_files, $rinteger_option_range );
954 if ($user_formatter) {
955 $rOpts->{'format'} = 'user';
958 # there must be one entry here for every possible format
959 my %default_file_extension = (
962 user => EMPTY_STRING,
965 $rstatus->{'opt_format'} = $rOpts->{'format'};
966 $rstatus->{'opt_max_iterations'} = $rOpts->{'iterations'};
967 $rstatus->{'opt_encode_output'} =
968 $rOpts->{'encode-output-strings'} ? 'eos' : 'neos';
970 # be sure we have a valid output format
971 if ( !exists $default_file_extension{ $rOpts->{'format'} } ) {
972 my $formats = join SPACE,
973 sort map { "'" . $_ . "'" } keys %default_file_extension;
974 my $fmt = $rOpts->{'format'};
975 Die("-format='$fmt' but must be one of: $formats\n");
978 my $output_extension =
979 $self->make_file_extension( $rOpts->{'output-file-extension'},
980 $default_file_extension{ $rOpts->{'format'} } );
982 # get parameters associated with the -b option
983 my ( $in_place_modify, $backup_extension, $delete_backup ) =
984 $self->check_in_place_modify( $source_stream, $destination_stream );
986 my $line_range_clipped = $rOpts->{'line-range-tidy'}
987 && ( $self->[_line_tidy_begin_] > 1
988 || defined( $self->[_line_tidy_end_] ) );
990 Perl::Tidy::Formatter::check_options( $rOpts, $wvt_in_args, $num_files,
991 $line_range_clipped );
992 Perl::Tidy::Tokenizer::check_options($rOpts);
993 Perl::Tidy::VerticalAligner::check_options($rOpts);
994 if ( $rOpts->{'format'} eq 'html' ) {
995 Perl::Tidy::HtmlWriter->check_options($rOpts);
998 # Try to catch an unusual missing string parameter error, like this:
999 # perltidy -wvt perltidy.pl
1000 # The problem is that -wvt wants a string, so it grabs 'perltidy.pl'.
1001 # Then there is no output filename, so input is assumed to be stdin.
1002 # This make perltidy unexpectedly wait for input. To the user, it
1003 # appears that perltidy has gone into an infinite loop. Issue c312.
1004 # To avoid getting this far, it is best for parameters which take a
1005 # string to check the strings in one of the 'check_options' subs, and
1006 # exit if there is an obvious error. This has been done for -wvt,
1007 # but are undoubtedly other parameters where this problem might occur.
1008 if ( !$num_files && @ARGV_saved > 1 ) {
1009 my $opt_test = $ARGV_saved[-2];
1010 my $file_test = $ARGV_saved[-1];
1011 if ( $opt_test =~ s/^[-]+//
1012 && $file_test !~ /^[-]/
1013 && $file_test !~ /^\d+$/
1017 # These options can take filenames, so we will ignore them here
1018 my %is_option_with_file_parameter;
1019 my @qf = qw( outfile profile );
1020 @is_option_with_file_parameter{@qf} = (1) x scalar(@qf);
1022 # Expand an abbreviation into a long name
1024 my $exp = $rexpansion->{$opt_test};
1025 if ( !$exp ) { $long_name = $opt_test }
1026 elsif ( @{$exp} == 1 ) { $long_name = $exp->[0] }
1029 # If this arg grabbed the file, then it must take a string arg
1031 && defined( $rOpts->{$long_name} )
1032 && $rOpts->{$long_name} eq $file_test
1033 && !$is_option_with_file_parameter{$long_name} )
1036 Stopping on possible missing string parameter for '-$opt_test':
1037 This parameter takes a string and has been set equal to file '$file_test',
1038 and formatted output will go to standard output. If this is actually correct,
1039 you can skip this message by entering this as '-$opt_test=$file_test'.
1045 # make the pattern of file extensions that we shouldn't touch
1046 my $forbidden_file_extensions = "(($dot_pattern)(LOG|DEBUG|ERR|TEE)";
1047 if ($output_extension) {
1048 my $ext = quotemeta($output_extension);
1049 $forbidden_file_extensions .= "|$ext";
1051 if ( $in_place_modify && $backup_extension ) {
1052 my $ext = quotemeta($backup_extension);
1053 $forbidden_file_extensions .= "|$ext";
1055 $forbidden_file_extensions .= ')$';
1057 # Create a diagnostics object if requested;
1058 # This is only useful for code development
1059 my $diagnostics_object = undef;
1061 $diagnostics_object = Perl::Tidy::Diagnostics->new();
1064 # no filenames should be given if input is from an array
1065 if ($source_stream) {
1066 if ( @Arg_files > 0 ) {
1068 "You may not specify any filenames when a source array is given\n"
1072 # we'll stuff the source array into Arg_files
1073 unshift( @Arg_files, $source_stream );
1075 # No special treatment for source stream which is a filename.
1076 # This will enable checks for binary files and other bad stuff.
1077 $source_stream = undef unless ref($source_stream);
1080 # use stdin by default if no source array and no args
1081 elsif ( !@Arg_files ) {
1082 unshift( @Arg_files, '-' );
1085 # check file existence and expand any globs
1088 foreach my $input_file (@Arg_files) {
1089 if ( -e $input_file ) {
1090 push @updated_files, $input_file;
1094 # file doesn't exist - check for a file glob
1095 if ( $input_file =~ /([\?\*\[\{])/ ) {
1097 # Windows shell may not remove quotes, so do it
1098 my $ifile = $input_file;
1099 if ( $ifile =~ /^\'(.+)\'$/ ) { $ifile = $1 }
1100 if ( $ifile =~ /^\"(.+)\"$/ ) { $ifile = $1 }
1101 my $pattern = fileglob_to_re($ifile);
1103 if ( opendir( $dh, './' ) ) {
1105 grep { /$pattern/ && !-d } readdir($dh);
1107 next unless (@files);
1108 push @updated_files, @files;
1112 Warn("skipping file: '$input_file': no matches found\n");
1115 } ## end loop over input filenames
1117 @Arg_files = @updated_files;
1118 if ( !@Arg_files ) {
1119 Die("no matching input files found\n");
1123 # Flag for loading module Unicode::GCString for evaluating text width:
1124 # undef = ok to use but not yet loaded
1125 # 0 = do not use; failed to load or not wanted
1126 # 1 = successfully loaded and ok to use
1127 # The module is not actually loaded unless/until it is needed
1128 if ( !$rOpts->{'use-unicode-gcstring'} ) {
1129 $loaded_unicode_gcstring = 0;
1132 # Remove duplicate filenames. Otherwise, for example if the user entered
1133 # perltidy -b myfile.pl myfile.pl
1134 # the backup version of the original would be lost.
1135 if ( @Arg_files > 1 ) {
1137 @Arg_files = grep { !$seen{$_}++ } @Arg_files;
1140 # If requested, process in order of increasing file size
1141 # This can significantly reduce perl's virtual memory usage during testing.
1142 if ( @Arg_files > 1 && $rOpts->{'file-size-order'} ) {
1145 sort { $a->[1] <=> $b->[1] }
1146 map { [ $_, -e $_ ? -s $_ : 0 ] } @Arg_files;
1149 my $logfile_header = make_logfile_header( $rOpts, $config_file,
1150 $rraw_options, $Windows_type, $readable_options );
1152 # Store some values needed by lower level routines
1153 $self->[_diagnostics_object_] = $diagnostics_object;
1154 $self->[_postfilter_] = $postfilter;
1155 $self->[_prefilter_] = $prefilter;
1156 $self->[_user_formatter_] = $user_formatter;
1158 #--------------------------
1159 # loop to process all files
1160 #--------------------------
1161 $self->process_all_files(
1163 rinput_hash => \%input_hash,
1164 rfiles => \@Arg_files,
1167 source_stream => $source_stream,
1168 output_extension => $output_extension,
1169 forbidden_file_extensions => $forbidden_file_extensions,
1170 in_place_modify => $in_place_modify,
1171 backup_extension => $backup_extension,
1172 delete_backup => $delete_backup,
1175 logfile_header => $logfile_header,
1176 rpending_complaint => $rpending_complaint,
1177 rpending_logfile_message => $rpending_logfile_message,
1185 # Fix for RT #130297: return a true value if anything was written to the
1186 # standard error output, even non-fatal warning messages, otherwise return
1189 # These exit codes are returned:
1190 # 0 = perltidy ran to completion with no errors
1191 # 1 = perltidy could not run to completion due to errors
1192 # 2 = perltidy ran to completion with error messages
1194 # Note that if perltidy is run with multiple files, any single file with
1195 # errors or warnings will write a line like
1196 # '## Please see file testing.t.ERR'
1197 # to standard output for each file with errors, so the flag will be true,
1198 # even if only some of the multiple files may have had errors.
1201 my $ret = $Warn_count ? 2 : 0;
1202 return wantarray ? ( $ret, $rstatus ) : $ret;
1205 return wantarray ? ( 1, $rstatus ) : 1;
1207 } ## end sub perltidy
1209 sub make_file_extension {
1211 # Make a file extension, adding any leading '.' if necessary.
1212 # (the '.' may actually be an '_' under VMS).
1213 my ( $self, $extension, ($default) ) = @_;
1216 # $extension = the first choice (usually a user entry)
1217 # $default = an optional backup extension
1219 # $extension = the actual file extension
1221 $extension = EMPTY_STRING unless defined($extension);
1222 $extension =~ s/^\s+//;
1223 $extension =~ s/\s+$//;
1225 # Use default extension if nothing remains of the first choice
1226 if ( length($extension) == 0 ) {
1227 $extension = $default;
1228 $extension = EMPTY_STRING unless defined($extension);
1229 $extension =~ s/^\s+//;
1230 $extension =~ s/\s+$//;
1233 # Only extensions with these leading characters get a '.'
1234 # This rule gives the user some freedom.
1235 if ( $extension =~ /^[a-zA-Z0-9]/ ) {
1236 my $dot = $self->[_file_extension_separator_];
1237 $extension = $dot . $extension;
1240 } ## end sub make_file_extension
1242 sub check_in_place_modify {
1244 my ( $self, $source_stream, $destination_stream ) = @_;
1246 # See if --backup-and-modify-in-place (-b) is set, and if so,
1247 # return its associated parameters
1248 my $rOpts = $self->[_rOpts_];
1250 # check for -b option;
1251 # silently ignore unless beautify mode
1252 my $in_place_modify = $rOpts->{'backup-and-modify-in-place'}
1253 && $rOpts->{'format'} eq 'tidy';
1255 my ( $backup_extension, $delete_backup );
1257 # Turn off -b with warnings in case of conflicts with other options.
1258 # NOTE: Do this silently, without warnings, if there is a source or
1259 # destination stream, or standard output is used. This is because the -b
1260 # flag may have been in a .perltidyrc file and warnings break
1261 # Test::NoWarnings. See email discussion with Merijn Brand 26 Feb 2014.
1262 if ($in_place_modify) {
1263 if ( $rOpts->{'standard-output'}
1264 || $destination_stream
1265 || ref($source_stream)
1266 || $rOpts->{'outfile'}
1267 || defined( $rOpts->{'output-path'} ) )
1269 $in_place_modify = 0;
1273 if ($in_place_modify) {
1275 # If the backup extension contains a / character then the backup should
1276 # be deleted when the -b option is used. On older versions of
1277 # perltidy this will generate an error message due to an illegal
1280 # A backup file will still be generated but will be deleted
1281 # at the end. If -bext='/' then this extension will be
1282 # the default 'bak'. Otherwise it will be whatever characters
1283 # remains after all '/' characters are removed. For example:
1284 # -bext extension slashes
1286 # '/delete' delete 1
1287 # 'delete/' delete 1
1288 # '/dev/null' devnull 2 (Currently not allowed)
1289 my $bext = $rOpts->{'backup-file-extension'};
1290 $delete_backup = ( $rOpts->{'backup-file-extension'} =~ s/\///g );
1292 # At present only one forward slash is allowed. In the future multiple
1293 # slashes may be allowed to allow for other options
1294 if ( $delete_backup > 1 ) {
1295 Die("-bext=$bext contains more than one '/'\n");
1299 $self->make_file_extension( $rOpts->{'backup-file-extension'},
1303 my $backup_method = $rOpts->{'backup-method'};
1304 if ( defined($backup_method)
1305 && $backup_method ne 'copy'
1306 && $backup_method ne 'move' )
1309 "Unexpected --backup-method='$backup_method'; must be one of: 'move', 'copy'\n"
1313 return ( $in_place_modify, $backup_extension, $delete_backup );
1314 } ## end sub check_in_place_modify
1316 sub backup_method_copy {
1318 my ( $self, $input_file, $routput_string, $backup_extension,
1322 # Handle the -b (--backup-and-modify-in-place) option with -bm='copy':
1323 # - First copy $input file to $backup_name.
1324 # - Then open input file and rewrite with contents of $routput_string
1325 # - Then delete the backup if requested
1328 # - Die immediately on any error.
1329 # - $routput_string is a SCALAR ref
1331 my $backup_file = $input_file . $backup_extension;
1333 if ( !-f $input_file ) {
1335 # no real file to backup ..
1336 # This shouldn't happen because of numerous preliminary checks
1338 "problem with -b backing up input file '$input_file': not a file\n"
1342 if ( -f $backup_file ) {
1343 unlink($backup_file)
1345 "unable to remove previous '$backup_file' for -b option; check permissions: $OS_ERROR\n"
1349 # Copy input file to backup
1350 File::Copy::copy( $input_file, $backup_file )
1351 or Die("File::Copy failed trying to backup source: $OS_ERROR");
1353 # set permissions of the backup file to match the input file
1354 my @input_file_stat = stat($input_file);
1355 my $in_place_modify = 1;
1356 $self->set_output_file_permissions( $backup_file, \@input_file_stat,
1359 # set the modification time of the copy to the original value (rt#145999)
1360 my ( $read_time, $write_time ) = @input_file_stat[ _atime_, _mtime_ ];
1361 if ( defined($write_time) ) {
1362 utime( $read_time, $write_time, $backup_file )
1363 || Warn("error setting times for backup file '$backup_file'\n");
1366 # Open the original input file for writing ... opening with ">" will
1367 # truncate the existing data.
1368 open( my $fout, ">", $input_file )
1370 "problem re-opening $input_file for write for -b option; check file and directory permissions: $OS_ERROR\n"
1373 if ( $self->[_is_encoded_data_] ) { binmode $fout, ":raw:encoding(UTF-8)" }
1374 else { binmode $fout }
1376 # Now copy the formatted output to it..
1377 # output must be SCALAR ref..
1378 if ( ref($routput_string) eq 'SCALAR' ) {
1379 $fout->print( ${$routput_string} )
1380 or Die("cannot print to '$input_file' with -b option: $OS_ERROR\n");
1383 # Error if anything else ...
1385 my $ref = ref($routput_string);
1387 Programming error: unable to print to '$input_file' with -b option:
1388 unexpected ref type '$ref'; expecting 'ARRAY' or 'SCALAR'
1393 or Die("cannot close '$input_file' with -b option: $OS_ERROR\n");
1395 # Set permissions of the output file to match the input file. This is
1396 # necessary even if the inode remains unchanged because suid/sgid bits may
1398 $self->set_output_file_permissions( $input_file, \@input_file_stat,
1401 # Keep original modification time if no change (rt#145999)
1402 if ( !$self->[_input_output_difference_] && defined($write_time) ) {
1403 utime( $read_time, $write_time, $input_file )
1404 || Warn("error setting times for '$input_file'\n");
1407 #---------------------------------------------------------
1408 # remove the original file for in-place modify as follows:
1409 # $delete_backup=0 never
1410 # $delete_backup=1 only if no errors
1411 # $delete_backup>1 always : NOT ALLOWED, too risky
1412 #---------------------------------------------------------
1413 if ( $delete_backup && -f $backup_file ) {
1415 # Currently, $delete_backup may only be 1. But if a future update
1416 # allows a value > 1, then reduce it to 1 if there were warnings.
1417 if ( $delete_backup > 1
1418 && $self->[_logger_object_]->get_warning_count() )
1423 # As an added safety precaution, do not delete the source file
1424 # if its size has dropped from positive to zero, since this
1425 # could indicate a disaster of some kind, including a hardware
1426 # failure. Actually, this could happen if you had a file of
1427 # all comments (or pod) and deleted everything with -dac (-dap)
1429 if ( !-s $input_file && -s $backup_file && $delete_backup == 1 ) {
1431 "output file '$input_file' missing or zero length; original '$backup_file' not deleted\n"
1435 unlink($backup_file)
1437 "unable to remove backup file '$backup_file' for -b option; check permissions: $OS_ERROR\n"
1442 # Verify that inode is unchanged during development
1444 my @output_file_stat = stat($input_file);
1445 my $inode_input = $input_file_stat[1];
1446 my $inode_output = $output_file_stat[1];
1447 if ( $inode_input != $inode_output ) {
1449 inode changed with -bm=copy for file '$input_file': inode_input=$inode_input inode_output=$inode_output
1455 } ## end sub backup_method_copy
1457 sub backup_method_move {
1459 my ( $self, $input_file, $routput_string, $backup_extension,
1463 # Handle the -b (--backup-and-modify-in-place) option with -bm='move':
1464 # - First move $input file to $backup_name.
1465 # - Then copy $routput_string to $input_file.
1466 # - Then delete the backup if requested
1469 # - Die immediately on any error.
1470 # - $routput_string is a SCALAR ref
1471 # - $input_file permissions will be set by sub set_output_file_permissions
1473 my $backup_name = $input_file . $backup_extension;
1475 if ( !-f $input_file ) {
1477 # oh, oh, no real file to backup ..
1478 # shouldn't happen because of numerous preliminary checks
1480 "problem with -b backing up input file '$input_file': not a file\n"
1483 if ( -f $backup_name ) {
1484 unlink($backup_name)
1486 "unable to remove previous '$backup_name' for -b option; check permissions: $OS_ERROR\n"
1490 my @input_file_stat = stat($input_file);
1492 # backup the input file
1493 # we use copy for symlinks, move for regular files
1494 if ( -l $input_file ) {
1495 File::Copy::copy( $input_file, $backup_name )
1496 or Die("File::Copy failed trying to backup source: $OS_ERROR");
1499 rename( $input_file, $backup_name )
1501 "problem renaming $input_file to $backup_name for -b option: $OS_ERROR\n"
1505 # Open a file with the original input file name for writing ...
1506 open( my $fout, ">", $input_file )
1508 "problem re-opening $input_file for write for -b option; check file and directory permissions: $OS_ERROR\n"
1511 if ( $self->[_is_encoded_data_] ) { binmode $fout, ":raw:encoding(UTF-8)" }
1512 else { binmode $fout }
1514 # Now copy the formatted output to it..
1515 # output must be SCALAR ref..
1516 if ( ref($routput_string) eq 'SCALAR' ) {
1517 $fout->print( ${$routput_string} )
1518 or Die("cannot print to '$input_file' with -b option: $OS_ERROR\n");
1521 # Error if anything else ...
1523 my $ref = ref($routput_string);
1525 Programming error: unable to print to '$input_file' with -b option:
1526 unexpected ref type '$ref'; expecting 'ARRAY' or 'SCALAR'
1531 or Die("cannot close '$input_file' with -b option: $OS_ERROR\n");
1533 # set permissions of the output file to match the input file
1534 my $in_place_modify = 1;
1535 $self->set_output_file_permissions( $input_file, \@input_file_stat,
1538 # Keep original modification time if no change (rt#145999)
1539 my ( $read_time, $write_time ) = @input_file_stat[ _atime_, _mtime_ ];
1540 if ( !$self->[_input_output_difference_] && defined($write_time) ) {
1541 utime( $read_time, $write_time, $input_file )
1542 || Warn("error setting times for '$input_file'\n");
1545 #---------------------------------------------------------
1546 # remove the original file for in-place modify as follows:
1547 # $delete_backup=0 never
1548 # $delete_backup=1 only if no errors
1549 # $delete_backup>1 always : NOT ALLOWED, too risky
1550 #---------------------------------------------------------
1551 if ( $delete_backup && -f $backup_name ) {
1553 # Currently, $delete_backup may only be 1. But if a future update
1554 # allows a value > 1, then reduce it to 1 if there were warnings.
1555 if ( $delete_backup > 1
1556 && $self->[_logger_object_]->get_warning_count() )
1561 # As an added safety precaution, do not delete the source file
1562 # if its size has dropped from positive to zero, since this
1563 # could indicate a disaster of some kind, including a hardware
1564 # failure. Actually, this could happen if you had a file of
1565 # all comments (or pod) and deleted everything with -dac (-dap)
1567 if ( !-s $input_file && -s $backup_name && $delete_backup == 1 ) {
1569 "output file '$input_file' missing or zero length; original '$backup_name' not deleted\n"
1573 unlink($backup_name)
1575 "unable to remove previous '$backup_name' for -b option; check permissions: $OS_ERROR\n"
1582 } ## end sub backup_method_move
1584 # masks for file permissions
1585 use constant OCT_777 => oct(777); # All users (O+G+W) + r/w/x bits
1586 use constant OCT_7777 => oct(7777); # Same + suid/sgid/sbit
1587 use constant OCT_600 => oct(600); # Owner RW permission
1589 sub set_output_file_permissions {
1591 my ( $self, $output_file, $rinput_file_stat, $in_place_modify ) = @_;
1593 # Set the permissions for the output file
1596 # $output_file = the file whose permissions we will set
1597 # $rinput_file_stat = the result of stat($input_file)
1598 # $in_place_modify = true if --backup-and-modify-in-place is set
1600 my ( $mode_i, $uid_i, $gid_i ) =
1601 @{$rinput_file_stat}[ _mode_, _uid_, _gid_ ];
1602 my ( $uid_o, $gid_o ) = ( stat($output_file) )[ _uid_, _gid_ ];
1603 my $input_file_permissions = $mode_i & OCT_7777;
1604 my $output_file_permissions = $input_file_permissions;
1606 #rt128477: avoid inconsistent owner/group and suid/sgid
1607 if ( $uid_i != $uid_o || $gid_i != $gid_o ) {
1609 # try to change owner and group to match input file if
1610 # in -b mode. Note: chown returns number of files
1611 # successfully changed.
1612 if ( $in_place_modify
1613 && chown( $uid_i, $gid_i, $output_file ) )
1615 # owner/group successfully changed
1619 # owner or group differ: do not copy suid and sgid
1620 $output_file_permissions = $mode_i & OCT_777;
1621 if ( $input_file_permissions != $output_file_permissions ) {
1623 "Unable to copy setuid and/or setgid bits for output file '$output_file'\n"
1629 # Mark the output file for rw unless we are in -b mode.
1630 # Explanation: perltidy does not unlink existing output
1631 # files before writing to them, for safety. If a
1632 # designated output file exists and is not writable,
1633 # perltidy will halt. This can prevent a data loss if a
1634 # user accidentally enters "perltidy infile -o
1635 # important_ro_file", or "perltidy infile -st
1636 # >important_ro_file". But it also means that perltidy can
1637 # get locked out of rerunning unless it marks its own
1638 # output files writable. The alternative, of always
1639 # unlinking the designated output file, is less safe and
1640 # not always possible, except in -b mode, where there is an
1641 # assumption that a previous backup can be unlinked even if
1643 if ( !$in_place_modify ) {
1644 $output_file_permissions |= OCT_600;
1647 if ( !chmod( $output_file_permissions, $output_file ) ) {
1649 # couldn't change file permissions
1650 my $operm = sprintf "%04o", $output_file_permissions;
1652 "Unable to set permissions for output file '$output_file' to $operm\n"
1656 } ## end sub set_output_file_permissions
1658 sub get_decoded_string_buffer {
1660 my ( $self, $input_file, $display_name ) = @_;
1662 # Decode the input buffer from utf8 if necessary or requested
1665 # $input_file = the input file or stream
1666 # $display_name = its name to use in error messages
1668 # Set $self->[_line_separator_], and
1671 # $rinput_string = ref to input string, decoded from utf8 if necessary
1672 # $is_encoded_data = true if $buf is decoded from utf8
1673 # $decoded_input_as = true if perltidy decoded input buf
1674 # $encoding_log_message = messages for log file,
1675 # $length_function = function to use for measuring string width
1677 # Return nothing on any error; this is a signal to skip this file
1679 my $rOpts = $self->[_rOpts_];
1682 stream_slurp( $input_file, $rOpts->{'timeout-in-seconds'} );
1683 return unless ( defined($rinput_string) );
1685 # Note that we could have a zero size input string here if it
1686 # arrived from standard input or from a string ref. For example
1687 # 'perltidy <null.pl'. If we issue a warning and stop, as we would
1688 # for a zero length file ('perltidy null.pl'), then we could cause
1689 # a call to the perltidy module to misbehave as a filter. So we will
1690 # process this as any other file in this case without any warning (c286).
1691 if ( !length( ${$rinput_string} ) ) {
1693 # zero length, but keep going
1696 # Check size of strings arriving from the standard input. These
1697 # could not be checked until now.
1698 if ( $input_file eq '-' ) {
1700 length( ${$rinput_string} ) / ( CONST_1024 * CONST_1024 );
1701 my $maximum_file_size_mb = $rOpts->{'maximum-file-size-mb'};
1702 if ( $size_in_mb > $maximum_file_size_mb ) {
1703 $size_in_mb = sprintf( "%0.1f", $size_in_mb );
1705 "skipping file: <stdin>: size $size_in_mb MB exceeds limit $maximum_file_size_mb; use -maxfs=i to change\n"
1711 $rinput_string = $self->set_line_separator($rinput_string);
1713 my $encoding_in = EMPTY_STRING;
1714 my $rOpts_character_encoding = $rOpts->{'character-encoding'};
1715 my $encoding_log_message;
1716 my $decoded_input_as = EMPTY_STRING;
1717 $rstatus->{'char_mode_source'} = 0;
1719 # Case 1: If Perl is already in a character-oriented mode for this
1720 # string rather than a byte-oriented mode. Normally, this happens if
1721 # the caller has decoded a utf8 string before calling perltidy. But it
1722 # could also happen if the user has done some unusual manipulations of
1723 # the source. In any case, we will not attempt to decode it because
1724 # that could result in an output string in a different mode.
1725 if ( is_char_mode( ${$rinput_string} ) ) {
1726 $encoding_in = "utf8";
1727 $rstatus->{'char_mode_source'} = 1;
1730 # Case 2. No input stream encoding requested. This is appropriate
1731 # for single-byte encodings like ascii, latin-1, etc
1732 elsif ( !$rOpts_character_encoding
1733 || $rOpts_character_encoding eq 'none' )
1739 # Case 3. guess input stream encoding if requested
1740 elsif ( lc($rOpts_character_encoding) eq 'guess' ) {
1742 # The guessing strategy is simple: use Encode::Guess to guess
1743 # an encoding. If and only if the guess is utf8, try decoding and
1744 # use it if successful. Otherwise, we proceed assuming the
1745 # characters are encoded as single bytes (same as if 'none' had
1746 # been specified as the encoding).
1748 # In testing I have found that including additional guess 'suspect'
1749 # encodings sometimes works but can sometimes lead to disaster by
1750 # using an incorrect decoding.
1753 if ( ${$rinput_string} =~ /[^[:ascii:]]/ ) {
1754 $decoder = guess_encoding( ${$rinput_string}, 'utf8' );
1756 if ( $decoder && ref($decoder) ) {
1757 $encoding_in = $decoder->name;
1758 if ( $encoding_in ne 'UTF-8' && $encoding_in ne 'utf8' ) {
1759 $encoding_in = EMPTY_STRING;
1760 $encoding_log_message .= <<EOM;
1761 Guessed encoding '$encoding_in' is not utf8; no encoding will be used
1767 if ( !eval { $buf = $decoder->decode( ${$rinput_string} ); 1 } )
1770 $encoding_log_message .= <<EOM;
1771 Guessed encoding '$encoding_in' but decoding was unsuccessful; no encoding is used
1774 # Note that a guess failed, but keep going
1775 # This warning can eventually be removed
1777 "file: $display_name: bad guess to decode source as $encoding_in\n"
1779 $encoding_in = EMPTY_STRING;
1782 $encoding_log_message .= <<EOM;
1783 Guessed encoding '$encoding_in' successfully decoded
1785 $decoded_input_as = $encoding_in;
1786 $rinput_string = \$buf;
1791 $encoding_log_message .= <<EOM;
1792 Does not look like utf8 encoded text so processing as raw bytes
1797 # Case 4. Decode with a specific encoding
1799 $encoding_in = $rOpts_character_encoding;
1803 $buf = Encode::decode( $encoding_in, ${$rinput_string},
1804 Encode::FB_CROAK | Encode::LEAVE_SRC );
1810 # Quit if we cannot decode by the requested encoding;
1811 # Something is not right.
1813 "skipping file: $display_name: Unable to decode source as $encoding_in\n"
1816 # return nothing on error
1820 $encoding_log_message .= <<EOM;
1821 Specified encoding '$encoding_in' successfully decoded
1823 $decoded_input_as = $encoding_in;
1824 $rinput_string = \$buf;
1828 # Set the encoding to be used for all further i/o: If we have
1829 # decoded the data with any format, then we must continue to
1830 # read and write it as encoded data, and we will normalize these
1831 # operations with utf8. If we have not decoded the data, then
1832 # we must not treat it as encoded data.
1833 my $is_encoded_data = $encoding_in ? 'utf8' : EMPTY_STRING;
1834 $self->[_is_encoded_data_] = $is_encoded_data;
1836 # Delete any Byte Order Mark (BOM), which can cause trouble
1837 if ($is_encoded_data) {
1838 ${$rinput_string} =~ s/^\x{FEFF}//;
1841 $rstatus->{'input_name'} = $display_name;
1842 $rstatus->{'opt_encoding'} = $rOpts_character_encoding;
1843 $rstatus->{'char_mode_used'} = $encoding_in ? 1 : 0;
1844 $rstatus->{'input_decoded_as'} = $decoded_input_as;
1846 # Define the function to determine the display width of character
1848 my $length_function;
1849 if ($is_encoded_data) {
1851 # Try to load Unicode::GCString for defining text display width, if
1852 # requested, when the first encoded file is encountered
1853 if ( !defined($loaded_unicode_gcstring) ) {
1854 if ( eval { require Unicode::GCString; 1 } ) {
1855 $loaded_unicode_gcstring = 1;
1858 $loaded_unicode_gcstring = 0;
1859 if ( $rOpts->{'use-unicode-gcstring'} ) {
1861 ----------------------
1862 Unable to load Unicode::GCString: $EVAL_ERROR
1863 Processing continues but some vertical alignment may be poor
1864 To prevent this warning message, you can either:
1865 - install module Unicode::GCString, or
1866 - remove '--use-unicode-gcstring' or '-gcs' from your perltidyrc or command line
1867 ----------------------
1872 if ($loaded_unicode_gcstring) {
1873 $length_function = sub {
1874 return Unicode::GCString->new( $_[0] )->columns;
1876 $encoding_log_message .= <<EOM;
1877 Using 'Unicode::GCString' to measure horizontal character widths
1879 $rstatus->{'gcs_used'} = 1;
1886 $encoding_log_message,
1890 } ## end sub get_decoded_string_buffer
1904 sub get_line_separator_default {
1908 # Get the line separator that will apply unless overridden by a
1909 # --preserve-line-endings flag for a specific file
1911 my $line_separator_default = "\n";
1913 my $ole = $rOpts->{'output-line-ending'};
1922 $line_separator_default = $endings{ lc $ole };
1924 if ( !$line_separator_default ) {
1925 my $str = join SPACE, keys %endings;
1927 Unrecognized line ending '$ole'; expecting one of: $str
1931 # Check for conflict with -ple
1932 if ( $rOpts->{'preserve-line-endings'} ) {
1933 Warn("Ignoring -ple; conflicts with -ole\n");
1934 $rOpts->{'preserve-line-endings'} = undef;
1938 return $line_separator_default;
1940 } ## end sub get_line_separator_default
1942 sub set_line_separator {
1944 my ( $self, $rinput_string ) = @_;
1946 # Set the (output) line separator as requested or necessary
1948 my $rOpts = $self->[_rOpts_];
1950 # Start with the default (output) line separator
1951 my $line_separator = $self->[_line_separator_default_];
1953 # First try to find the line separator of the input stream
1954 my $input_line_separator;
1956 # Limit the search to a reasonable number of characters, in case we
1958 my $str = substr( ${$rinput_string}, 0, CONST_1024 );
1961 if ( $str =~ m/(($CR|$LF)+)/ ) {
1966 if ( $test =~ /^($CRLF)+\z/ ) {
1967 $input_line_separator = $CRLF;
1971 elsif ( $test =~ /^($CR)+\z/ ) {
1972 $input_line_separator = $CR;
1976 elsif ( $test =~ /^($LF)+\z/ ) {
1977 $input_line_separator = $LF;
1988 if ( defined($input_line_separator) ) {
1990 # Remember the input line separator if needed
1991 if ( $rOpts->{'preserve-line-endings'} ) {
1992 $line_separator = $input_line_separator;
1995 # Convert line endings to "\n" for processing if necessary.
1996 if ( $input_line_separator ne "\n" ) {
1997 my @lines = split /^/, ${$rinput_string};
1999 # try to convert CR to \n
2000 if ( $input_line_separator eq $CR ) {
2002 # if this file is currently a single line ..
2003 if ( @lines == 1 ) {
2005 # and becomes multiple lines with the change ..
2006 @lines = map { $_ . "\n" } split /$CR/, ${$rinput_string};
2009 # then make the change
2010 my $buf = join EMPTY_STRING, @lines;
2011 $rinput_string = \$buf;
2016 # convert CR-LF to LF
2017 elsif ( ( $input_line_separator eq $CRLF ) && ( "\n" eq $LF ) ) {
2018 foreach my $line (@lines) { $line =~ s/$CRLF$/\n/ }
2019 my $buf = join EMPTY_STRING, @lines;
2020 $rinput_string = \$buf;
2023 # unknown line ending scheme - leave it alone and let the tokenizer
2030 $self->[_line_separator_] = $line_separator;
2031 return $rinput_string;
2032 } ## end sub set_line_separator
2035 sub process_all_files {
2037 my ( $self, $rcall_hash ) = @_;
2039 # This routine is the main loop to process all files.
2040 # Total formatting is done with these layers of subroutines:
2041 # perltidy - main routine; checks run parameters
2042 # *process_all_files - main loop to process all files; *THIS LAYER
2043 # process_filter_layer - do any pre and post processing;
2044 # process_iteration_layer - handle any iterations on formatting
2045 # process_single_case - solves one formatting problem
2047 my $rinput_hash = $rcall_hash->{rinput_hash};
2048 my $rfiles = $rcall_hash->{rfiles};
2049 my $source_stream = $rcall_hash->{source_stream};
2050 my $output_extension = $rcall_hash->{output_extension};
2051 my $forbidden_file_extensions = $rcall_hash->{forbidden_file_extensions};
2052 my $in_place_modify = $rcall_hash->{in_place_modify};
2053 my $backup_extension = $rcall_hash->{backup_extension};
2054 my $delete_backup = $rcall_hash->{delete_backup};
2055 my $logfile_header = $rcall_hash->{logfile_header};
2056 my $rpending_complaint = $rcall_hash->{rpending_complaint};
2057 my $rpending_logfile_message = $rcall_hash->{rpending_logfile_message};
2059 my $rOpts = $self->[_rOpts_];
2060 my $dot = $self->[_file_extension_separator_];
2061 my $diagnostics_object = $self->[_diagnostics_object_];
2063 my $destination_stream = $rinput_hash->{'destination'};
2064 my $errorfile_stream = $rinput_hash->{'errorfile'};
2065 my $logfile_stream = $rinput_hash->{'logfile'};
2066 my $teefile_stream = $rinput_hash->{'teefile'};
2067 my $debugfile_stream = $rinput_hash->{'debugfile'};
2069 my $number_of_files = @{$rfiles};
2070 foreach my $input_file ( @{$rfiles} ) {
2072 my @input_file_stat;
2075 #--------------------------
2076 # prepare this input stream
2077 #--------------------------
2078 if ($source_stream) {
2079 $fileroot = "perltidy";
2080 $display_name = "<source_stream>";
2082 # If the source is from an array or string, then .LOG output
2083 # is only possible if a logfile stream is specified. This prevents
2084 # unexpected perltidy.LOG files. If the stream is not defined
2085 # then we will capture it in a string ref but it will not be
2086 # accessible. Previously by Perl::Tidy::DevNull (fix c255);
2087 if ( !defined($logfile_stream) ) {
2088 $logfile_stream = \my $tmp;
2090 # Likewise for .TEE and .DEBUG output
2092 if ( !defined($teefile_stream) ) {
2093 $teefile_stream = \my $tmp;
2095 if ( !defined($debugfile_stream) ) {
2096 $debugfile_stream = \my $tmp;
2099 elsif ( $input_file eq '-' ) { # '-' indicates input from STDIN
2100 $fileroot = "perltidy"; # root name to use for .ERR, .LOG, etc
2101 $display_name = "<stdin>";
2102 $in_place_modify = 0;
2105 $fileroot = $input_file;
2106 $display_name = $input_file;
2107 if ( !-e $input_file ) {
2108 Warn("skipping file: '$input_file': no matches found\n");
2112 if ( !-f $input_file ) {
2113 Warn("skipping file: $input_file: not a regular file\n");
2117 # As a safety precaution, skip zero length files.
2118 # If for example a source file got clobbered somehow,
2119 # the old .tdy or .bak files might still exist so we
2120 # shouldn't overwrite them with zero length files.
2121 if ( !-s $input_file ) {
2122 Warn("skipping file: $input_file: Zero size\n");
2126 # And avoid formatting extremely large files. Since perltidy reads
2127 # files into memory, trying to process an extremely large file
2128 # could cause system problems.
2129 my $size_in_mb = ( -s $input_file ) / ( CONST_1024 * CONST_1024 );
2130 my $maximum_file_size_mb = $rOpts->{'maximum-file-size-mb'};
2131 if ( $size_in_mb > $maximum_file_size_mb ) {
2132 $size_in_mb = sprintf( "%0.1f", $size_in_mb );
2134 "skipping file: $input_file: size $size_in_mb MB exceeds limit $maximum_file_size_mb; use -maxfs=i to change\n"
2139 if ( !-T $input_file && !$rOpts->{'force-read-binary'} ) {
2140 Warn("skipping file: $input_file: Non-text (override with -f)\n"
2145 # Input file must be writable for -b -bm='copy'. We must catch
2146 # this early to prevent encountering trouble after unlinking the
2148 if ( $in_place_modify && !-w $input_file ) {
2149 my $backup_method = $rOpts->{'backup-method'};
2150 if ( defined($backup_method) && $backup_method eq 'copy' ) {
2152 "skipping file '$input_file' for -b option: file reported as non-writable\n"
2158 # we should have a valid filename now
2159 $fileroot = $input_file;
2160 @input_file_stat = stat($input_file);
2162 if ( $OSNAME eq 'VMS' ) {
2163 ( $fileroot, $dot ) = check_vms_filename($fileroot);
2164 $self->[_file_extension_separator_] = $dot;
2167 # add option to change path here
2168 if ( defined( $rOpts->{'output-path'} ) ) {
2170 my ( $base, $old_path_uu ) = fileparse($fileroot);
2171 my $new_path = $rOpts->{'output-path'};
2172 if ( !-d $new_path ) {
2173 mkdir($new_path) # Default MODE is 0777
2175 Die("unable to create directory $new_path: $OS_ERROR\n");
2177 my $path = $new_path;
2178 $fileroot = File::Spec->catfile( $path, $base );
2181 ------------------------------------------------------------------------
2182 Problem combining $new_path and $base to make a filename; check -opath
2183 ------------------------------------------------------------------------
2189 # Skip files with same extension as the output files because
2190 # this can lead to a messy situation with files like
2191 # script.tdy.tdy.tdy ... or worse problems ... when you
2192 # rerun perltidy over and over with wildcard input.
2195 && ( $input_file =~ /$forbidden_file_extensions/
2196 || $input_file eq 'DIAGNOSTICS' )
2199 Warn("skipping file: $input_file: wrong extension\n");
2203 # copy source to a string buffer, decoding from utf8 if necessary
2208 $encoding_log_message,
2211 ) = $self->get_decoded_string_buffer( $input_file, $display_name );
2213 # Skip this file on any error
2214 next if ( !defined($rinput_string) );
2216 # Register this file name with the Diagnostics package, if any.
2217 $diagnostics_object->set_input_file($input_file)
2218 if $diagnostics_object;
2220 # The (possibly decoded) input is now in string ref $rinput_string.
2221 # Now prepare the output stream and error logger.
2223 #--------------------------
2224 # prepare the output stream
2225 #--------------------------
2227 my $output_name = EMPTY_STRING;
2228 my $actual_output_extension;
2230 if ( $rOpts->{'outfile'} ) {
2232 if ( $number_of_files <= 1 ) {
2234 if ( $rOpts->{'standard-output'} ) {
2235 my $saw_pbp = $self->[_saw_pbp_];
2236 my $msg = "You may not use -o and -st together";
2237 $msg .= " (-pbp contains -st; see manual)" if ($saw_pbp);
2241 if ($destination_stream) {
2243 "You may not specify a destination array and -o together\n"
2247 if ( defined( $rOpts->{'output-path'} ) ) {
2248 Die("You may not specify -o and -opath together\n");
2251 if ( defined( $rOpts->{'output-file-extension'} ) ) {
2252 Die("You may not specify -o and -oext together\n");
2255 $output_file = $rOpts->{outfile};
2256 $output_name = $output_file;
2258 # make sure user gives a file name after -o
2259 if ( $output_file =~ /^-/ ) {
2260 Die("You must specify a valid filename after -o\n");
2263 # do not overwrite input file with -o
2264 if ( @input_file_stat && ( $output_file eq $input_file ) ) {
2265 Die("Use 'perltidy -b $input_file' to modify in-place\n");
2269 Die("You may not use -o with more than one input file\n");
2272 elsif ( $rOpts->{'standard-output'} ) {
2273 if ($destination_stream) {
2274 my $saw_pbp = $self->[_saw_pbp_];
2276 "You may not specify a destination array and -st together\n";
2277 $msg .= " (-pbp contains -st; see manual)" if ($saw_pbp);
2281 $output_name = "<stdout>";
2283 if ( $number_of_files <= 1 ) {
2286 Die("You may not use -st with more than one input file\n");
2289 elsif ($destination_stream) {
2291 $output_file = $destination_stream;
2292 $output_name = "<destination_stream>";
2294 elsif ($source_stream) { # source but no destination goes to stdout
2296 $output_name = "<stdout>";
2298 elsif ( $input_file eq '-' ) {
2300 $output_name = "<stdout>";
2303 if ($in_place_modify) {
2304 $output_name = $display_name;
2307 $actual_output_extension = $output_extension;
2308 $output_file = $fileroot . $output_extension;
2309 $output_name = $output_file;
2313 # prepare standard output in case of a dump to stdout
2314 if ( $is_encoded_data && $self->[_dump_to_stdout_] ) {
2315 binmode *STDOUT, ':encoding(UTF-8)';
2318 $rstatus->{'file_count'} += 1;
2319 $rstatus->{'output_name'} = $output_name;
2320 $rstatus->{'iteration_count'} = 0;
2321 $rstatus->{'converged'} = 0;
2323 #------------------------------------------
2324 # initialize the error logger for this file
2325 #------------------------------------------
2326 my $warning_file = $fileroot . $dot . "ERR";
2327 if ($errorfile_stream) { $warning_file = $errorfile_stream }
2328 my $log_file = $fileroot . $dot . "LOG";
2329 if ($logfile_stream) { $log_file = $logfile_stream }
2331 # The logger object handles warning messages, logfile messages,
2332 # and can supply basic run information to lower level routines.
2333 my $logger_object = Perl::Tidy::Logger->new(
2335 log_file => $log_file,
2336 warning_file => $warning_file,
2337 fh_stderr => $fh_stderr,
2338 display_name => $display_name,
2339 is_encoded_data => $is_encoded_data,
2341 $logger_object->write_logfile_entry($logfile_header);
2342 $logger_object->write_logfile_entry($encoding_log_message)
2343 if $encoding_log_message;
2345 # Now we can add any pending messages to the log
2346 if ( ${$rpending_logfile_message} ) {
2347 $logger_object->write_logfile_entry( ${$rpending_logfile_message} );
2349 if ( ${$rpending_complaint} ) {
2350 $logger_object->complain( ${$rpending_complaint} );
2353 # additional parameters needed by lower level routines
2354 $self->[_actual_output_extension_] = $actual_output_extension;
2355 $self->[_debugfile_stream_] = $debugfile_stream;
2356 $self->[_decoded_input_as_] = $decoded_input_as;
2357 $self->[_destination_stream_] = $destination_stream;
2358 $self->[_display_name_] = $display_name;
2359 $self->[_fileroot_] = $fileroot;
2360 $self->[_is_encoded_data_] = $is_encoded_data;
2361 $self->[_length_function_] = $length_function;
2362 $self->[_logger_object_] = $logger_object;
2363 $self->[_output_file_] = $output_file;
2364 $self->[_teefile_stream_] = $teefile_stream;
2365 $self->[_input_copied_verbatim_] = 0;
2366 $self->[_input_output_difference_] = 1; ## updated later if -b used
2368 #--------------------
2369 # process this buffer
2370 #--------------------
2371 my $routput_string = $self->process_filter_layer($rinput_string);
2373 #------------------------------------------------
2374 # send the tidied output to its final destination
2375 #------------------------------------------------
2376 if ( $rOpts->{'format'} eq 'tidy' && defined($routput_string) ) {
2378 $self->write_tidy_output(
2380 routput_string => $routput_string,
2381 rinput_file_stat => \@input_file_stat,
2382 in_place_modify => $in_place_modify,
2383 input_file => $input_file,
2384 backup_extension => $backup_extension,
2385 delete_backup => $delete_backup,
2390 $logger_object->finish()
2392 } ## end loop over files
2395 } ## end sub process_all_files
2397 sub write_tidy_output {
2399 my ( $self, $rcall_hash ) = @_;
2401 # Write tidied output in '$routput_string' to its final destination
2403 my $routput_string = $rcall_hash->{routput_string};
2404 my $rinput_file_stat = $rcall_hash->{rinput_file_stat};
2405 my $in_place_modify = $rcall_hash->{in_place_modify};
2406 my $input_file = $rcall_hash->{input_file};
2407 my $backup_extension = $rcall_hash->{backup_extension};
2408 my $delete_backup = $rcall_hash->{delete_backup};
2410 my $rOpts = $self->[_rOpts_];
2411 my $is_encoded_data = $self->[_is_encoded_data_];
2412 my $output_file = $self->[_output_file_];
2414 # There are three main output paths:
2416 #-------------------------------------------------------------------------
2417 # PATH 1: $output_file is not defined: --backup and modify in-place option
2418 #-------------------------------------------------------------------------
2419 if ($in_place_modify) {
2421 # For -b option, leave the file unchanged if a severe error caused
2422 # formatting to be skipped. Otherwise we will overwrite any backup.
2423 if ( !$self->[_input_copied_verbatim_] ) {
2425 my $backup_method = $rOpts->{'backup-method'};
2427 #-------------------------------------------------------------
2428 # PATH 1a: -bm='copy': uses newer version in which original is
2429 # copied to the backup and rewritten; see git #103.
2430 #-------------------------------------------------------------
2431 if ( defined($backup_method) && $backup_method eq 'copy' ) {
2432 $self->backup_method_copy(
2433 $input_file, $routput_string,
2434 $backup_extension, $delete_backup
2438 #-------------------------------------------------------------
2439 # PATH 1b: -bm='move': uses older version, where original is
2440 # moved to the backup and formatted output goes to a new file.
2441 #-------------------------------------------------------------
2443 $self->backup_method_move(
2444 $input_file, $routput_string,
2445 $backup_extension, $delete_backup
2451 #--------------------------------------------------------------------------
2452 # PATH 2: $output_file is a reference (=destination_stream): send output to
2453 # a destination stream ref received from an external perl program. We use
2454 # a sub to do this because the encoding rules are a bit tricky.
2455 #--------------------------------------------------------------------------
2456 elsif ( ref($output_file) ) {
2457 $self->copy_buffer_to_external_ref( $routput_string, $output_file );
2460 #--------------------------------------------------------------------------
2461 # PATH 3: $output_file is named file or '-'; send output to the file system
2462 #--------------------------------------------------------------------------
2465 #--------------------------
2466 # PATH 3a: output to STDOUT
2467 #--------------------------
2468 if ( $output_file eq '-' ) {
2470 if ($is_encoded_data) { binmode $fh, ":raw:encoding(UTF-8)" }
2471 else { binmode $fh }
2472 $fh->print( ${$routput_string} );
2475 #--------------------------------
2476 # PATH 3b: output to a named file
2477 #--------------------------------
2479 if ( open( my $fh, '>', $output_file ) ) {
2480 if ($is_encoded_data) { binmode $fh, ":raw:encoding(UTF-8)" }
2481 else { binmode $fh }
2482 $fh->print( ${$routput_string} );
2483 $fh->close() or Die("Cannot close '$output_file': $OS_ERROR\n");
2486 Die("Cannot open $output_file to write: $OS_ERROR\n");
2489 # set output file ownership and permissions if appropriate
2490 if ( $output_file && -f $output_file && !-l $output_file ) {
2491 if ( @{$rinput_file_stat} ) {
2492 $self->set_output_file_permissions( $output_file,
2493 \@{$rinput_file_stat}, $in_place_modify );
2498 # Save diagnostic info
2499 if ($is_encoded_data) {
2500 $rstatus->{'output_encoded_as'} = 'UTF-8';
2506 } ## end sub write_tidy_output
2508 sub process_filter_layer {
2510 my ( $self, $rinput_string ) = @_;
2512 # This is the filter layer of processing.
2513 # Do all requested formatting on the string ref '$rinput_string', including
2514 # any pre- and post-processing with filters.
2516 # $routput_string = ref to tidied output if in 'tidy' mode
2517 # (nothing) if not in 'tidy' mode [these modes handle output separately]
2519 # Total formatting is done with these layers of subroutines:
2520 # perltidy - main routine; checks run parameters
2521 # process_all_files - main loop to process all files;
2522 # *process_filter_layer - do any pre and post processing; *THIS LAYER
2523 # process_iteration_layer - handle any iterations on formatting
2524 # process_single_case - solves one formatting problem
2526 # Data Flow in this layer:
2528 # -> optional prefilter operations
2529 # -> [ formatting by sub process_iteration_layer ]
2530 # -> return if not in 'tidy' mode
2531 # -> optional postfilter operations
2532 # -> $routput_string
2534 # What is done based on format type:
2535 # utf8 decoding is done for all format types
2536 # prefiltering is applied to all format types
2537 # - because it may be needed to get through the tokenizer
2538 # postfiltering is only done for format='tidy'
2539 # - not appropriate for html text, which has already been output
2540 # encoding of decoded output is only done for format='tidy'
2541 # - because html does its own encoding; user formatter does what it wants
2543 # Be sure the string we received is defined
2544 if ( !defined($rinput_string) ) {
2545 Fault("bad call: the source string ref \$rinput_string is undefined\n");
2547 if ( ref($rinput_string) ne 'SCALAR' ) {
2548 Fault("bad call: the source string ref is not SCALAR\n");
2551 my $rOpts = $self->[_rOpts_];
2552 my $logger_object = $self->[_logger_object_];
2554 # vars for --line-range-tidy filter, if needed
2555 my @input_lines_pre;
2556 my @input_lines_post;
2558 # vars for checking assertions, if needed
2560 my $saved_input_buf;
2562 # var for checking --noadd-terminal-newline
2563 my $chomp_terminal_newline;
2565 # Setup post-filter vars; these apply to 'tidy' mode only
2566 if ( $rOpts->{'format'} eq 'tidy' ) {
2568 #---------------------------------------------------------------------
2569 # for --line-range-tidy, clip '$rinput_string' to a limited line range
2570 #---------------------------------------------------------------------
2571 my $line_tidy_begin = $self->[_line_tidy_begin_];
2572 if ($line_tidy_begin) {
2574 my @input_lines = split /^/, ${$rinput_string};
2576 my $num = @input_lines;
2577 if ( $line_tidy_begin > $num ) {
2579 #--line-range-tidy=n1:n2 has n1=$line_tidy_begin which exceeds max line number of $num
2583 my $line_tidy_end = $self->[_line_tidy_end_];
2584 if ( !defined($line_tidy_end) || $line_tidy_end > $num ) {
2585 $line_tidy_end = $num;
2587 my $input_string = join EMPTY_STRING,
2588 @input_lines[ $line_tidy_begin - 1 .. $line_tidy_end - 1 ];
2589 $rinput_string = \$input_string;
2591 @input_lines_pre = @input_lines[ 0 .. $line_tidy_begin - 2 ];
2592 @input_lines_post = @input_lines[ $line_tidy_end .. $num - 1 ];
2596 #------------------------------------------
2597 # evaluate MD5 sum of input file, if needed
2598 #------------------------------------------
2599 if ( $rOpts->{'assert-tidy'}
2600 || $rOpts->{'assert-untidy'}
2601 || $rOpts->{'backup-and-modify-in-place'} )
2603 $digest_input = $md5_hex->( ${$rinput_string} );
2604 $saved_input_buf = ${$rinput_string};
2607 # When -noadd-terminal-newline is set, and the input does not
2608 # have a newline, then we remove the final newline of the output
2609 $chomp_terminal_newline = !$rOpts->{'add-terminal-newline'}
2610 && substr( ${$rinput_string}, -1, 1 ) !~ /\n/;
2614 #-----------------------------------------------------------------------
2615 # Apply any prefilter. The prefilter is a code reference that will be
2616 # applied to the source before tokenizing. Note that we are doing this
2617 # for all format types ('tidy', 'html', 'user') because it may be needed
2618 # to avoid tokenization errors.
2619 #-----------------------------------------------------------------------
2620 my $prefilter = $self->[_prefilter_];
2622 my $input_string = $prefilter->( ${$rinput_string} );
2623 $rinput_string = \$input_string;
2626 #-------------------------------------------
2627 # Format contents of string '$rinput_string'
2628 #-------------------------------------------
2629 my $routput_string = $self->process_iteration_layer($rinput_string);
2631 #-------------------------------
2632 # All done if not in 'tidy' mode
2633 #-------------------------------
2634 if ( $rOpts->{'format'} ne 'tidy' ) {
2638 #---------------------
2639 # apply any postfilter
2640 #---------------------
2641 my $postfilter = $self->[_postfilter_];
2643 my $output_string = $postfilter->( ${$routput_string} );
2644 $routput_string = \$output_string;
2647 if ( defined($digest_input) ) {
2648 my $digest_output = $md5_hex->( ${$routput_string} );
2649 $self->[_input_output_difference_] = $digest_output ne $digest_input;
2652 #-----------------------------------------------------
2653 # check for changes if requested by 'assert-...' flags
2654 #-----------------------------------------------------
2655 if ( $rOpts->{'assert-tidy'} ) {
2656 if ( $self->[_input_output_difference_] ) {
2658 compare_string_buffers( \$saved_input_buf, $routput_string );
2659 $logger_object->warning(<<EOM);
2660 assertion failure: '--assert-tidy' is set but output differs from input
2662 $logger_object->interrupt_logfile();
2663 $logger_object->warning( $diff_msg . "\n" );
2664 $logger_object->resume_logfile();
2668 if ( $rOpts->{'assert-untidy'} ) {
2669 if ( !$self->[_input_output_difference_] ) {
2670 $logger_object->warning(
2671 "assertion failure: '--assert-untidy' is set but output equals input\n"
2676 #----------------------------------------
2677 # do --line-range-tidy line recombination
2678 #----------------------------------------
2679 if ( @input_lines_pre || @input_lines_post ) {
2680 my $str_pre = join EMPTY_STRING, @input_lines_pre;
2681 my $str_post = join EMPTY_STRING, @input_lines_post;
2682 my $output_string = $str_pre . ${$routput_string} . $str_post;
2683 $routput_string = \$output_string;
2686 #-----------------------------------------
2687 # handle a '--noadd-terminal-newline' flag
2688 #-----------------------------------------
2689 if ($chomp_terminal_newline) {
2690 chomp ${$routput_string};
2693 #-------------------------------------------------------------
2694 # handle --preserve-line-endings or -output-line-endings flags
2695 #-------------------------------------------------------------
2696 # The native line separator has been used in all intermediate
2697 # iterations and filter operations until here so that string
2698 # operations work ok.
2699 if ( $self->[_line_separator_] ne "\n" ) {
2700 my $line_separator = $self->[_line_separator_];
2701 my @output_lines = split /^/, ${$routput_string};
2702 foreach my $line (@output_lines) {
2704 # must check chomp because last line might not have a newline
2705 # if --noadd-terminal-newline is also set (c283)
2706 if ( chomp $line ) {
2707 $line .= $line_separator;
2710 my $output_string = join EMPTY_STRING, @output_lines;
2711 $routput_string = \$output_string;
2714 return $routput_string;
2715 } ## end sub process_filter_layer
2717 # For safety, set an upper bound on number of iterations before stopping.
2718 # The average number of iterations is 2. No known cases exceed 4.
2719 use constant ITERATION_LIMIT => 6;
2721 sub process_iteration_layer {
2723 my ( $self, $rinput_string ) = @_;
2725 # This is the iteration layer of processing.
2726 # Do all formatting, iterating if requested, on the source $rinput_string
2727 # Output depends on format type:
2728 # For 'tidy' formatting, output goes to sink object
2729 # For 'html' formatting, output goes to the ultimate destination
2730 # For 'user' formatting, user formatter handles output
2732 # Total formatting is done with these layers of subroutines:
2733 # perltidy - main routine; checks run parameters
2734 # process_all_files - main loop to process all files;
2735 # process_filter_layer - do any pre and post processing
2736 # *process_iteration_layer - do any iterations on formatting; *THIS LAYER
2737 # process_single_case - solves one formatting problem
2739 # Data Flow in this layer:
2740 # $rinput_string -> [ loop over iterations ] -> $routput_string
2742 my $diagnostics_object = $self->[_diagnostics_object_];
2743 my $display_name = $self->[_display_name_];
2744 my $fileroot = $self->[_fileroot_];
2745 my $is_encoded_data = $self->[_is_encoded_data_];
2746 my $length_function = $self->[_length_function_];
2747 my $logger_object = $self->[_logger_object_];
2748 my $rOpts = $self->[_rOpts_];
2749 my $user_formatter = $self->[_user_formatter_];
2751 # make a debugger object if requested
2752 my $debugger_object;
2753 if ( $rOpts->{DEBUG} ) {
2754 my $debug_file = $self->[_debugfile_stream_]
2755 || $fileroot . $self->make_file_extension('DEBUG');
2757 Perl::Tidy::Debugger->new( $debug_file, $is_encoded_data );
2760 # make a tee file handle if requested
2763 if ( $rOpts->{'tee-pod'}
2764 || $rOpts->{'tee-block-comments'}
2765 || $rOpts->{'tee-side-comments'} )
2767 $tee_file = $self->[_teefile_stream_]
2768 || $fileroot . $self->make_file_extension('TEE');
2769 $fh_tee = Perl::Tidy::streamhandle( $tee_file, 'w', $is_encoded_data );
2771 Warn("couldn't open TEE file $tee_file: $OS_ERROR\n");
2775 # vars for iterations and convergence test
2776 my $max_iterations = 1;
2777 my $convergence_log_message;
2780 # Only 'tidy' formatting can use multiple iterations
2781 if ( $rOpts->{'format'} eq 'tidy' ) {
2783 # check iteration count and quietly fix if necessary:
2784 # - iterations option only applies to code beautification mode
2785 # - the convergence check should stop most runs on iteration 2, and
2786 # virtually all on iteration 3. We allow up to ITERATION_LIMIT.
2787 $max_iterations = $rOpts->{'iterations'};
2788 if ( !defined($max_iterations)
2789 || $max_iterations <= 0 )
2791 $max_iterations = 1;
2794 if ( $max_iterations > ITERATION_LIMIT ) {
2795 $max_iterations = ITERATION_LIMIT;
2798 # get starting MD5 sum for convergence test
2799 if ( $max_iterations > 1 ) {
2800 my $digest = $md5_hex->( ${$rinput_string} );
2801 $saw_md5{$digest} = 0;
2805 # save objects to allow redirecting output during iterations
2806 my $logger_object_final = $logger_object;
2807 my $iteration_of_formatter_convergence;
2810 #---------------------
2811 # Loop over iterations
2812 #---------------------
2813 foreach my $iter ( 1 .. $max_iterations ) {
2815 $rstatus->{'iteration_count'} += 1;
2817 # create a string to capture the output
2818 my $sink_buffer = EMPTY_STRING;
2819 $routput_string = \$sink_buffer;
2821 # Save logger, debugger and tee output only on pass 1 because:
2822 # (1) line number references must be to the starting
2823 # source, not an intermediate result, and
2824 # (2) we need to know if there are errors so we can stop the
2825 # iterations early if necessary.
2826 # (3) the tee option only works on first pass if comments are also
2830 $debugger_object->close_debug_file()
2831 if ($debugger_object);
2834 && $fh_tee->can('close')
2836 && $tee_file ne '-' )
2839 or Warn("couldn't close TEE file $tee_file: $OS_ERROR\n");
2842 $debugger_object = undef;
2843 $logger_object = undef;
2847 #---------------------------------
2848 # create a formatter for this file
2849 #---------------------------------
2853 if ($user_formatter) {
2854 $formatter = $user_formatter;
2856 elsif ( $rOpts->{'format'} eq 'html' ) {
2858 my $html_toc_extension =
2859 $self->make_file_extension( $rOpts->{'html-toc-extension'},
2862 my $html_src_extension =
2863 $self->make_file_extension( $rOpts->{'html-src-extension'},
2866 $formatter = Perl::Tidy::HtmlWriter->new(
2867 input_file => $fileroot,
2868 html_file => $self->[_output_file_],
2869 extension => $self->[_actual_output_extension_],
2870 html_toc_extension => $html_toc_extension,
2871 html_src_extension => $html_src_extension,
2874 elsif ( $rOpts->{'format'} eq 'tidy' ) {
2875 $formatter = Perl::Tidy::Formatter->new(
2876 logger_object => $logger_object,
2877 diagnostics_object => $diagnostics_object,
2878 sink_object => $routput_string,
2879 length_function => $length_function,
2880 is_encoded_data => $is_encoded_data,
2885 Die("I don't know how to do -format=$rOpts->{'format'}\n");
2888 if ( !$formatter ) {
2889 Die("Unable to continue with $rOpts->{'format'} formatting\n");
2892 #-----------------------------------
2893 # create the tokenizer for this file
2894 #-----------------------------------
2895 my $tokenizer = Perl::Tidy::Tokenizer->new(
2896 source_object => $rinput_string,
2897 logger_object => $logger_object,
2898 debugger_object => $debugger_object,
2899 diagnostics_object => $diagnostics_object,
2901 starting_level => $rOpts->{'starting-indentation-level'},
2904 #---------------------------------
2905 # do processing for this iteration
2906 #---------------------------------
2907 $self->process_single_case( $tokenizer, $formatter );
2913 # see if the formatter is converged
2914 if ( $max_iterations > 1
2915 && !defined($iteration_of_formatter_convergence)
2916 && $formatter->can('get_convergence_check') )
2918 if ( $formatter->get_convergence_check() ) {
2919 $iteration_of_formatter_convergence = $iter;
2920 $rstatus->{'converged'} = 1;
2924 # line source for next iteration (if any) comes from the current
2925 # temporary output buffer
2926 if ( $iter < $max_iterations ) {
2928 $rinput_string = \$sink_buffer;
2930 # stop iterations if errors or converged
2931 my $stop_now = $self->[_input_copied_verbatim_];
2932 $stop_now ||= $tokenizer->get_unexpected_error_count();
2933 my $stopping_on_error = $stop_now;
2935 $convergence_log_message = <<EOM;
2936 Stopping iterations because of severe errors.
2940 # or do convergence test
2943 # stop if the formatter has converged
2944 $stop_now ||= defined($iteration_of_formatter_convergence);
2946 my $digest = $md5_hex->($sink_buffer);
2947 if ( !defined( $saw_md5{$digest} ) ) {
2948 $saw_md5{$digest} = $iter;
2951 # do a second iteration if all ok and requested by formatter
2952 # to allow delayed adding/deleting of commas (git156, git143)
2955 && $formatter->can('want_second_iteration')
2956 && $formatter->want_second_iteration() )
2958 ## deja vu, but do not set $stop_now
2959 $saw_md5{$digest} = $iter;
2963 # Deja vu, stop iterating
2966 my $iterm = $iter - 1;
2967 if ( $saw_md5{$digest} != $iterm ) {
2969 # Blinking (oscillating) between two or more stable
2970 # end states. This is unlikely to occur with normal
2971 # parameters, but it can occur in stress testing
2972 # with extreme parameter values, such as very short
2973 # maximum line lengths. We want to catch and fix
2974 # them when they happen.
2975 $rstatus->{'blinking'} = 1;
2976 $convergence_log_message = <<EOM;
2977 BLINKER. Output for iteration $iter same as for $saw_md5{$digest}.
2979 $stopping_on_error ||= $convergence_log_message;
2981 && print {*STDERR} $convergence_log_message;
2982 $diagnostics_object->write_diagnostics(
2983 $convergence_log_message)
2984 if $diagnostics_object;
2986 # Uncomment to search for blinking states
2987 # Warn( "$display_name: blinking; iter $iter same as for $saw_md5{$digest}\n" );
2991 $convergence_log_message = <<EOM;
2992 Converged. Output for iteration $iter same as for iter $iterm.
2994 $diagnostics_object->write_diagnostics(
2995 $convergence_log_message)
2996 if $diagnostics_object && $iterm > 2;
2997 $rstatus->{'converged'} = 1;
3006 if ( defined($iteration_of_formatter_convergence) ) {
3008 # This message cannot appear unless the formatter
3009 # convergence test above is temporarily skipped for
3011 if ( $iteration_of_formatter_convergence < $iter - 1 ) {
3013 "STRANGE Early conv in $display_name: Stopping on it=$iter, converged in formatter on $iteration_of_formatter_convergence\n";
3016 elsif ( !$stopping_on_error ) {
3018 # The md5 sum implies convergence but the convergence
3019 # was not detected by the Formatter. This is not
3020 # critical but should be investigated. It happened
3021 # once when a line break was placed before a phantom
3022 # comma under -qwaf, and has been fixed.
3024 "STRANGE no conv in $display_name: stopping on it=$iter, but not converged in formatter\n";
3031 # we are stopping the iterations early;
3034 } ## end if ( $iter < $max_iterations)
3035 } ## end loop over iterations for one source file
3037 $debugger_object->close_debug_file()
3038 if $debugger_object;
3041 && $fh_tee->can('close')
3043 && $tee_file ne '-' )
3046 or Warn("couldn't close TEE file $tee_file: $OS_ERROR\n");
3049 # leave logger object open for additional messages
3050 $logger_object = $logger_object_final;
3051 $logger_object->write_logfile_entry($convergence_log_message)
3052 if $convergence_log_message;
3054 return $routput_string;
3056 } ## end sub process_iteration_layer
3058 sub process_single_case {
3060 my ( $self, $tokenizer, $formatter ) = @_;
3062 # Run the formatter on a single defined case
3064 # Total formatting is done with these layers of subroutines:
3065 # perltidy - main routine; checks run parameters
3066 # process_all_files - main loop to process all files;
3067 # process_filter_layer - do any pre and post processing;
3068 # process_iteration_layer - do any iterations on formatting
3069 # *process_single_case - solve one formatting problem; *THIS LAYER
3071 while ( my $line = $tokenizer->get_line() ) {
3072 $formatter->write_line($line);
3075 # user-defined formatters are possible, and may not have a
3076 # sub 'finish_formatting', so we have to check
3077 if ( $formatter->can('finish_formatting') ) {
3078 my $severe_error = $tokenizer->report_tokenization_errors();
3079 my $verbatim = $formatter->finish_formatting($severe_error);
3080 $self->[_input_copied_verbatim_] = $verbatim;
3084 } ## end sub process_single_case
3086 sub copy_buffer_to_external_ref {
3088 my ( $self, $routput, $destination_stream ) = @_;
3090 # Copy $routput to the final $destination_stream,
3091 # encoding if the flag $encode_destination_buffer is true.
3094 # $destination_buffer -> [ encode? ] -> $destination_stream
3096 my $destination_buffer = EMPTY_STRING;
3097 if ( ref($routput) eq 'ARRAY' ) {
3098 $destination_buffer = join EMPTY_STRING, @{$routput};
3100 elsif ( ref($routput) eq 'SCALAR' ) {
3101 $destination_buffer = ${$routput};
3105 "'copy_buffer_to_external_ref' expecting ref to ARRAY or SCALAR\n");
3108 $rstatus->{'output_encoded_as'} = EMPTY_STRING;
3109 my $ref_destination_stream = ref($destination_stream);
3111 # Encode output? Strings and arrays use special encoding rules; see:
3112 # https://github.com/perltidy/perltidy/blob/master/docs/eos_flag.md
3113 my $encode_destination_buffer;
3114 if ( $ref_destination_stream eq 'SCALAR'
3115 || $ref_destination_stream eq 'ARRAY' )
3117 my $rOpts = $self->[_rOpts_];
3118 $encode_destination_buffer =
3119 $rOpts->{'encode-output-strings'} && $self->[_decoded_input_as_];
3122 # An object with a print method will use file encoding rules
3123 elsif ( $ref_destination_stream->can('print') ) {
3124 $encode_destination_buffer = $self->[_is_encoded_data_];
3128 ------------------------------------------------------------------------
3129 No 'print' method is defined for object of class '$ref_destination_stream'
3130 Please check your call to Perl::Tidy::perltidy. Trace follows.
3131 ------------------------------------------------------------------------
3135 if ($encode_destination_buffer) {
3140 Encode::encode( "UTF-8", $destination_buffer,
3141 Encode::FB_CROAK | Encode::LEAVE_SRC );
3148 "Error attempting to encode output string ref; encoding not done\n"
3152 $destination_buffer = $encoded_buffer;
3153 $rstatus->{'output_encoded_as'} = 'UTF-8';
3157 # Send data for SCALAR, ARRAY & OBJ refs to its final destination
3158 if ( $ref_destination_stream eq 'SCALAR' ) {
3159 ${$destination_stream} = $destination_buffer;
3161 elsif ( defined($destination_buffer) ) {
3162 my @lines = split /^/, $destination_buffer;
3163 if ( $ref_destination_stream eq 'ARRAY' ) {
3164 @{$destination_stream} = @lines;
3167 # destination stream must be an object with print method
3169 foreach my $line (@lines) {
3170 $destination_stream->print($line);
3172 if ( $ref_destination_stream->can('close') ) {
3173 $destination_stream->close();
3179 # Empty destination buffer not going to a string ... could
3180 # happen for example if user deleted all pod or comments
3183 } ## end sub copy_buffer_to_external_ref
3185 } ## end of closure for sub perltidy
3189 my ( $s1, $s2 ) = @_;
3191 # Given two strings, Return
3192 # $diff_marker = a string with caret (^) symbols indicating differences
3193 # $pos1 = character position of first difference; pos1=-1 if no difference
3195 # Form exclusive or of the strings, which has null characters where strings
3196 # have same common characters so non-null characters indicate character
3198 my $diff_marker = EMPTY_STRING;
3201 if ( defined($s1) && defined($s2) ) {
3202 my $mask = $s1 ^ $s2;
3204 while ( $mask =~ /[^\0]/g ) {
3205 my $pos_last = $pos;
3206 $pos = $LAST_MATCH_START[0];
3207 if ( $pos1 < 0 ) { $pos1 = $pos; }
3208 $diff_marker .= SPACE x ( $pos - $pos_last - 1 ) . '^';
3210 # we could continue to mark all differences, but there is no point
3212 } ## end while ( $mask =~ /[^\0]/g)
3214 return ( $diff_marker, $pos1 );
3215 } ## end sub line_diff
3217 sub compare_string_buffers {
3219 my ( $string_i, $string_o, ($max_diff_count) ) = @_;
3221 # Compare input and output string buffers and return a brief text
3222 # description of the first difference.
3225 # $string_i = input string, or ref to input string
3226 # $string_o = output string, or ref to output string
3227 # $max_diff_count = optional maximum number of differences to show,
3230 # a string showing differences
3232 my $rbufi = ref($string_i) ? $string_i : \$string_i;
3233 my $rbufo = ref($string_o) ? $string_o : \$string_o;
3235 if ( !defined($max_diff_count) ) { $max_diff_count = 1 }
3237 my ( @aryi, @aryo );
3238 my ( $leni, $leno ) = ( 0, 0 );
3239 if ( defined($rbufi) ) {
3240 $leni = length( ${$rbufi} );
3241 @aryi = split /^/, ${$rbufi};
3243 if ( defined($rbufo) ) {
3244 $leno = length( ${$rbufo} );
3245 @aryo = split /^/, ${$rbufo};
3247 my $nlines_i = @aryi;
3248 my $nlines_o = @aryo;
3250 Input file length has $leni chars in $nlines_i lines
3251 Output file length has $leno chars in $nlines_o lines
3253 return $msg unless ( $leni && $leno );
3255 my $truncate = sub {
3256 my ( $str, $lenmax ) = @_;
3257 if ( length($str) > $lenmax ) {
3258 $str = substr( $str, 0, $lenmax ) . "...";
3261 }; ## end $truncate = sub
3263 my $last_nonblank_line = EMPTY_STRING;
3264 my $last_nonblank_count = 0;
3266 # loop over lines until we find a difference
3269 while ( @aryi && @aryo ) {
3271 my $linei = shift @aryi;
3272 my $lineo = shift @aryo;
3275 if ( $linei eq $lineo ) {
3276 if ( length($linei) ) {
3277 $last_nonblank_line = $linei;
3278 $last_nonblank_count = $count;
3283 #---------------------------
3284 # lines differ ... finish up
3285 #---------------------------
3286 my ( $line_diff, $pos1 ) = line_diff( $linei, $lineo );
3287 my $ch1 = $pos1 + 1;
3288 my $reason = "Files first differ at character $ch1 of line $count";
3290 my ( $leading_ws_i, $leading_ws_o ) = ( EMPTY_STRING, EMPTY_STRING );
3291 if ( $linei =~ /^(\s+)/ ) { $leading_ws_i = $1; }
3292 if ( $lineo =~ /^(\s+)/ ) { $leading_ws_o = $1; }
3293 if ( $leading_ws_i ne $leading_ws_o ) {
3294 $reason .= "; leading whitespace differs";
3295 if ( $leading_ws_i =~ /\t/ ) {
3296 $reason .= "; input has tab char";
3300 my ( $trailing_ws_i, $trailing_ws_o ) =
3301 ( EMPTY_STRING, EMPTY_STRING );
3302 if ( $linei =~ /(\s+)$/ ) { $trailing_ws_i = $1; }
3303 if ( $lineo =~ /(\s+)$/ ) { $trailing_ws_o = $1; }
3304 if ( $trailing_ws_i ne $trailing_ws_o ) {
3305 $reason .= "; trailing whitespace differs";
3308 $msg .= $reason . "\n";
3310 # limit string display length
3312 my $drop = $pos1 - 40;
3313 $linei = "..." . substr( $linei, $drop );
3314 $lineo = "..." . substr( $lineo, $drop );
3315 $line_diff = SPACE x 3 . substr( $line_diff, $drop );
3317 $linei = $truncate->( $linei, 72 );
3318 $lineo = $truncate->( $lineo, 72 );
3319 $last_nonblank_line = $truncate->( $last_nonblank_line, 72 );
3321 if ($last_nonblank_line) {
3323 $last_nonblank_count:$last_nonblank_line
3326 $line_diff = SPACE x ( 2 + length($count) ) . $line_diff;
3333 last if ( $diff_count >= $max_diff_count );
3334 } ## end while ( @aryi && @aryo )
3336 if ($diff_count) { return $msg }
3338 #------------------------------------------------------
3339 # no differences found, see if one file has fewer lines
3340 #------------------------------------------------------
3341 if ( $nlines_i > $nlines_o ) {
3343 Files initially match file but output file has fewer lines
3346 elsif ( $nlines_i < $nlines_o ) {
3348 Files initially match file but input file has fewer lines
3353 Text in lines of file match but checksums differ. Perhaps line endings differ.
3357 } ## end sub compare_string_buffers
3359 sub fileglob_to_re {
3361 # modified (corrected) from version in find2perl
3363 $x =~ s/([.\/^\$()])/\\$1/g; # escape special characters
3364 $x =~ s/\*/.*/g; # '*' -> '.*'
3365 $x =~ s/\?/./g; # '?' -> '.'
3366 return "^$x\\z"; # match whole word
3367 } ## end sub fileglob_to_re
3369 sub make_logfile_header {
3370 my ( $rOpts, $config_file, $rraw_options, $Windows_type, $readable_options )
3373 # Note: the punctuation variable '$]' is not in older versions of
3374 # English.pm so leave it as is to avoid failing installation tests.
3376 "perltidy version $VERSION log file on a $OSNAME system, OLD_PERL_VERSION=$]\n";
3377 if ($Windows_type) {
3378 $msg .= "Windows type is $Windows_type\n";
3380 my $options_string = join( SPACE, @{$rraw_options} );
3382 if ( defined($config_file) ) {
3383 $msg .= "Found Configuration File >>> $config_file \n";
3385 $msg .= "Configuration and command line parameters for this run:\n";
3386 $msg .= "$options_string\n";
3388 if ( $rOpts->{'show-options'} ) {
3389 $rOpts->{'logfile'} = 1; # force logfile to be saved
3390 $msg .= "Final parameter set for this run\n";
3391 $msg .= "------------------------------------\n";
3393 $msg .= $readable_options;
3395 $msg .= "------------------------------------\n";
3397 $msg .= "To find error messages search for 'WARNING' with your editor\n";
3399 } ## end sub make_logfile_header
3401 sub generate_options {
3403 ######################################################################
3404 # Generate and return references to:
3405 # @option_string - the list of options to be passed to Getopt::Long
3406 # @defaults - the list of default options
3407 # %expansion - a hash showing how all abbreviations are expanded
3408 # %category - a hash giving the general category of each option
3409 # %option_range - a hash giving the valid ranges of certain options
3411 # Note: a few options are not documented in the man page and usage
3412 # message. This is because these are deprecated, experimental or debug
3413 # options and may or may not be retained in future versions:
3415 # These undocumented flags are accepted but not used:
3417 # --fuzzy-line-length
3419 # These undocumented flags are for debugging:
3420 # --recombine # used to debug line breaks
3421 # --short-concatenation-item-length # used to break a '.' chain
3423 ######################################################################
3425 # here is a summary of the Getopt codes:
3426 # <none> does not take an argument
3427 # =s takes a mandatory string
3428 # :s takes an optional string (DO NOT USE - filenames will get eaten up)
3429 # =i takes a mandatory integer
3430 # :i takes an optional integer (NOT RECOMMENDED - can cause trouble)
3431 # ! does not take an argument and may be negated
3432 # i.e., -foo and -nofoo are allowed
3433 # a double dash signals the end of the options list
3435 #-----------------------------------------------
3436 # Define the option string passed to GetOptions.
3437 #-----------------------------------------------
3439 my @option_string = ();
3441 my %option_category = ();
3442 my %option_range = ();
3443 my %integer_option_range;
3445 # names of categories in manual
3446 # leading integers will allow sorting
3447 my @category_name = (
3449 '1. Basic formatting options',
3450 '2. Code indentation control',
3451 '3. Whitespace control',
3452 '4. Comment controls',
3453 '5. Linebreak controls',
3454 '6. Controlling list formatting',
3455 '7. Retaining or ignoring existing line breaks',
3456 '8. Blank line control',
3457 '9. Other controls',
3459 '11. pod2html options',
3460 '12. Controlling HTML properties',
3464 # These options are parsed directly by perltidy:
3467 # However, they are included in the option set so that they will
3468 # be seen in the options dump.
3470 # These long option names have no abbreviations or are treated specially
3471 @option_string = qw(
3480 my $category = 13; # Debugging
3481 foreach (@option_string) {
3482 my $opt = $_; # must avoid changing the actual flag
3484 $option_category{$opt} = $category_name[$category];
3487 $category = 11; # HTML
3488 $option_category{html} = $category_name[$category];
3490 # routine to install and check options
3491 my $add_option = sub {
3492 my ( $long_name, $short_name, $flag ) = @_;
3493 push @option_string, $long_name . $flag;
3494 $option_category{$long_name} = $category_name[$category];
3496 if ( $expansion{$short_name} ) {
3497 my $existing_name = $expansion{$short_name}->[0];
3499 "redefining abbreviation $short_name for $long_name; already used for $existing_name\n"
3502 $expansion{$short_name} = [$long_name];
3503 if ( $flag eq '!' ) {
3504 my $nshort_name = 'n' . $short_name;
3505 my $nolong_name = 'no' . $long_name;
3506 if ( $expansion{$nshort_name} ) {
3507 my $existing_name = $expansion{$nshort_name}->[0];
3509 "attempting to redefine abbreviation $nshort_name for $nolong_name; already used for $existing_name\n"
3512 $expansion{$nshort_name} = [$nolong_name];
3516 }; ## end $add_option = sub
3518 # Install long option names which have a simple abbreviation.
3519 # Options with code '!' get standard negation ('no' for long names,
3520 # 'n' for abbreviations). Categories follow the manual.
3522 ###########################
3523 $category = 0; # I/O_Control
3524 ###########################
3525 $add_option->( 'backup-and-modify-in-place', 'b', '!' );
3526 $add_option->( 'backup-file-extension', 'bext', '=s' );
3527 $add_option->( 'backup-method', 'bm', '=s' );
3528 $add_option->( 'character-encoding', 'enc', '=s' );
3529 $add_option->( 'force-read-binary', 'f', '!' );
3530 $add_option->( 'format', 'fmt', '=s' );
3531 $add_option->( 'iterations', 'it', '=i' );
3532 $add_option->( 'logfile', 'log', '!' );
3533 $add_option->( 'logfile-gap', 'g', ':i' );
3534 $add_option->( 'outfile', 'o', '=s' );
3535 $add_option->( 'output-file-extension', 'oext', '=s' );
3536 $add_option->( 'output-path', 'opath', '=s' );
3537 $add_option->( 'profile', 'pro', '=s' );
3538 $add_option->( 'quiet', 'q', '!' );
3539 $add_option->( 'standard-error-output', 'se', '!' );
3540 $add_option->( 'standard-output', 'st', '!' );
3541 $add_option->( 'use-unicode-gcstring', 'gcs', '!' );
3542 $add_option->( 'warning-output', 'w', '!' );
3543 $add_option->( 'add-terminal-newline', 'atnl', '!' );
3544 $add_option->( 'line-range-tidy', 'lrt', '=s' );
3545 $add_option->( 'timeout-in-seconds', 'tos', '=i' );
3547 # options which are both toggle switches and values moved here
3548 # to hide from tidyview (which does not show category 0 flags):
3549 # -ole moved here from category 1
3550 # -sil moved here from category 2
3551 $add_option->( 'output-line-ending', 'ole', '=s' );
3552 $add_option->( 'starting-indentation-level', 'sil', '=i' );
3554 ########################################
3555 $category = 1; # Basic formatting options
3556 ########################################
3557 $add_option->( 'check-syntax', 'syn', '!' );
3558 $add_option->( 'entab-leading-whitespace', 'et', '=i' );
3559 $add_option->( 'indent-columns', 'i', '=i' );
3560 $add_option->( 'maximum-line-length', 'l', '=i' );
3561 $add_option->( 'variable-maximum-line-length', 'vmll', '!' );
3562 $add_option->( 'whitespace-cycle', 'wc', '=i' );
3563 $add_option->( 'perl-syntax-check-flags', 'pscf', '=s' );
3564 $add_option->( 'preserve-line-endings', 'ple', '!' );
3565 $add_option->( 'tabs', 't', '!' );
3566 $add_option->( 'default-tabsize', 'dt', '=i' );
3567 $add_option->( 'extended-syntax', 'xs', '!' );
3568 $add_option->( 'assert-tidy', 'ast', '!' );
3569 $add_option->( 'assert-untidy', 'asu', '!' );
3570 $add_option->( 'encode-output-strings', 'eos', '!' );
3571 $add_option->( 'sub-alias-list', 'sal', '=s' );
3572 $add_option->( 'grep-alias-list', 'gal', '=s' );
3573 $add_option->( 'grep-alias-exclusion-list', 'gaxl', '=s' );
3574 $add_option->( 'use-feature', 'uf', '=s' );
3576 ########################################
3577 $category = 2; # Code indentation control
3578 ########################################
3579 $add_option->( 'continuation-indentation', 'ci', '=i' );
3580 $add_option->( 'extended-continuation-indentation', 'xci', '!' );
3581 $add_option->( 'minimize-continuation-indentation', 'mci', '!' );
3582 $add_option->( 'line-up-parentheses', 'lp', '!' );
3583 $add_option->( 'extended-line-up-parentheses', 'xlp', '!' );
3584 $add_option->( 'line-up-parentheses-exclusion-list', 'lpxl', '=s' );
3585 $add_option->( 'line-up-parentheses-inclusion-list', 'lpil', '=s' );
3586 $add_option->( 'outdent-keyword-list', 'okwl', '=s' );
3587 $add_option->( 'outdent-keywords', 'okw', '!' );
3588 $add_option->( 'outdent-labels', 'ola', '!' );
3589 $add_option->( 'outdent-long-quotes', 'olq', '!' );
3590 $add_option->( 'indent-closing-brace', 'icb', '!' );
3591 $add_option->( 'indent-leading-semicolon', 'ils', '!' );
3592 $add_option->( 'closing-token-indentation', 'cti', '=i' );
3593 $add_option->( 'closing-paren-indentation', 'cpi', '=i' );
3594 $add_option->( 'closing-brace-indentation', 'cbi', '=i' );
3595 $add_option->( 'closing-square-bracket-indentation', 'csbi', '=i' );
3596 $add_option->( 'brace-left-and-indent', 'bli', '!' );
3597 $add_option->( 'brace-left-and-indent-list', 'blil', '=s' );
3598 $add_option->( 'brace-left-and-indent-exclusion-list', 'blixl', '=s' );
3600 ########################################
3601 $category = 3; # Whitespace control
3602 ########################################
3603 $add_option->( 'add-trailing-commas', 'atc', '!' );
3604 $add_option->( 'add-lone-trailing-commas', 'altc', '!' );
3605 $add_option->( 'add-semicolons', 'asc', '!' );
3606 $add_option->( 'add-whitespace', 'aws', '!' );
3607 $add_option->( 'block-brace-tightness', 'bbt', '=i' );
3608 $add_option->( 'brace-tightness', 'bt', '=i' );
3609 $add_option->( 'delete-old-whitespace', 'dws', '!' );
3610 $add_option->( 'delete-repeated-commas', 'drc', '!' );
3611 $add_option->( 'delete-trailing-commas', 'dtc', '!' );
3612 $add_option->( 'delete-lone-trailing-commas', 'dltc', '!' );
3613 $add_option->( 'delete-weld-interfering-commas', 'dwic', '!' );
3614 $add_option->( 'delete-semicolons', 'dsm', '!' );
3615 $add_option->( 'function-paren-vertical-alignment', 'fpva', '!' );
3616 $add_option->( 'delay-trailing-comma-operations', 'dtco', '!' );
3617 $add_option->( 'keyword-paren-inner-tightness', 'kpit', '=i' );
3618 $add_option->( 'keyword-paren-inner-tightness-list', 'kpitl', '=s' );
3619 $add_option->( 'logical-padding', 'lop', '!' );
3620 $add_option->( 'multiple-token-tightness', 'mutt', '=s' );
3621 $add_option->( 'nospace-after-keyword', 'nsak', '=s' );
3622 $add_option->( 'nowant-left-space', 'nwls', '=s' );
3623 $add_option->( 'nowant-right-space', 'nwrs', '=s' );
3624 $add_option->( 'paren-tightness', 'pt', '=i' );
3625 $add_option->( 'space-after-keyword', 'sak', '=s' );
3626 $add_option->( 'space-for-semicolon', 'sfs', '!' );
3627 $add_option->( 'space-function-paren', 'sfp', '!' );
3628 $add_option->( 'space-keyword-paren', 'skp', '!' );
3629 $add_option->( 'space-terminal-semicolon', 'sts', '!' );
3630 $add_option->( 'square-bracket-tightness', 'sbt', '=i' );
3631 $add_option->( 'square-bracket-vertical-tightness', 'sbvt', '=i' );
3632 $add_option->( 'square-bracket-vertical-tightness-closing', 'sbvtc', '=i' );
3633 $add_option->( 'tight-secret-operators', 'tso', '!' );
3634 $add_option->( 'trim-qw', 'tqw', '!' );
3635 $add_option->( 'trim-pod', 'trp', '!' );
3636 $add_option->( 'want-left-space', 'wls', '=s' );
3637 $add_option->( 'want-right-space', 'wrs', '=s' );
3638 $add_option->( 'want-trailing-commas', 'wtc', '=s' );
3639 $add_option->( 'space-prototype-paren', 'spp', '=i' );
3640 $add_option->( 'space-signature-paren', 'ssp', '=i' );
3641 $add_option->( 'valign-code', 'vc', '!' );
3642 $add_option->( 'valign-block-comments', 'vbc', '!' );
3643 $add_option->( 'valign-side-comments', 'vsc', '!' );
3644 $add_option->( 'valign-exclusion-list', 'vxl', '=s' );
3645 $add_option->( 'valign-inclusion-list', 'vil', '=s' );
3646 $add_option->( 'valign-if-unless', 'viu', '!' );
3647 $add_option->( 'valign-signed-numbers', 'vsn', '!' );
3648 $add_option->( 'valign-signed-numbers-limit', 'vsnl', '=i' );
3649 $add_option->( 'valign-wide-equals', 'vwe', '!' );
3650 $add_option->( 'extended-block-tightness', 'xbt', '!' );
3651 $add_option->( 'extended-block-tightness-list', 'xbtl', '=s' );
3652 $add_option->( 'qw-as-function', 'qwaf', '!' );
3654 ########################################
3655 $category = 4; # Comment controls
3656 ########################################
3657 $add_option->( 'closing-side-comment-else-flag', 'csce', '=i' );
3658 $add_option->( 'closing-side-comment-interval', 'csci', '=i' );
3659 $add_option->( 'closing-side-comment-list', 'cscl', '=s' );
3660 $add_option->( 'closing-side-comment-exclusion-list', 'cscxl', '=s' );
3661 $add_option->( 'closing-side-comment-maximum-text', 'csct', '=i' );
3662 $add_option->( 'closing-side-comment-prefix', 'cscp', '=s' );
3663 $add_option->( 'closing-side-comment-warnings', 'cscw', '!' );
3664 $add_option->( 'closing-side-comments', 'csc', '!' );
3665 $add_option->( 'closing-side-comments-balanced', 'cscb', '!' );
3666 $add_option->( 'code-skipping', 'cs', '!' );
3667 $add_option->( 'code-skipping-begin', 'csb', '=s' );
3668 $add_option->( 'code-skipping-end', 'cse', '=s' );
3669 $add_option->( 'format-skipping', 'fs', '!' );
3670 $add_option->( 'format-skipping-begin', 'fsb', '=s' );
3671 $add_option->( 'format-skipping-end', 'fse', '=s' );
3672 $add_option->( 'hanging-side-comments', 'hsc', '!' );
3673 $add_option->( 'indent-block-comments', 'ibc', '!' );
3674 $add_option->( 'indent-spaced-block-comments', 'isbc', '!' );
3675 $add_option->( 'fixed-position-side-comment', 'fpsc', '=i' );
3676 $add_option->( 'minimum-space-to-comment', 'msc', '=i' );
3677 $add_option->( 'non-indenting-braces', 'nib', '!' );
3678 $add_option->( 'non-indenting-brace-prefix', 'nibp', '=s' );
3679 $add_option->( 'outdent-long-comments', 'olc', '!' );
3680 $add_option->( 'outdent-static-block-comments', 'osbc', '!' );
3681 $add_option->( 'static-block-comment-prefix', 'sbcp', '=s' );
3682 $add_option->( 'static-block-comments', 'sbc', '!' );
3683 $add_option->( 'static-side-comment-prefix', 'sscp', '=s' );
3684 $add_option->( 'static-side-comments', 'ssc', '!' );
3685 $add_option->( 'ignore-side-comment-lengths', 'iscl', '!' );
3686 $add_option->( 'ignore-perlcritic-comments', 'ipc', '!' );
3688 ########################################
3689 $category = 5; # Linebreak controls
3690 ########################################
3691 $add_option->( 'add-newlines', 'anl', '!' );
3692 $add_option->( 'block-brace-vertical-tightness', 'bbvt', '=i' );
3693 $add_option->( 'block-brace-vertical-tightness-list', 'bbvtl', '=s' );
3694 $add_option->( 'brace-follower-vertical-tightness', 'bfvt', '=i' );
3695 $add_option->( 'brace-vertical-tightness', 'bvt', '=i' );
3696 $add_option->( 'brace-vertical-tightness-closing', 'bvtc', '=i' );
3697 $add_option->( 'cuddled-else', 'ce', '!' );
3698 $add_option->( 'cuddled-block-list', 'cbl', '=s' );
3699 $add_option->( 'cuddled-block-list-exclusive', 'cblx', '!' );
3700 $add_option->( 'cuddled-break-option', 'cbo', '=i' );
3701 $add_option->( 'cuddled-paren-brace', 'cpb', '!' );
3702 $add_option->( 'delete-old-newlines', 'dnl', '!' );
3703 $add_option->( 'opening-brace-always-on-right', 'bar', '!' );
3704 $add_option->( 'opening-brace-on-new-line', 'bl', '!' );
3705 $add_option->( 'opening-hash-brace-right', 'ohbr', '!' );
3706 $add_option->( 'opening-paren-right', 'opr', '!' );
3707 $add_option->( 'opening-square-bracket-right', 'osbr', '!' );
3708 $add_option->( 'opening-anonymous-sub-brace-on-new-line', 'asbl', '!' );
3709 $add_option->( 'opening-sub-brace-on-new-line', 'sbl', '!' );
3710 $add_option->( 'paren-vertical-tightness', 'pvt', '=i' );
3711 $add_option->( 'paren-vertical-tightness-closing', 'pvtc', '=i' );
3712 $add_option->( 'weld-nested-containers', 'wn', '!' );
3713 $add_option->( 'weld-nested-exclusion-list', 'wnxl', '=s' );
3714 $add_option->( 'weld-fat-comma', 'wfc', '!' );
3715 $add_option->( 'space-backslash-quote', 'sbq', '=i' );
3716 $add_option->( 'stack-closing-block-brace', 'scbb', '!' );
3717 $add_option->( 'stack-closing-hash-brace', 'schb', '!' );
3718 $add_option->( 'stack-closing-paren', 'scp', '!' );
3719 $add_option->( 'stack-closing-square-bracket', 'scsb', '!' );
3720 $add_option->( 'stack-opening-hash-brace', 'sohb', '!' );
3721 $add_option->( 'stack-opening-paren', 'sop', '!' );
3722 $add_option->( 'stack-opening-square-bracket', 'sosb', '!' );
3724 # FIXME: --vt and --vtc are actually expansions now, so these two lines
3725 # should eventually be removed.
3726 $add_option->( 'vertical-tightness', 'vt', '=i' );
3727 $add_option->( 'vertical-tightness-closing', 'vtc', '=i' );
3729 $add_option->( 'want-break-after', 'wba', '=s' );
3730 $add_option->( 'want-break-before', 'wbb', '=s' );
3731 $add_option->( 'break-after-all-operators', 'baao', '!' );
3732 $add_option->( 'break-before-all-operators', 'bbao', '!' );
3733 $add_option->( 'keep-interior-semicolons', 'kis', '!' );
3734 $add_option->( 'one-line-block-semicolons', 'olbs', '=i' );
3735 $add_option->( 'one-line-block-nesting', 'olbn', '=i' );
3736 $add_option->( 'one-line-block-exclusion-list', 'olbxl', '=s' );
3737 $add_option->( 'break-before-hash-brace', 'bbhb', '=i' );
3738 $add_option->( 'break-before-hash-brace-and-indent', 'bbhbi', '=i' );
3739 $add_option->( 'break-before-square-bracket', 'bbsb', '=i' );
3740 $add_option->( 'break-before-square-bracket-and-indent', 'bbsbi', '=i' );
3741 $add_option->( 'break-before-paren', 'bbp', '=i' );
3742 $add_option->( 'break-before-paren-and-indent', 'bbpi', '=i' );
3743 $add_option->( 'brace-left-list', 'bll', '=s' );
3744 $add_option->( 'brace-left-exclusion-list', 'blxl', '=s' );
3745 $add_option->( 'break-after-labels', 'bal', '=i' );
3747 # This was an experiment mentioned in git #78, originally named -bopl. I
3748 # expanded it to also open logical blocks, based on git discussion #100,
3749 # and renamed it -bocp. It works, but will remain commented out due to
3750 # apparent lack of interest.
3751 # $add_option->( 'break-open-compact-parens', 'bocp', '=s' );
3753 ########################################
3754 $category = 6; # Controlling list formatting
3755 ########################################
3756 $add_option->( 'break-at-old-comma-breakpoints', 'boc', '!' );
3757 $add_option->( 'break-at-trailing-comma-types', 'btct', '=s' );
3758 $add_option->( 'comma-arrow-breakpoints', 'cab', '=i' );
3759 $add_option->( 'maximum-fields-per-table', 'mft', '=i' );
3761 ########################################
3762 $category = 7; # Retaining or ignoring existing line breaks
3763 ########################################
3764 $add_option->( 'break-at-old-keyword-breakpoints', 'bok', '!' );
3765 $add_option->( 'break-at-old-logical-breakpoints', 'bol', '!' );
3766 $add_option->( 'break-at-old-method-breakpoints', 'bom', '!' );
3767 $add_option->( 'break-at-old-semicolon-breakpoints', 'bos', '!' );
3768 $add_option->( 'break-at-old-ternary-breakpoints', 'bot', '!' );
3769 $add_option->( 'break-at-old-attribute-breakpoints', 'boa', '!' );
3770 $add_option->( 'keep-old-breakpoints-before', 'kbb', '=s' );
3771 $add_option->( 'keep-old-breakpoints-after', 'kba', '=s' );
3772 $add_option->( 'ignore-old-breakpoints', 'iob', '!' );
3774 ########################################
3775 $category = 8; # Blank line control
3776 ########################################
3777 $add_option->( 'blanks-before-blocks', 'bbb', '!' );
3778 $add_option->( 'blanks-before-comments', 'bbc', '!' );
3779 $add_option->( 'blank-lines-before-subs', 'blbs', '=i' );
3780 $add_option->( 'blank-lines-before-packages', 'blbp', '=i' );
3781 $add_option->( 'long-block-line-count', 'lbl', '=i' );
3782 $add_option->( 'maximum-consecutive-blank-lines', 'mbl', '=i' );
3783 $add_option->( 'keep-old-blank-lines', 'kbl', '=i' );
3785 $add_option->( 'keyword-group-blanks-list', 'kgbl', '=s' );
3786 $add_option->( 'keyword-group-blanks-size', 'kgbs', '=s' );
3787 $add_option->( 'keyword-group-blanks-repeat-count', 'kgbr', '=i' );
3788 $add_option->( 'keyword-group-blanks-before', 'kgbb', '=i' );
3789 $add_option->( 'keyword-group-blanks-after', 'kgba', '=i' );
3790 $add_option->( 'keyword-group-blanks-inside', 'kgbi', '!' );
3791 $add_option->( 'keyword-group-blanks-delete', 'kgbd', '!' );
3793 $add_option->( 'blank-lines-after-opening-block', 'blao', '=i' );
3794 $add_option->( 'blank-lines-before-closing-block', 'blbc', '=i' );
3795 $add_option->( 'blank-lines-after-opening-block-list', 'blaol', '=s' );
3796 $add_option->( 'blank-lines-before-closing-block-list', 'blbcl', '=s' );
3798 ########################################
3799 $category = 9; # Other controls
3800 ########################################
3801 $add_option->( 'warn-missing-else', 'wme', '!' );
3802 $add_option->( 'add-missing-else', 'ame', '!' );
3803 $add_option->( 'add-missing-else-comment', 'amec', '=s' );
3804 $add_option->( 'delete-block-comments', 'dbc', '!' );
3805 $add_option->( 'delete-closing-side-comments', 'dcsc', '!' );
3806 $add_option->( 'delete-pod', 'dp', '!' );
3807 $add_option->( 'delete-side-comments', 'dsc', '!' );
3808 $add_option->( 'tee-block-comments', 'tbc', '!' );
3809 $add_option->( 'tee-pod', 'tp', '!' );
3810 $add_option->( 'tee-side-comments', 'tsc', '!' );
3811 $add_option->( 'look-for-autoloader', 'lal', '!' );
3812 $add_option->( 'look-for-hash-bang', 'x', '!' );
3813 $add_option->( 'look-for-selfloader', 'lsl', '!' );
3814 $add_option->( 'pass-version-line', 'pvl', '!' );
3815 $add_option->( 'warn-variable-types', 'wvt', '=s' );
3816 $add_option->( 'warn-variable-exclusion-list', 'wvxl', '=s' );
3817 $add_option->( 'want-call-parens', 'wcp', '=s' );
3818 $add_option->( 'nowant-call-parens', 'nwcp', '=s' );
3820 $add_option->( 'warn-mismatched-args', 'wma', '!' );
3821 $add_option->( 'warn-mismatched-arg-types', 'wmat', '=s' );
3822 $add_option->( 'warn-mismatched-arg-undercount-cutoff', 'wmauc', '=i' );
3823 $add_option->( 'warn-mismatched-arg-overcount-cutoff', 'wmaoc', '=i' );
3824 $add_option->( 'warn-mismatched-arg-exclusion-list', 'wmaxl', '=s' );
3825 $add_option->( 'warn-mismatched-returns', 'wmr', '!' );
3826 $add_option->( 'warn-mismatched-return-types', 'wmrt', '=s' );
3827 $add_option->( 'warn-mismatched-return-exclusion-list', 'wmrxl', '=s' );
3829 $add_option->( 'add-interbracket-arrows', 'aia', '!' );
3830 $add_option->( 'delete-interbracket-arrows', 'dia', '!' );
3831 $add_option->( 'warn-interbracket-arrows', 'wia', '!' );
3832 $add_option->( 'interbracket-arrow-style', 'ias', '=s' );
3833 $add_option->( 'interbracket-arrow-complexity', 'iac', '=i' );
3835 ########################################
3836 $category = 13; # Debugging
3837 ########################################
3838 $add_option->( 'DEBUG', 'D', '!' );
3839 $add_option->( 'dump-block-summary', 'dbs', '!' );
3840 $add_option->( 'dump-block-minimum-lines', 'dbl', '=i' );
3841 $add_option->( 'dump-block-types', 'dbt', '=s' );
3842 $add_option->( 'dump-cuddled-block-list', 'dcbl', '!' );
3843 $add_option->( 'dump-defaults', 'ddf', '!' );
3844 $add_option->( 'dump-integer-option-range', 'dior', '!' );
3845 $add_option->( 'dump-long-names', 'dln', '!' );
3846 $add_option->( 'dump-mismatched-args', 'dma', '!' );
3847 $add_option->( 'dump-mismatched-returns', 'dmr', '!' );
3848 $add_option->( 'dump-mixed-call-parens', 'dmcp', '!' );
3849 $add_option->( 'dump-options', 'dop', '!' );
3850 $add_option->( 'dump-profile', 'dpro', '!' );
3851 $add_option->( 'dump-short-names', 'dsn', '!' );
3852 $add_option->( 'dump-token-types', 'dtt', '!' );
3853 $add_option->( 'dump-unusual-variables', 'duv', '!' );
3854 $add_option->( 'dump-unique-keys', 'duk', '!' );
3855 $add_option->( 'dump-want-left-space', 'dwls', '!' );
3856 $add_option->( 'dump-want-right-space', 'dwrs', '!' );
3857 $add_option->( 'fuzzy-line-length', 'fll', '!' );
3858 $add_option->( 'help', 'h', EMPTY_STRING );
3859 $add_option->( 'short-concatenation-item-length', 'scl', '=i' );
3860 $add_option->( 'show-options', 'opt', '!' );
3861 $add_option->( 'timestamp', 'ts', '!' );
3862 $add_option->( 'version', 'v', EMPTY_STRING );
3863 $add_option->( 'memoize', 'mem', '!' );
3864 $add_option->( 'file-size-order', 'fso', '!' );
3865 $add_option->( 'maximum-file-size-mb', 'maxfs', '=i' );
3866 $add_option->( 'maximum-level-errors', 'maxle', '=i' );
3867 $add_option->( 'maximum-unexpected-errors', 'maxue', '=i' );
3868 $add_option->( 'integer-range-check', 'irc', '=i' );
3870 #---------------------------------------------------------------------
3872 # The Perl::Tidy::HtmlWriter will add its own options to the string
3873 Perl::Tidy::HtmlWriter->make_getopt_long_names( \@option_string );
3875 ########################################
3876 # Set categories 10, 11, 12
3877 ########################################
3878 # Based on their known order
3879 $category = 12; # HTML properties
3880 foreach my $opt (@option_string) {
3881 my $long_name = $opt;
3882 $long_name =~ s/(!|=.*|:.*)$//;
3883 if ( !defined( $option_category{$long_name} ) ) {
3884 if ( $long_name =~ /^html-linked/ ) {
3885 $category = 10; # HTML options
3887 elsif ( $long_name =~ /^pod2html/ ) {
3888 $category = 11; # Pod2html
3891 $category = 12; # HTML properties
3893 $option_category{$long_name} = $category_name[$category];
3897 #------------------------------------------------------------------
3898 # DEFAULTS: Assign default values to the above options here, except
3899 # for 'outfile' and 'help'.
3900 # These settings should approximate the perlstyle(1) suggestions.
3901 #------------------------------------------------------------------
3903 add-lone-trailing-commas
3905 add-terminal-newline
3908 blanks-before-blocks
3909 blanks-before-comments
3910 blank-lines-before-subs=1
3911 blank-lines-before-packages=1
3913 keyword-group-blanks-size=5
3914 keyword-group-blanks-repeat-count=0
3915 keyword-group-blanks-before=1
3916 keyword-group-blanks-after=1
3917 nokeyword-group-blanks-inside
3918 nokeyword-group-blanks-delete
3920 block-brace-tightness=0
3921 block-brace-vertical-tightness=0
3922 brace-follower-vertical-tightness=1
3924 brace-vertical-tightness-closing=0
3925 brace-vertical-tightness=0
3926 break-after-labels=0
3927 break-at-old-logical-breakpoints
3928 break-at-old-ternary-breakpoints
3929 break-at-old-attribute-breakpoints
3930 break-at-old-keyword-breakpoints
3931 break-before-hash-brace=0
3932 break-before-hash-brace-and-indent=0
3933 break-before-square-bracket=0
3934 break-before-square-bracket-and-indent=0
3935 break-before-paren=0
3936 break-before-paren-and-indent=0
3937 comma-arrow-breakpoints=5
3939 character-encoding=guess
3940 closing-side-comment-interval=6
3941 closing-side-comment-maximum-text=20
3942 closing-side-comment-else-flag=0
3943 closing-side-comments-balanced
3944 closing-paren-indentation=0
3945 closing-brace-indentation=0
3946 closing-square-bracket-indentation=0
3947 continuation-indentation=2
3948 noextended-continuation-indentation
3949 cuddled-break-option=1
3951 delete-repeated-commas
3952 delete-lone-trailing-commas
3954 dump-block-minimum-lines=20
3955 dump-block-types=sub
3957 encode-output-strings
3959 function-paren-vertical-alignment
3961 hanging-side-comments
3962 indent-block-comments
3964 indent-leading-semicolon
3965 integer-range-check=2
3966 interbracket-arrow-complexity=1
3968 keep-old-blank-lines=1
3969 keyword-paren-inner-tightness=1
3971 long-block-line-count=8
3974 maximum-consecutive-blank-lines=1
3975 maximum-fields-per-table=0
3976 maximum-line-length=80
3977 maximum-file-size-mb=10
3978 maximum-level-errors=1
3979 maximum-unexpected-errors=0
3981 minimum-space-to-comment=4
3982 warn-mismatched-arg-undercount-cutoff=4
3983 warn-mismatched-arg-overcount-cutoff=1
3984 nobrace-left-and-indent
3986 nodelete-old-whitespace
3989 non-indenting-braces
3992 nostatic-side-comments
3995 one-line-block-semicolons=1
3996 one-line-block-nesting=0
3999 outdent-long-comments
4001 paren-vertical-tightness-closing=0
4002 paren-vertical-tightness=0
4004 noweld-nested-containers
4006 nouse-unicode-gcstring
4008 valign-block-comments
4009 valign-side-comments
4010 valign-signed-numbers
4011 valign-signed-numbers-limit=20
4012 short-concatenation-item-length=8
4014 space-backslash-quote=1
4015 space-prototype-paren=1
4016 space-signature-paren=1
4017 square-bracket-tightness=1
4018 square-bracket-vertical-tightness-closing=0
4019 square-bracket-vertical-tightness=0
4020 static-block-comments
4025 backup-file-extension=bak
4029 timeout-in-seconds=10
4032 entab-leading-whitespace=0
4033 blank-lines-before-closing-block=0
4034 blank-lines-after-opening-block=0
4037 html-table-of-contents
4041 #---------------------------------------
4042 # Assign valid ranges to certain options
4043 #---------------------------------------
4044 # In the future, these may be used to make preliminary checks
4045 # hash keys are long names
4046 # If key or value is undefined:
4047 # strings may have any value
4048 # integer ranges are >=0
4049 # If value is defined:
4050 # value is [qw(any valid words)] for strings
4051 # value is [min, max] for integers
4052 # if min is undefined, there is no lower limit
4053 # if max is undefined, there is no upper limit
4054 # Parameters not listed here have defaults
4056 'format' => [ 'tidy', 'html', 'user' ],
4057 'output-line-ending' => [ 'dos', 'win', 'mac', 'unix' ],
4058 'space-backslash-quote' => [ 0, 2 ],
4059 'block-brace-tightness' => [ 0, 2 ],
4060 'keyword-paren-inner-tightness' => [ 0, 2 ],
4061 'brace-tightness' => [ 0, 2 ],
4062 'paren-tightness' => [ 0, 2 ],
4063 'square-bracket-tightness' => [ 0, 2 ],
4065 'block-brace-vertical-tightness' => [ 0, 2 ],
4066 'brace-follower-vertical-tightness' => [ 0, 2 ],
4067 'brace-vertical-tightness' => [ 0, 2 ],
4068 'brace-vertical-tightness-closing' => [ 0, 3 ],
4069 'paren-vertical-tightness' => [ 0, 2 ],
4070 'paren-vertical-tightness-closing' => [ 0, 3 ],
4071 'square-bracket-vertical-tightness' => [ 0, 2 ],
4072 'square-bracket-vertical-tightness-closing' => [ 0, 3 ],
4073 'vertical-tightness' => [ 0, 2 ],
4074 'vertical-tightness-closing' => [ 0, 3 ],
4076 'closing-brace-indentation' => [ 0, 3 ],
4077 'closing-paren-indentation' => [ 0, 3 ],
4078 'closing-square-bracket-indentation' => [ 0, 3 ],
4079 'closing-token-indentation' => [ 0, 3 ],
4081 'closing-side-comment-else-flag' => [ 0, 2 ],
4082 'comma-arrow-breakpoints' => [ 0, 5 ],
4084 'keyword-group-blanks-before' => [ 0, 2 ],
4085 'keyword-group-blanks-after' => [ 0, 2 ],
4087 'space-prototype-paren' => [ 0, 2 ],
4088 'space-signature-paren' => [ 0, 2 ],
4089 'break-after-labels' => [ 0, 2 ],
4092 # Valid [min,max] ranges of all integer options (type '=i'). This hash is
4093 # replacing %option_range, above, for use by sub 'check_options'
4094 %integer_option_range = (
4095 'blank-lines-after-opening-block' => [ 0, undef ],
4096 'blank-lines-before-closing-block' => [ 0, undef ],
4097 'blank-lines-before-packages' => [ 0, undef ],
4098 'blank-lines-before-subs' => [ 0, undef ],
4099 'block-brace-tightness' => [ 0, 2 ],
4100 'block-brace-vertical-tightness' => [ 0, 2 ],
4101 'brace-follower-vertical-tightness' => [ 0, 2 ],
4102 'brace-tightness' => [ 0, 2 ],
4103 'brace-vertical-tightness' => [ 0, 2 ],
4104 'brace-vertical-tightness-closing' => [ 0, 3 ],
4105 'break-after-labels' => [ 0, 2 ],
4106 'break-before-hash-brace' => [ 0, 3 ],
4107 'break-before-hash-brace-and-indent' => [ 0, 2 ],
4108 'break-before-paren' => [ 0, 3 ],
4109 'break-before-paren-and-indent' => [ 0, 2 ],
4110 'break-before-square-bracket' => [ 0, 3 ],
4111 'break-before-square-bracket-and-indent' => [ 0, 2 ],
4112 'closing-brace-indentation' => [ 0, 3 ],
4113 'closing-paren-indentation' => [ 0, 3 ],
4114 'closing-side-comment-else-flag' => [ 0, 2 ],
4115 'closing-side-comment-interval' => [ 0, undef ],
4116 'closing-side-comment-maximum-text' => [ 0, undef ],
4117 'closing-square-bracket-indentation' => [ 0, 3 ],
4118 'closing-token-indentation' => [ 0, 3 ],
4119 'comma-arrow-breakpoints' => [ 0, 5 ],
4120 'continuation-indentation' => [ 0, undef ],
4121 'cuddled-break-option' => [ 0, 2 ],
4122 'default-tabsize' => [ 0, undef ],
4123 'dump-block-minimum-lines' => [ 0, undef ],
4124 'entab-leading-whitespace' => [ 0, undef ],
4125 'fixed-position-side-comment' => [ 0, undef ],
4126 'indent-columns' => [ 0, undef ],
4127 'interbracket-arrow-complexity' => [ 0, 2 ],
4128 'integer-range-check' => [ 0, 3 ],
4129 'iterations' => [ 0, undef ],
4130 'keep-old-blank-lines' => [ 0, 2 ],
4131 'keyword-group-blanks-after' => [ 0, 2 ],
4132 'keyword-group-blanks-before' => [ 0, 2 ],
4133 'keyword-group-blanks-repeat-count' => [ 0, undef ],
4134 'keyword-paren-inner-tightness' => [ 0, 2 ],
4135 'long-block-line-count' => [ 0, undef ],
4136 'maximum-consecutive-blank-lines' => [ 0, undef ],
4137 'maximum-fields-per-table' => [ 0, undef ],
4138 'maximum-file-size-mb' => [ 0, undef ],
4139 'maximum-level-errors' => [ 0, undef ],
4140 'maximum-line-length' => [ 0, undef ],
4141 'maximum-unexpected-errors' => [ 0, undef ],
4142 'minimum-space-to-comment' => [ 0, undef ],
4143 'warn-mismatched-arg-undercount-cutoff' => [ 0, undef ],
4144 'warn-mismatched-arg-overcount-cutoff' => [ 0, undef ],
4145 'one-line-block-nesting' => [ 0, 1 ],
4146 'one-line-block-semicolons' => [ 0, 2 ],
4147 'paren-tightness' => [ 0, 2 ],
4148 'paren-vertical-tightness' => [ 0, 2 ],
4149 'paren-vertical-tightness-closing' => [ 0, 3 ],
4150 'short-concatenation-item-length' => [ 0, undef ],
4151 'space-backslash-quote' => [ 0, 2 ],
4152 'space-prototype-paren' => [ 0, 2 ],
4153 'space-signature-paren' => [ 0, 2 ],
4154 'square-bracket-tightness' => [ 0, 2 ],
4155 'square-bracket-vertical-tightness' => [ 0, 2 ],
4156 'square-bracket-vertical-tightness-closing' => [ 0, 3 ],
4157 'starting-indentation-level' => [ 0, undef ],
4158 'timeout-in-seconds' => [ 0, undef ],
4159 'vertical-tightness' => [ 0, 2 ],
4160 'vertical-tightness-closing' => [ 0, 3 ],
4161 'valign-signed-numbers-limit' => [ 0, undef ],
4162 'whitespace-cycle' => [ 0, undef ],
4165 # Enter default values into the integer option range table
4166 foreach my $opt (@defaults) {
4167 if ( $opt =~ /^(.*)=(\d+)$/ ) {
4170 if ( defined( $integer_option_range{$key} ) ) {
4171 $integer_option_range{$key}->[2] = $def;
4176 # Enter special values which have undef as the default.
4177 # Note that cti, vt, and vtc are aliases which are included to work
4178 # around an old problem with msdos (see note in check_options).
4181 closing-token-indentation
4183 vertical-tightness-closing
4184 fixed-position-side-comment
4185 starting-indentation-level
4189 if ( defined( $integer_option_range{$key} )
4190 && @{ $integer_option_range{$key} } < 3 )
4192 $integer_option_range{$key}->[2] = undef;
4196 # Verify that only integers of type =i are in the above list during
4197 # development. This will guard against spelling errors.
4200 my $msg = EMPTY_STRING;
4201 foreach my $opt (@option_string) {
4203 my $flag = EMPTY_STRING;
4204 if ( $key =~ /(.*)(!|=.*|:.*)$/ ) {
4208 $option_flag{$key} = $flag;
4211 # Be sure all keys of %integer_option_range have option type '=i'
4212 foreach my $opt ( keys %integer_option_range ) {
4213 my $flag = $option_flag{$opt};
4214 if ( !defined($flag) ) { $flag = EMPTY_STRING }
4215 if ( $flag ne '=i' ) {
4217 # If this fault occurs, one of the items in the previous hash
4218 # is not type =i, possibly due to incorrect spelling.
4220 "Option '$opt' has an entry in '%integer_option_range' but is not an integer\n";
4224 # Be sure all '=i' options are in %integer_option_range. This is not
4225 # strictly necessary but helps insure that nothing was missed.
4226 foreach my $opt ( keys %option_flag ) {
4227 my $flag = $option_flag{$opt};
4228 next if ( $flag ne '=i' );
4229 if ( !defined( $integer_option_range{$opt} ) ) {
4231 "Integer option '$opt' is needs an entry in '%integer_option_range'\n";
4235 # look for integer options without default values
4236 foreach my $opt ( keys %integer_option_range ) {
4237 if ( @{ $integer_option_range{$opt} } < 3 ) {
4238 $msg .= "Integer option '$opt' does not have a default value\n";
4247 #-----------------------------------------------------------------------
4248 # Define abbreviations which will be expanded into the above primitives.
4249 # These may be defined recursively.
4250 #-----------------------------------------------------------------------
4253 'freeze-newlines' => [qw(noadd-newlines nodelete-old-newlines)],
4254 'fnl' => [qw(freeze-newlines)],
4255 'freeze-whitespace' => [qw(noadd-whitespace nodelete-old-whitespace)],
4256 'fws' => [qw(freeze-whitespace)],
4257 'freeze-blank-lines' =>
4258 [qw(maximum-consecutive-blank-lines=0 keep-old-blank-lines=2)],
4259 'fbl' => [qw(freeze-blank-lines)],
4260 'indent-only' => [qw(freeze-newlines freeze-whitespace)],
4261 'outdent-long-lines' => [qw(outdent-long-quotes outdent-long-comments)],
4262 'nooutdent-long-lines' =>
4263 [qw(nooutdent-long-quotes nooutdent-long-comments)],
4264 'oll' => [qw(outdent-long-lines)],
4265 'noll' => [qw(nooutdent-long-lines)],
4266 'io' => [qw(indent-only)],
4267 'delete-all-comments' =>
4268 [qw(delete-block-comments delete-side-comments delete-pod)],
4269 'nodelete-all-comments' =>
4270 [qw(nodelete-block-comments nodelete-side-comments nodelete-pod)],
4271 'dac' => [qw(delete-all-comments)],
4272 'ndac' => [qw(nodelete-all-comments)],
4273 'gnu' => [qw(gnu-style)],
4274 'pbp' => [qw(perl-best-practices)],
4275 'tee-all-comments' =>
4276 [qw(tee-block-comments tee-side-comments tee-pod)],
4277 'notee-all-comments' =>
4278 [qw(notee-block-comments notee-side-comments notee-pod)],
4279 'tac' => [qw(tee-all-comments)],
4280 'ntac' => [qw(notee-all-comments)],
4281 'html' => [qw(format=html)],
4282 'nhtml' => [qw(format=tidy)],
4283 'tidy' => [qw(format=tidy)],
4285 'brace-left' => [qw(opening-brace-on-new-line)],
4287 # -cb is now a synonym for -ce
4288 'cb' => [qw(cuddled-else)],
4289 'cuddled-blocks' => [qw(cuddled-else)],
4291 'utf8' => [qw(character-encoding=utf8)],
4292 'UTF8' => [qw(character-encoding=utf8)],
4293 'guess' => [qw(character-encoding=guess)],
4295 'swallow-optional-blank-lines' => [qw(kbl=0)],
4296 'noswallow-optional-blank-lines' => [qw(kbl=1)],
4297 'sob' => [qw(kbl=0)],
4298 'nsob' => [qw(kbl=1)],
4300 'break-after-comma-arrows' => [qw(cab=0)],
4301 'nobreak-after-comma-arrows' => [qw(cab=1)],
4302 'baa' => [qw(cab=0)],
4303 'nbaa' => [qw(cab=1)],
4305 'blanks-before-subs' => [qw(blbs=1 blbp=1)],
4306 'bbs' => [qw(blbs=1 blbp=1)],
4307 'noblanks-before-subs' => [qw(blbs=0 blbp=0)],
4308 'nbbs' => [qw(blbs=0 blbp=0)],
4310 'keyword-group-blanks' => [qw(kgbb=2 kgbi kgba=2)],
4311 'kgb' => [qw(kgbb=2 kgbi kgba=2)],
4312 'nokeyword-group-blanks' => [qw(kgbb=1 nkgbi kgba=1)],
4313 'nkgb' => [qw(kgbb=1 nkgbi kgba=1)],
4315 'break-at-old-trinary-breakpoints' => [qw(bot)],
4317 'cti=0' => [qw(cpi=0 cbi=0 csbi=0)],
4318 'cti=1' => [qw(cpi=1 cbi=1 csbi=1)],
4319 'cti=2' => [qw(cpi=2 cbi=2 csbi=2)],
4320 'icp' => [qw(cpi=2 cbi=2 csbi=2)],
4321 'nicp' => [qw(cpi=0 cbi=0 csbi=0)],
4323 'closing-token-indentation=0' => [qw(cpi=0 cbi=0 csbi=0)],
4324 'closing-token-indentation=1' => [qw(cpi=1 cbi=1 csbi=1)],
4325 'closing-token-indentation=2' => [qw(cpi=2 cbi=2 csbi=2)],
4326 'indent-closing-paren' => [qw(cpi=2 cbi=2 csbi=2)],
4327 'noindent-closing-paren' => [qw(cpi=0 cbi=0 csbi=0)],
4329 'vt=0' => [qw(pvt=0 bvt=0 sbvt=0)],
4330 'vt=1' => [qw(pvt=1 bvt=1 sbvt=1)],
4331 'vt=2' => [qw(pvt=2 bvt=2 sbvt=2)],
4333 'vertical-tightness=0' => [qw(pvt=0 bvt=0 sbvt=0)],
4334 'vertical-tightness=1' => [qw(pvt=1 bvt=1 sbvt=1)],
4335 'vertical-tightness=2' => [qw(pvt=2 bvt=2 sbvt=2)],
4337 'vtc=0' => [qw(pvtc=0 bvtc=0 sbvtc=0)],
4338 'vtc=1' => [qw(pvtc=1 bvtc=1 sbvtc=1)],
4339 'vtc=2' => [qw(pvtc=2 bvtc=2 sbvtc=2)],
4341 'vertical-tightness-closing=0' => [qw(pvtc=0 bvtc=0 sbvtc=0)],
4342 'vertical-tightness-closing=1' => [qw(pvtc=1 bvtc=1 sbvtc=1)],
4343 'vertical-tightness-closing=2' => [qw(pvtc=2 bvtc=2 sbvtc=2)],
4345 'otr' => [qw(opr ohbr osbr)],
4346 'opening-token-right' => [qw(opr ohbr osbr)],
4347 'notr' => [qw(nopr nohbr nosbr)],
4348 'noopening-token-right' => [qw(nopr nohbr nosbr)],
4350 'sot' => [qw(sop sohb sosb)],
4351 'nsot' => [qw(nsop nsohb nsosb)],
4352 'stack-opening-tokens' => [qw(sop sohb sosb)],
4353 'nostack-opening-tokens' => [qw(nsop nsohb nsosb)],
4355 'sct' => [qw(scp schb scsb)],
4356 'stack-closing-tokens' => [qw(scp schb scsb)],
4357 'nsct' => [qw(nscp nschb nscsb)],
4358 'nostack-closing-tokens' => [qw(nscp nschb nscsb)],
4360 'sac' => [qw(sot sct)],
4361 'nsac' => [qw(nsot nsct)],
4362 'stack-all-containers' => [qw(sot sct)],
4363 'nostack-all-containers' => [qw(nsot nsct)],
4365 'act=0' => [qw(pt=0 sbt=0 bt=0 bbt=0)],
4366 'act=1' => [qw(pt=1 sbt=1 bt=1 bbt=1)],
4367 'act=2' => [qw(pt=2 sbt=2 bt=2 bbt=2)],
4368 'all-containers-tightness=0' => [qw(pt=0 sbt=0 bt=0 bbt=0)],
4369 'all-containers-tightness=1' => [qw(pt=1 sbt=1 bt=1 bbt=1)],
4370 'all-containers-tightness=2' => [qw(pt=2 sbt=2 bt=2 bbt=2)],
4372 'stack-opening-block-brace' => [qw(bbvt=2 bbvtl=*)],
4373 'sobb' => [qw(bbvt=2 bbvtl=*)],
4374 'nostack-opening-block-brace' => [qw(bbvt=0)],
4375 'nsobb' => [qw(bbvt=0)],
4377 'converge' => [qw(it=4)],
4378 'noconverge' => [qw(it=1)],
4379 'conv' => [qw(it=4)],
4380 'nconv' => [qw(it=1)],
4382 'valign' => [qw(vc vsc vbc)],
4383 'novalign' => [qw(nvc nvsc nvbc)],
4385 # NOTE: This is a possible future shortcut. But it will remain
4386 # deactivated until the -lpxl flag is no longer experimental.
4387 # 'line-up-function-parentheses' => [ qw(lp), q#lpxl=[ { F(2# ],
4388 # 'lfp' => [qw(line-up-function-parentheses)],
4390 # 'mangle' originally deleted pod and comments, but to keep it
4391 # reversible, it no longer does. But if you really want to
4392 # delete them, just use:
4395 # An interesting use for 'mangle' is to do this:
4396 # perltidy -mangle myfile.pl -st | perltidy -o myfile.pl.new
4397 # which will form as many one-line blocks as possible
4401 keep-old-blank-lines=0
4403 delete-old-whitespace
4406 maximum-consecutive-blank-lines=0
4407 maximum-line-length=100000
4411 noblanks-before-blocks
4412 blank-lines-before-subs=0
4413 blank-lines-before-packages=0
4418 # 'extrude' originally deleted pod and comments, but to keep it
4419 # reversible, it no longer does. But if you really want to
4420 # delete them, just use
4423 # An interesting use for 'extrude' is to do this:
4424 # perltidy -extrude myfile.pl -st | perltidy -o myfile.pl.new
4425 # which will break up all one-line blocks.
4430 delete-old-whitespace
4433 maximum-consecutive-blank-lines=0
4434 maximum-line-length=1
4437 noblanks-before-blocks
4438 blank-lines-before-subs=0
4439 blank-lines-before-packages=0
4446 # this style tries to follow the GNU Coding Standards (which do
4447 # not really apply to perl but which are followed by some perl
4451 lp bl noll pt=2 bt=2 sbt=2 cpi=1 csbi=1 cbi=1
4455 # Style suggested in Damian Conway's Perl Best Practices
4456 'perl-best-practices' => [
4457 qw(l=78 i=4 ci=4 st se vt=2 cti=0 pt=1 bt=1 sbt=1 bbt=1 nsfs nolq),
4458 q(wbb=% + - * / x != == >= <= =~ !~ < > | & = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=)
4461 # Additional styles can be added here
4464 Perl::Tidy::HtmlWriter->make_abbreviated_names( \%expansion );
4466 # Uncomment next line to dump all expansions for debugging:
4467 # dump_short_names(\%expansion);
4468 return ( \@option_string, \@defaults, \%expansion, \%option_category,
4469 \%option_range, \%integer_option_range );
4471 } ## end sub generate_options
4473 { #<<< closure process_command_line
4475 # Memoize process_command_line. Given same @ARGV passed in, return same
4476 # values and same @ARGV back.
4477 # This patch was supplied by Jonathan Swartz Nov 2012 and significantly speeds
4478 # up masontidy (https://metacpan.org/module/masontidy)
4480 my %process_command_line_cache;
4482 sub process_command_line {
4486 $perltidyrc_stream, $is_Windows_uu, $Windows_type_uu,
4487 $rpending_complaint_uu, $dump_options_type
4490 # This is the outer sub which handles memoization
4492 my $use_cache = !defined($perltidyrc_stream) && !$dump_options_type;
4494 my $cache_key = join( chr(28), @ARGV );
4495 if ( my $result = $process_command_line_cache{$cache_key} ) {
4496 my ( $argv, @retvals ) = @{$result};
4501 my @retvals = _process_command_line(@q);
4502 $process_command_line_cache{$cache_key} = [ \@ARGV, @retvals ]
4503 if $retvals[0]->{'memoize'};
4508 return _process_command_line(@q);
4510 } ## end sub process_command_line
4511 } ## end closure process_command_line
4513 # (note the underscore here)
4514 sub _process_command_line {
4517 $perltidyrc_stream, $is_Windows, $Windows_type,
4518 $rpending_complaint, $dump_options_type
4521 # This is the inner sub which actually processes the command line
4525 # Save any current Getopt::Long configuration
4526 # and set to Getopt::Long defaults. Use eval to avoid
4527 # breaking old versions of Perl without these routines.
4528 # Previous configuration is reset at the exit of this routine.
4530 if ( eval { $glc = Getopt::Long::Configure(); 1 } ) {
4531 my $ok = eval { Getopt::Long::ConfigDefaults(); 1 };
4532 if ( !$ok && DEVEL_MODE ) {
4533 Fault("Failed call to Getopt::Long::ConfigDefaults: $EVAL_ERROR\n");
4536 else { $glc = undef }
4538 my ( $roption_string, $rdefaults, $rexpansion,
4539 $roption_category, $roption_range, $rinteger_option_range )
4540 = generate_options();
4542 #--------------------------------------------------------------
4543 # set the defaults by passing the above list through GetOptions
4544 #--------------------------------------------------------------
4549 # do not load the defaults if we are just dumping perltidyrc
4550 if ( $dump_options_type ne 'perltidyrc' ) {
4551 for my $i ( @{$rdefaults} ) { push @ARGV, "--" . $i }
4553 if ( !GetOptions( \%Opts, @{$roption_string} ) ) {
4555 "Programming Bug reported by 'GetOptions': error in setting default options"
4560 my @raw_options = ();
4561 my $saw_ignore_profile = 0;
4562 my $saw_dump_profile = 0;
4565 #--------------------------------------------------------------
4566 # Take a first look at the command-line parameters. Do as many
4567 # immediate dumps as possible, which can avoid confusion if the
4568 # perltidyrc file has an error.
4569 #--------------------------------------------------------------
4570 foreach my $i (@ARGV) {
4573 if ( $i =~ /^-(npro|noprofile|no-profile)$/ ) {
4574 $saw_ignore_profile = 1;
4577 # note: this must come before -pro and -profile, below:
4578 elsif ( $i =~ /^-(dump-profile|dpro)$/ ) {
4579 $saw_dump_profile = 1;
4581 elsif ( $i =~ /^-(pro|profile)=(.+)/ ) {
4582 if ( defined($config_file) ) {
4584 "Only one -pro=filename allowed, using '$2' instead of '$config_file'\n"
4589 # resolve <dir>/.../<file>, meaning look upwards from directory
4590 if ( defined($config_file) ) {
4591 if ( my ( $start_dir, $search_file ) =
4592 ( $config_file =~ m{^(.*)\.\.\./(.*)$} ) )
4594 $start_dir = '.' if !$start_dir;
4595 $start_dir = Cwd::realpath($start_dir);
4597 find_file_upwards( $start_dir, $search_file );
4598 if ( defined($found_file) ) {
4599 $config_file = $found_file;
4603 if ( !-e $config_file ) {
4605 "cannot find file given with -pro=$config_file: $OS_ERROR\n"
4609 elsif ( $i =~ /^-(pro|profile)=?$/ ) {
4610 Die("usage: -pro=filename or --profile=filename, no spaces\n");
4612 elsif ( $i =~ /^-(?: help | [ h \? ] )$/xi ) {
4616 elsif ( $i =~ /^-(version|v)$/ ) {
4620 elsif ( $i =~ /^-(dump-defaults|ddf)$/ ) {
4621 dump_defaults( @{$rdefaults} );
4624 elsif ( $i =~ /^-(dump-integer-option-range|dior)$/ ) {
4625 dump_integer_option_range($rinteger_option_range);
4628 elsif ( $i =~ /^-(dump-long-names|dln)$/ ) {
4629 dump_long_names( @{$roption_string} );
4632 elsif ( $i =~ /^-(dump-short-names|dsn)$/ ) {
4633 dump_short_names($rexpansion);
4636 elsif ( $i =~ /^-(dump-token-types|dtt)$/ ) {
4637 Perl::Tidy::Tokenizer->dump_token_types(*STDOUT);
4641 ## no more special cases
4645 # The above commands processed before disambiguation and then Exited. So
4646 # we need to check below to see if the user entered something like
4647 # '-dump-t' or '-he'. This will slip past here and not get processed.
4648 my %early_exit_commands = (
4651 'dump-defaults' => 'ddf',
4652 'dump-integer-option-range' => 'dior',
4653 'dump-long-names' => 'dln',
4654 'dump-short-names' => 'dsn',
4655 'dump-token-types' => 'dtt',
4658 if ( $saw_dump_profile && $saw_ignore_profile ) {
4659 Warn("No profile to dump because of -npro\n");
4663 #----------------------------------------
4664 # read any .perltidyrc configuration file
4665 #----------------------------------------
4666 if ( !$saw_ignore_profile ) {
4668 # resolve possible conflict between $perltidyrc_stream passed
4669 # as call parameter to perltidy and -pro=filename on command
4671 if ($perltidyrc_stream) {
4672 if ( defined($config_file) ) {
4674 Conflict: a perltidyrc configuration file was specified both as this
4675 perltidy call parameter: $perltidyrc_stream
4676 and with this -profile=$config_file.
4677 Using -profile=$config_file.
4681 $config_file = $perltidyrc_stream;
4685 # look for a config file if we don't have one yet
4686 my $rconfig_file_chatter;
4687 ${$rconfig_file_chatter} = EMPTY_STRING;
4688 if ( !defined($config_file) ) {
4690 find_config_file( $is_Windows, $Windows_type,
4691 $rconfig_file_chatter, $rpending_complaint );
4694 # open any config file
4696 if ( defined($config_file) ) {
4697 $rconfig_string = stream_slurp($config_file);
4698 if ( !defined($rconfig_string) ) {
4700 "exiting because profile '$config_file' could not be opened\n"
4703 filter_unknown_options(
4704 $rconfig_string, $roption_category,
4705 $rexpansion, $rconfig_file_chatter
4708 if ($saw_dump_profile) {
4709 dump_config_file( $rconfig_string, $config_file,
4710 $rconfig_file_chatter );
4714 if ( defined($rconfig_string) ) {
4716 my ( $rconfig_list, $death_message ) =
4717 read_config_file( $rconfig_string, $config_file, $rexpansion );
4718 Die($death_message) if ($death_message);
4720 # process any .perltidyrc parameters right now so we can
4722 if ( @{$rconfig_list} ) {
4723 local @ARGV = @{$rconfig_list};
4725 expand_command_abbreviations( $rexpansion, \@raw_options,
4728 if ( !GetOptions( \%Opts, @{$roption_string} ) ) {
4730 "Error in this config file: $config_file \nUse -npro to ignore this file, -dpro to dump it, -h for help'\n"
4734 # Anything left in this local @ARGV is an error and must be
4735 # invalid bare words from the configuration file. We cannot
4736 # check this earlier because bare words may have been valid
4737 # values for parameters. We had to wait for GetOptions to have
4741 my $str = EMPTY_STRING;
4742 foreach my $param (@ARGV) {
4743 if ( length($str) < 70 ) {
4744 if ($str) { $str .= ', ' }
4753 There are $count unrecognized values in the configuration file '$config_file':
4755 Use leading dashes for parameters. Use -npro to ignore this file.
4759 # Undo any options which cause premature exit. They are not
4760 # appropriate for a config file, and it could be hard to
4761 # diagnose the cause of the premature exit.
4763 # These are options include dump switches of the form
4764 # '--dump-xxx-xxx!'.
4766 grep { /^(dump-.*)!$/ } @{$roption_string};
4767 foreach (@dump_commands) { s/!$// }
4769 # Here is a current list of these @dump_commands:
4770 # dump-block-summary
4771 # dump-cuddled-block-list
4773 # dump-integer-option-range
4775 # dump-mismatched-args
4776 # dump-mismatched-returns
4777 # dump-mixed-call-parens
4782 # dump-unusual-variables
4783 # dump-want-left-space
4784 # dump-want-right-space
4786 # The following two dump configuration parameters which
4787 # take =i or =s would still be allowed:
4788 # dump-block-minimum-lines', 'dbl', '=i' );
4789 # dump-block-types', 'dbt', '=s' );
4800 if ( defined( $Opts{$cmd} ) ) {
4802 Warn("ignoring --$cmd in config file: $config_file\n");
4809 #----------------------------------------
4810 # now process the command line parameters
4811 #----------------------------------------
4812 expand_command_abbreviations( $rexpansion, \@raw_options, $config_file );
4814 local $SIG{'__WARN__'} = sub { Warn( $_[0] ) };
4815 if ( !GetOptions( \%Opts, @{$roption_string} ) ) {
4816 Die("Error on command line; for help try 'perltidy -h'\n");
4819 # Catch ambiguous entries which should have exited above (c333)
4820 foreach my $long_name ( keys %early_exit_commands ) {
4821 if ( $Opts{$long_name} ) {
4822 my $short_name = $early_exit_commands{$long_name};
4824 Ambiguous entry; please enter '--$long_name' or '-$short_name'
4829 # reset Getopt::Long configuration back to its previous value
4830 if ( defined($glc) ) {
4831 my $ok = eval { Getopt::Long::Configure($glc); 1 };
4832 if ( !$ok && DEVEL_MODE ) {
4833 Fault("Could not reset Getopt::Long configuration: $EVAL_ERROR\n");
4837 return ( \%Opts, $config_file, \@raw_options, $roption_string,
4838 $rexpansion, $roption_category, $roption_range,
4839 $rinteger_option_range );
4840 } ## end sub _process_command_line
4842 sub make_grep_alias_string {
4846 # pre-process the --grep-alias-list parameter
4848 # Defaults: list operators in List::Util
4849 # Possible future additions: pairfirst pairgrep pairmap
4850 my $default_string = join SPACE,
4851 qw( all any first none notall reduce reductions );
4853 # make a hash of any excluded words
4854 my %is_excluded_word;
4855 my $exclude_string = $rOpts->{'grep-alias-exclusion-list'};
4856 if ($exclude_string) {
4857 $exclude_string =~ s/,/ /g; # allow commas
4858 $exclude_string =~ s/^\s+//;
4859 $exclude_string =~ s/\s+$//;
4860 my @q = split /\s+/, $exclude_string;
4861 @is_excluded_word{@q} = (1) x scalar(@q);
4864 # The special option -gaxl='*' removes all defaults
4865 if ( $is_excluded_word{'*'} ) { $default_string = EMPTY_STRING }
4867 # combine the defaults and any input list
4868 my $input_string = $rOpts->{'grep-alias-list'};
4869 if ($input_string) { $input_string .= SPACE . $default_string }
4870 else { $input_string = $default_string }
4872 # Now make the final list of unique grep alias words
4873 $input_string =~ s/,/ /g; # allow commas
4874 $input_string =~ s/^\s+//;
4875 $input_string =~ s/\s+$//;
4876 my @word_list = split /\s+/, $input_string;
4877 my @filtered_word_list;
4880 foreach my $word (@word_list) {
4882 if ( $word !~ /^\w[\w\d]*$/ ) {
4884 "unexpected word in --grep-alias-list: '$word' - ignoring\n"
4887 if ( !$seen{$word} && !$is_excluded_word{$word} ) {
4889 push @filtered_word_list, $word;
4893 my $joined_words = join SPACE, @filtered_word_list;
4894 $rOpts->{'grep-alias-list'} = $joined_words;
4896 } ## end sub make_grep_alias_string
4898 sub cleanup_word_list {
4900 my ( $rOpts, $option_name, $rforced_words ) = @_;
4902 # Clean up the list of words in a user option to simplify use by
4903 # later routines (delete repeats, replace commas with single space,
4907 # $rOpts - the global option hash
4908 # $option_name - hash key of this option
4909 # $rforced_words - ref to list of any words to be added
4912 # \%seen - hash of the final list of words
4917 my $input_string = $rOpts->{$option_name};
4918 if ( defined($input_string) && length($input_string) ) {
4919 $input_string =~ s/,/ /g; # allow commas
4920 $input_string =~ s/^\s+//;
4921 $input_string =~ s/\s+$//;
4922 @input_list = split /\s+/, $input_string;
4925 if ($rforced_words) {
4926 push @input_list, @{$rforced_words};
4929 my @filtered_word_list;
4930 foreach my $word (@input_list) {
4933 # look for obviously bad words
4934 if ( $word =~ /^\d/ || $word !~ /^\w[\w\d]*$/ ) {
4935 Warn("unexpected '$option_name' word '$word' - ignoring\n");
4937 if ( !$seen{$word} ) {
4939 push @filtered_word_list, $word;
4943 $rOpts->{$option_name} = join SPACE, @filtered_word_list;
4945 } ## end sub cleanup_word_list
4949 my ( $self, $num_files, $rinteger_option_range ) = @_;
4951 # Check options at a high level. Note that other modules have their
4952 # own sub 'check_options' for lower level checking.
4955 # $num_files = the number of files to be processed in this call to
4956 # perltidy, needed for error checks.
4957 # $rinteger_option-range = hash with valid ranges of parameters which
4960 my $rOpts = $self->[_rOpts_];
4962 #------------------------------------------------------------
4963 # check and handle any interactions among the basic options..
4964 #------------------------------------------------------------
4966 # Since perltidy only encodes in utf8, problems can occur if we let it
4967 # decode anything else. See discussions for issue git #83.
4968 my $encoding = $rOpts->{'character-encoding'};
4969 if ( $encoding !~ /^\s*(?:guess|none|utf8|utf-8)\s*$/i ) {
4971 --character-encoding = '$encoding' is not allowed; the options are: 'none', 'guess', 'utf8'
4975 my $integer_range_check = $rOpts->{'integer-range-check'};
4976 if ( !defined($integer_range_check)
4977 || $integer_range_check < 0
4978 || $integer_range_check > 3 )
4980 $integer_range_check = 2;
4983 # Check for integer values out of bounds as follows:
4984 # $integer_range_check=
4985 # 0 => skip check completely (for stress-testing perltidy only)
4986 # 1 => quietly reset bad values to defaults
4987 # 2 => issue warning and reset bad values defaults [DEFAULT]
4988 # 3 => stop if any values are out of bounds
4989 if ($integer_range_check) {
4991 foreach my $opt ( keys %{$rinteger_option_range} ) {
4992 my $range = $rinteger_option_range->{$opt};
4993 next unless defined($range);
4994 my ( $min, $max, $default ) = @{$range};
4996 my $val = $rOpts->{$opt};
4997 if ( defined($min) && defined($val) && $val < $min ) {
4998 $Error_message .= "--$opt=$val but should be >= $min";
4999 if ( $integer_range_check < 3 ) {
5000 $rOpts->{$opt} = $default;
5001 my $def = defined($default) ? $default : 'undef';
5002 $Error_message .= "; using default $def";
5004 $Error_message .= "\n";
5006 if ( defined($max) && defined($val) && $val > $max ) {
5007 $Error_message .= "--$opt=$val but should be <= $max";
5008 if ( $integer_range_check < 3 ) {
5009 $rOpts->{$opt} = $default;
5010 my $def = defined($default) ? $default : 'undef';
5011 $Error_message .= "; using default $def";
5013 $Error_message .= "\n";
5016 if ($Error_message) {
5017 if ( $integer_range_check == 1 ) {
5020 elsif ( $integer_range_check == 2 ) {
5021 Warn($Error_message);
5024 Die($Error_message);
5029 # Note that -vt, -vtc, and -cti are abbreviations. But under
5030 # msdos, an unquoted input parameter like vtc=1 will be
5031 # seen as 2 parameters, vtc and 1, so the abbreviations
5032 # won't be seen. Therefore, we will catch them here if
5034 if ( defined( $rOpts->{'vertical-tightness'} ) ) {
5035 my $vt = $rOpts->{'vertical-tightness'};
5036 $rOpts->{'paren-vertical-tightness'} = $vt;
5037 $rOpts->{'square-bracket-vertical-tightness'} = $vt;
5038 $rOpts->{'brace-vertical-tightness'} = $vt;
5041 if ( defined( $rOpts->{'vertical-tightness-closing'} ) ) {
5042 my $vtc = $rOpts->{'vertical-tightness-closing'};
5043 $rOpts->{'paren-vertical-tightness-closing'} = $vtc;
5044 $rOpts->{'square-bracket-vertical-tightness-closing'} = $vtc;
5045 $rOpts->{'brace-vertical-tightness-closing'} = $vtc;
5048 if ( defined( $rOpts->{'closing-token-indentation'} ) ) {
5049 my $cti = $rOpts->{'closing-token-indentation'};
5050 $rOpts->{'closing-square-bracket-indentation'} = $cti;
5051 $rOpts->{'closing-brace-indentation'} = $cti;
5052 $rOpts->{'closing-paren-indentation'} = $cti;
5055 # Syntax checking is no longer supported due to concerns about executing
5056 # code in BEGIN blocks. The flag is still accepted for backwards
5057 # compatibility but is ignored if set.
5058 $rOpts->{'check-syntax'} = 0;
5060 my $check_blank_count = sub {
5061 my ( $key, $abbrev ) = @_;
5062 if ( $rOpts->{$key} ) {
5063 if ( $rOpts->{$key} < 0 ) {
5065 Warn("negative value of $abbrev, setting 0\n");
5067 if ( $rOpts->{$key} > 100 ) {
5068 Warn("unreasonably large value of $abbrev, reducing\n");
5069 $rOpts->{$key} = 100;
5073 }; ## end $check_blank_count = sub
5075 # check for reasonable number of blank lines and fix to avoid problems
5076 $check_blank_count->( 'blank-lines-before-subs', '-blbs' );
5077 $check_blank_count->( 'blank-lines-before-packages', '-blbp' );
5078 $check_blank_count->( 'blank-lines-after-block-opening', '-blao' );
5079 $check_blank_count->( 'blank-lines-before-block-closing', '-blbc' );
5081 # setting a non-negative logfile gap causes logfile to be saved
5082 if ( defined( $rOpts->{'logfile-gap'} ) && $rOpts->{'logfile-gap'} >= 0 ) {
5083 $rOpts->{'logfile'} = 1;
5086 # set short-cut flag when only indentation is to be done.
5087 # Note that the user may or may not have already set the
5089 if ( !$rOpts->{'add-whitespace'}
5090 && !$rOpts->{'delete-old-whitespace'}
5091 && !$rOpts->{'add-newlines'}
5092 && !$rOpts->{'delete-old-newlines'} )
5094 $rOpts->{'indent-only'} = 1;
5097 # -isbc implies -ibc
5098 if ( $rOpts->{'indent-spaced-block-comments'} ) {
5099 $rOpts->{'indent-block-comments'} = 1;
5102 # -bar cannot be used with -bl or -bli; arbitrarily keep -bar
5103 if ( $rOpts->{'opening-brace-always-on-right'} ) {
5105 if ( $rOpts->{'opening-brace-on-new-line'} ) {
5107 Conflict: you specified both 'opening-brace-always-on-right' (-bar) and
5108 'opening-brace-on-new-line' (-bl). Ignoring -bl.
5110 $rOpts->{'opening-brace-on-new-line'} = 0;
5112 if ( $rOpts->{'brace-left-and-indent'} ) {
5114 Conflict: you specified both 'opening-brace-always-on-right' (-bar) and
5115 '--brace-left-and-indent' (-bli). Ignoring -bli.
5117 $rOpts->{'brace-left-and-indent'} = 0;
5121 # it simplifies things if -bl is 0 rather than undefined
5122 if ( !defined( $rOpts->{'opening-brace-on-new-line'} ) ) {
5123 $rOpts->{'opening-brace-on-new-line'} = 0;
5126 if ( $rOpts->{'entab-leading-whitespace'} ) {
5127 if ( $rOpts->{'entab-leading-whitespace'} < 0 ) {
5128 Warn("-et=n must use a positive integer; ignoring -et\n");
5129 $rOpts->{'entab-leading-whitespace'} = undef;
5132 # entab leading whitespace has priority over the older 'tabs' option
5133 if ( $rOpts->{'tabs'} ) {
5135 # The following warning could be added but would annoy a lot of
5136 # users who have a perltidyrc with both -t and -et=n. So instead
5137 # there is a note in the manual that -et overrides -t.
5138 ##Warn("-tabs and -et=n conflict; ignoring -tabs\n");
5139 $rOpts->{'tabs'} = 0;
5143 # set a default tabsize to be used in guessing the starting indentation
5144 # level if and only if this run does not use tabs and the old code does
5146 if ( $rOpts->{'default-tabsize'} ) {
5147 if ( $rOpts->{'default-tabsize'} < 0 ) {
5148 Warn("negative value of -dt, setting 0\n");
5149 $rOpts->{'default-tabsize'} = 0;
5151 if ( $rOpts->{'default-tabsize'} > 20 ) {
5152 Warn("unreasonably large value of -dt, reducing\n");
5153 $rOpts->{'default-tabsize'} = 20;
5157 $rOpts->{'default-tabsize'} = 8;
5160 # Check and clean up any sub-alias-list
5161 if ( defined( $rOpts->{'sub-alias-list'} )
5162 && length( $rOpts->{'sub-alias-list'} ) )
5166 # include 'sub' for convenience if this option is used
5167 push @forced_words, 'sub';
5169 cleanup_word_list( $rOpts, 'sub-alias-list', \@forced_words );
5172 make_grep_alias_string($rOpts);
5174 # Turn on fuzzy-line-length unless this is an extrude run, as determined
5175 # by the -i and -ci settings. Otherwise blinkers can form (case b935).
5176 # This is an undocumented parameter used only for stress-testing when
5178 if ( !$rOpts->{'fuzzy-line-length'} ) {
5179 if ( $rOpts->{'maximum-line-length'} != 1
5180 || $rOpts->{'continuation-indentation'} != 0 )
5182 $rOpts->{'fuzzy-line-length'} = 1;
5186 # Large values of -scl can cause convergence problems, issue c167
5187 if ( $rOpts->{'short-concatenation-item-length'} > 12 ) {
5188 $rOpts->{'short-concatenation-item-length'} = 12;
5191 # The freeze-whitespace option is currently a derived option which has its
5193 $rOpts->{'freeze-whitespace'} = !$rOpts->{'add-whitespace'}
5194 && !$rOpts->{'delete-old-whitespace'};
5196 # Turn off certain options if whitespace is frozen
5197 # Note: vertical alignment will be automatically shut off
5198 if ( $rOpts->{'freeze-whitespace'} ) {
5199 $rOpts->{'logical-padding'} = 0;
5202 # Define the default line ending, before any -ple option is applied
5203 $self->[_line_separator_default_] = get_line_separator_default($rOpts);
5205 $self->[_line_tidy_begin_] = undef;
5206 $self->[_line_tidy_end_] = undef;
5207 my $line_range_tidy = $rOpts->{'line-range-tidy'};
5208 if ($line_range_tidy) {
5210 if ( $num_files > 1 ) {
5212 --line-range-tidy expects no more than 1 filename in the arg list but saw $num_files filenames
5216 $line_range_tidy =~ s/\s+//g;
5217 if ( $line_range_tidy =~ /^(\d+):(\d+)?$/ ) {
5222 --line-range-tidy=n1:n2 expects starting line number n1>=1 but n1=$n1
5225 if ( defined($n2) && $n2 < $n1 ) {
5227 --line-range-tidy=n1:n2 expects ending line number n2>=n1 but n1=$n1 and n2=$n2
5230 $self->[_line_tidy_begin_] = $n1;
5231 $self->[_line_tidy_end_] = $n2;
5235 "unrecognized 'line-range-tidy'; expecting format '-lrt=n1:n2'\n"
5241 } ## end sub check_options
5243 sub find_file_upwards {
5245 my ( $search_dir, $search_file ) = @_;
5247 # This implements the ... upward search for a file
5249 $search_dir =~ s{/+$}{};
5250 $search_file =~ s{^/+}{};
5253 my $try_path = "$search_dir/$search_file";
5254 if ( -f $try_path ) {
5257 elsif ( $search_dir eq '/' ) {
5261 $search_dir = dirname($search_dir);
5265 # This return is for Perl-Critic.
5266 # We shouldn't get out of the while loop without a return
5268 } ## end sub find_file_upwards
5270 sub expand_command_abbreviations {
5272 # go through @ARGV and expand any abbreviations
5273 # note that @ARGV has been localized
5275 my ( $rexpansion, $rraw_options, $config_file ) = @_;
5277 # set a pass limit to prevent an infinite loop;
5278 # 10 should be plenty, but it may be increased to allow deeply
5279 # nested expansions.
5280 my $max_passes = 10;
5282 # keep looping until all expansions have been converted into actual
5284 foreach my $pass_count ( 0 .. $max_passes ) {
5286 my $abbrev_count = 0;
5288 # loop over each item in @ARGV..
5289 foreach my $word (@ARGV) {
5291 # convert any leading 'no-' to just 'no'
5292 if ( $word =~ /^(-[-]?no)-(.*)/ ) { $word = $1 . $2 }
5294 # if it is a dash flag (instead of a file name)..
5295 if ( $word =~ /^-[-]?([\w\-]+)(.*)/ ) {
5300 # save the raw input for debug output in case of circular refs
5301 if ( $pass_count == 0 ) {
5302 push( @{$rraw_options}, $word );
5305 # recombine abbreviation and flag, if necessary,
5306 # to allow abbreviations with arguments such as '-vt=1'
5307 if ( $rexpansion->{ $abr . $flags } ) {
5308 $abr = $abr . $flags;
5309 $flags = EMPTY_STRING;
5312 # if we see this dash item in the expansion hash..
5313 if ( $rexpansion->{$abr} ) {
5316 # stuff all of the words that it expands to into the
5317 # new arg list for the next pass
5318 foreach my $abbrev ( @{ $rexpansion->{$abr} } ) {
5319 next unless $abbrev; # for safety; shouldn't happen
5320 push( @new_argv, '--' . $abbrev . $flags );
5324 # not in expansion hash, must be actual long name
5326 push( @new_argv, $word );
5330 # not a dash item, so just save it for the next pass
5332 push( @new_argv, $word );
5334 } ## end of this pass
5336 # update parameter list @ARGV to the new one
5338 last if ( !$abbrev_count );
5340 # make sure we are not in an infinite loop
5341 if ( $pass_count == $max_passes ) {
5342 local $LIST_SEPARATOR = ')(';
5344 I'm tired. We seem to be in an infinite loop trying to expand aliases.
5345 Here are the raw options;
5348 my $num = @new_argv;
5351 After $max_passes passes here is ARGV
5357 After $max_passes passes ARGV has $num entries
5361 if ( defined($config_file) ) {
5363 Please check your configuration file $config_file for circular-references.
5364 To deactivate it, use -npro.
5369 Program bug - circular-references in the %expansion hash, probably due to
5370 a recent program change.
5373 } ## end of check for circular references
5374 } ## end of loop over all passes
5376 } ## end sub expand_command_abbreviations
5378 # Debug routine -- this will dump the expansion hash
5379 sub dump_short_names {
5380 my $rexpansion = shift;
5381 print {*STDOUT} <<EOM;
5382 List of short names. This list shows how all abbreviations are
5383 translated into other abbreviations and, eventually, into long names.
5384 New abbreviations may be defined in a .perltidyrc file.
5385 For a list of all long names, use perltidy --dump-long-names (-dln).
5386 --------------------------------------------------------------------------
5388 foreach my $abbrev ( sort keys %{$rexpansion} ) {
5389 my @list = @{ $rexpansion->{$abbrev} };
5390 print {*STDOUT} "$abbrev --> @list\n";
5393 } ## end sub dump_short_names
5395 sub check_vms_filename {
5397 # given a valid filename (the perltidy input file)
5398 # create a modified filename and separator character
5401 # Contributed by Michael Cartmell
5403 my $filename = shift;
5404 my ( $base, $path ) = fileparse($filename);
5406 # remove explicit ; version
5407 $base =~ s/;-?\d*$//
5409 # remove explicit . version ie two dots in filename NB ^ escapes a dot
5410 or $base =~ s{( # begin capture $1
5411 (?:^|[^^])\. # match a dot not preceded by a caret
5412 (?: # followed by nothing
5414 .*[^^] # anything ending in a non caret
5417 \.-?\d*$ # match . version number
5420 # normalize filename, if there are no unescaped dots then append one
5421 $base .= '.' unless ( $base =~ /(?:^|[^^])\./ );
5423 # if we don't already have an extension then we just append the extension
5424 my $separator = ( $base =~ /\.$/ ) ? EMPTY_STRING : "_";
5425 return ( $path . $base, $separator );
5426 } ## end sub check_vms_filename
5430 my $rpending_complaint = shift;
5432 # Returns a string that determines what MS OS we are on.
5433 # Returns win32s,95,98,Me,NT3.51,NT4,2000,XP/.Net,Win2003
5434 # Returns blank string if not an MS system.
5435 # Original code contributed by: Yves Orton
5436 # We need to know this to decide where to look for config files
5438 # TODO: are these more standard names?
5439 # Win32s Win95 Win98 WinMe WinNT3.51 WinNT4 Win2000 WinXP/.Net Win2003
5441 my $os = EMPTY_STRING;
5442 return $os unless ( $OSNAME =~ /win32|dos/i ); # is it a MS box?
5444 # Systems built from Perl source may not have Win32.pm
5445 # But probably have Win32::GetOSVersion() anyway so the
5446 # following line is not 'required':
5447 # return $os unless eval('require Win32');
5449 # Use the standard API call to determine the version
5450 my ( $undef, $major, $minor, $build, $id );
5452 ( $undef, $major, $minor, $build, $id ) = Win32::GetOSVersion();
5455 if ( !$ok && DEVEL_MODE ) {
5456 Fault("Could not cal Win32::GetOSVersion(): $EVAL_ERROR\n");
5460 # NAME ID MAJOR MINOR
5461 # Windows NT 4 2 4 0
5462 # Windows 2000 2 5 0
5464 # Windows Server 2003 2 5 2
5466 return "win32s" unless $id; # If id==0 then its a win32s box.
5467 $os = { # Magic numbers from MSDN
5468 # documentation of GetOSVersion
5475 0 => "2000", # or NT 4, see below
5482 # If $os is undefined, the above code is out of date. Suggested updates
5484 if ( !defined($os) ) {
5487 # Deactivated this message 20180322 because it was needlessly
5488 # causing some test scripts to fail. Need help from someone
5489 # with expertise in Windows to decide what is possible with windows.
5490 ${$rpending_complaint} .= <<EOS if (0);
5491 Error trying to discover Win_OS_Type: $id:$major:$minor Has no name of record!
5492 We won't be able to look for a system-wide config file.
5496 # Unfortunately the logic used for the various versions isn't so clever..
5497 # so we have to handle an outside case.
5498 return ( $os eq "2000" && $major != 5 ) ? "NT4" : $os;
5499 } ## end sub Win_OS_Type
5501 sub look_for_Windows {
5503 # determine Windows sub-type and location of
5504 # system-wide configuration files
5505 my $rpending_complaint = shift;
5506 my $is_Windows = ( $OSNAME =~ /win32|dos/i );
5508 $Windows_type = Win_OS_Type($rpending_complaint) if $is_Windows;
5509 return ( $is_Windows, $Windows_type );
5510 } ## end sub look_for_Windows
5512 sub find_config_file {
5514 # look for a .perltidyrc configuration file
5515 # For Windows also look for a file named perltidy.ini
5516 my ( $is_Windows, $Windows_type, $rconfig_file_chatter,
5517 $rpending_complaint )
5520 ${$rconfig_file_chatter} .= "# Config file search...system reported as:";
5522 ${$rconfig_file_chatter} .= "Windows $Windows_type\n";
5525 ${$rconfig_file_chatter} .= " $OSNAME\n";
5528 # sub to check file existence and record all tests
5529 my $exists_config_file = sub {
5530 my $config_file = shift;
5531 return 0 unless defined($config_file);
5532 ${$rconfig_file_chatter} .= "# Testing: $config_file\n";
5533 return -f $config_file;
5534 }; ## end $exists_config_file = sub
5536 # Sub to search upward for config file
5537 my $resolve_config_file = sub {
5539 # resolve <dir>/.../<file>, meaning look upwards from directory
5540 my $config_file = shift;
5541 if ( defined($config_file) ) {
5542 if ( my ( $start_dir, $search_file ) =
5543 ( $config_file =~ m{^(.*)\.\.\./(.*)$} ) )
5545 ${$rconfig_file_chatter} .=
5546 "# Searching Upward: $config_file\n";
5547 $start_dir = '.' if !$start_dir;
5548 $start_dir = Cwd::realpath($start_dir);
5549 my $found_file = find_file_upwards( $start_dir, $search_file );
5550 if ( defined($found_file) ) {
5551 $config_file = $found_file;
5552 ${$rconfig_file_chatter} .= "# Found: $config_file\n";
5556 return $config_file;
5557 }; ## end $resolve_config_file = sub
5561 # look in current directory first
5562 $config_file = ".perltidyrc";
5563 return $config_file if $exists_config_file->($config_file);
5565 $config_file = "perltidy.ini";
5566 return $config_file if $exists_config_file->($config_file);
5569 # Default environment vars.
5570 my @envs = qw( PERLTIDY HOME );
5572 # Check the NT/2k/XP locations, first a local machine def, then a
5574 push @envs, qw( USERPROFILE HOMESHARE ) if $OSNAME =~ /win32/i;
5576 # Now go through the environment ...
5577 foreach my $var (@envs) {
5578 ${$rconfig_file_chatter} .= "# Examining: \$ENV{$var}";
5579 if ( defined( $ENV{$var} ) ) {
5580 ${$rconfig_file_chatter} .= " = $ENV{$var}\n";
5582 # test ENV{ PERLTIDY } as file:
5583 if ( $var eq 'PERLTIDY' ) {
5584 $config_file = "$ENV{$var}";
5585 $config_file = $resolve_config_file->($config_file);
5586 return $config_file if $exists_config_file->($config_file);
5589 # test ENV as directory:
5590 $config_file = File::Spec->catfile( $ENV{$var}, ".perltidyrc" );
5591 $config_file = $resolve_config_file->($config_file);
5592 return $config_file if $exists_config_file->($config_file);
5596 File::Spec->catfile( $ENV{$var}, "perltidy.ini" );
5597 $config_file = $resolve_config_file->($config_file);
5598 return $config_file if $exists_config_file->($config_file);
5602 ${$rconfig_file_chatter} .= "\n";
5606 # then look for a system-wide definition
5607 # where to look varies with OS
5610 if ($Windows_type) {
5611 my ( $os_uu, $system, $allusers ) =
5612 Win_Config_Locs( $rpending_complaint, $Windows_type );
5614 # Check All Users directory, if there is one.
5615 # i.e. C:\Documents and Settings\User\perltidy.ini
5618 $config_file = File::Spec->catfile( $allusers, ".perltidyrc" );
5619 return $config_file if $exists_config_file->($config_file);
5621 $config_file = File::Spec->catfile( $allusers, "perltidy.ini" );
5622 return $config_file if $exists_config_file->($config_file);
5625 # Check system directory.
5626 # retain old code in case someone has been able to create
5627 # a file with a leading period.
5628 $config_file = File::Spec->catfile( $system, ".perltidyrc" );
5629 return $config_file if $exists_config_file->($config_file);
5631 $config_file = File::Spec->catfile( $system, "perltidy.ini" );
5632 return $config_file if $exists_config_file->($config_file);
5636 # Place to add customization code for other systems
5637 elsif ( $OSNAME eq 'OS2' ) {
5639 elsif ( $OSNAME eq 'MacOS' ) {
5641 elsif ( $OSNAME eq 'VMS' ) {
5644 # Assume some kind of Unix
5647 $config_file = "/usr/local/etc/perltidyrc";
5648 return $config_file if $exists_config_file->($config_file);
5650 $config_file = "/etc/perltidyrc";
5651 return $config_file if $exists_config_file->($config_file);
5654 # Couldn't find a config file
5656 } ## end sub find_config_file
5658 sub Win_Config_Locs {
5660 # In scalar context returns the OS name (95 98 ME NT3.51 NT4 2000 XP),
5661 # or undef if its not a win32 OS. In list context returns OS, System
5662 # Directory, and All Users Directory. All Users will be empty on a
5663 # 9x/Me box. Contributed by: Yves Orton.
5665 my ( $rpending_complaint, $os ) = @_;
5666 if ( !$os ) { $os = Win_OS_Type($rpending_complaint) }
5670 my $system = EMPTY_STRING;
5671 my $allusers = EMPTY_STRING;
5673 if ( $os =~ /9[58]|Me/ ) {
5674 $system = "C:/Windows";
5676 elsif ( $os =~ /NT|XP|200?/ ) {
5677 $system = ( $os =~ /XP/ ) ? "C:/Windows/" : "C:/WinNT/";
5680 ? "C:/WinNT/profiles/All Users/"
5681 : "C:/Documents and Settings/All Users/";
5685 # This currently would only happen on a win32s computer. I don't have
5686 # one to test, so I am unsure how to proceed. Suggestions welcome!
5687 ${$rpending_complaint} .=
5688 "I dont know a sensible place to look for config files on an $os system.\n";
5691 return ( $os, $system, $allusers );
5692 } ## end sub Win_Config_Locs
5694 sub dump_config_file {
5695 my ( $rconfig_string, $config_file, $rconfig_file_chatter ) = @_;
5696 print {*STDOUT} "${$rconfig_file_chatter}";
5697 if ($rconfig_string) {
5698 my @lines = split /^/, ${$rconfig_string};
5699 print {*STDOUT} "# Dump of file: '$config_file'\n";
5700 foreach my $line (@lines) { print {*STDOUT} $line }
5703 print {*STDOUT} "# ...no config file found\n";
5706 } ## end sub dump_config_file
5708 sub filter_unknown_options {
5711 $rconfig_string, $roption_category,
5712 $rexpansion, $rconfig_file_chatter
5715 # Look through the configuration file for lines beginning with '---' and
5716 # - remove the line if the option is unknown, or
5717 # - remove the extra dash if the option is known
5718 # See git #146 for discussion
5721 # $rconfig_string = string ref to a .perltidyrc configuration file
5722 # $roption_category = ref to hash with long_names as key
5723 # $rexpansion = ref to hash with abbreviations as key
5724 # $rconfig_file_chatter = messages displayed in --dump-profile
5727 # $rconfig_string and $rconfig_file_chatter
5729 # quick check to skip most files
5730 if ( ${$rconfig_string} !~ /^\s*---\w/m ) { return }
5732 my $new_config_string;
5733 my $change_notices = EMPTY_STRING;
5734 my @lines = split /^/, ${$rconfig_string};
5735 foreach my $line (@lines) {
5738 # look for lines beginning with '---'
5739 if ( $line && $line =~ /^\s*---(\w[\w-]*)/ ) {
5742 # first look for a long name or an abbreviation
5743 my $is_known = $roption_category->{$word} || $rexpansion->{$word};
5745 # then look for prefix 'no' or 'no-' on a long name
5746 if ( !$is_known && $word =~ s/^no-?// ) {
5747 $is_known = $roption_category->{$word};
5751 $change_notices .= "# removing unknown option line $line\n";
5755 $change_notices .= "# accepting and fixing line $line\n";
5759 $new_config_string .= $line . "\n";
5762 if ($change_notices) {
5763 ${$rconfig_file_chatter} .= "# Filter operations:\n" . $change_notices;
5764 ${$rconfig_string} = $new_config_string;
5767 } ## end sub filter_unknown_options
5769 sub read_config_file {
5771 my ( $rconfig_string, $config_file, $rexpansion ) = @_;
5773 # Read and process the contents of a perltidyrc command file
5776 # $rconfig_string = ref to the file as a string
5777 # $config_file = name of the file, for error reporting
5778 # $rexpansion = ref to hash of abbreviations; if this config file defines
5779 # any abbreviations they will be added to it
5782 # \@config_list = ref to final parameters and values which will be
5783 # placed in @ARGV for processing by GetOptions
5784 # $death_message = error message returned if a fatal error occurs
5785 my @config_list = ();
5787 # remove side comments and join multiline quotes
5788 my ( $rline_hash, $death_message ) =
5789 strip_comments_and_join_quotes( $rconfig_string, $config_file );
5791 # file is bad if non-empty $death_message is returned
5792 if ($death_message) {
5793 return ( \@config_list, $death_message );
5797 my $opening_brace_line;
5798 foreach my $item ( @{$rline_hash} ) {
5799 my $line = $item->{line};
5800 my $line_no = $item->{line_no};
5803 next unless ( length($line) );
5807 # Look for complete or partial abbreviation definition of the form
5808 # name { body } or name { or name { body
5809 # See rules in perltidy's perldoc page
5810 # Section: Other Controls - Creating a new abbreviation
5811 if ( $line =~ /^(?: (\w+) \s* \{ ) (.*)? $/x ) {
5812 ( $name, $body ) = ( $1, $2 );
5814 # Cannot start new abbreviation unless old abbreviation is complete
5815 last if ($opening_brace_line);
5817 $opening_brace_line = $line_no unless ( $body && $body =~ s/\}$// );
5819 # handle a new alias definition
5820 if ( $rexpansion->{$name} ) {
5821 local $LIST_SEPARATOR = ')(';
5822 my @names = sort keys %{$rexpansion};
5824 "Here is a list of all installed aliases\n(@names)\n"
5825 . "Attempting to redefine alias ($name) in config file $config_file line $INPUT_LINE_NUMBER\n";
5828 $rexpansion->{$name} = [];
5831 # leading opening braces not allowed
5832 elsif ( $line =~ /^{/ ) {
5833 $opening_brace_line = undef;
5835 "Unexpected '{' at line $line_no in config file '$config_file'\n";
5839 # Look for abbreviation closing: body } or }
5840 elsif ( $line =~ /^(.*)?\}$/ ) {
5842 if ($opening_brace_line) {
5843 $opening_brace_line = undef;
5847 "Unexpected '}' at line $line_no in config file '$config_file'\n";
5852 # no abbreviations to untangle
5855 # Now store any parameters
5858 my ( $rbody_parts, $msg ) = parse_args($body);
5860 $death_message = <<EOM;
5861 Error reading file '$config_file' at line number $line_no.
5863 Please fix this line or use -npro to avoid reading this file
5870 # remove leading dashes if this is an alias
5871 foreach ( @{$rbody_parts} ) { s/^\-+//; }
5872 push @{ $rexpansion->{$name} }, @{$rbody_parts};
5875 push( @config_list, @{$rbody_parts} );
5880 if ($opening_brace_line) {
5882 "Didn't see a '}' to match the '{' at line $opening_brace_line in config file '$config_file'\n";
5884 return ( \@config_list, $death_message );
5885 } ## end sub read_config_file
5887 sub strip_comments_and_join_quotes {
5889 my ( $rconfig_string, $config_file ) = @_;
5892 # 1. Strip comments from .perltidyrc lines
5893 # 2. Join lines which are spanned by a quote
5896 # $rconfig_string = the configuration file
5897 # $config_file = filename, for error messages
5899 # $rline_hash = hash with modified lines and their input numbers
5900 # $msg = any error message; code will die on any message.
5903 my $msg = EMPTY_STRING;
5904 my $rline_hash = [];
5906 # quote state variables
5907 my $quote_char = EMPTY_STRING;
5908 my $quote_start_line = EMPTY_STRING;
5909 my $quote_start_line_no = -1;
5910 my $in_string = EMPTY_STRING;
5911 my $out_string = EMPTY_STRING;
5913 my @lines = split /^/, ${$rconfig_string};
5917 foreach my $line (@lines) {
5921 next unless ( length($line) );
5923 if ( !$quote_char ) {
5925 # skip a full-line comment
5926 if ( substr( $line, 0, 1 ) eq '#' ) {
5930 $out_string = EMPTY_STRING;
5934 # treat previous newline as a space
5935 $in_string = SPACE . $line;
5938 # loop over string characters
5939 # $in_string = the input string
5940 # $out_string = the output string
5941 # $quote_char = quote character being sought
5944 # accumulating characters not in quote
5945 if ( !$quote_char ) {
5947 if ( $in_string =~ /\G([\"\'])/gc ) {
5949 # starting new quote..
5952 $quote_start_line_no = $line_no;
5953 $quote_start_line = $line;
5955 elsif ( $in_string =~ /\G#/gc ) {
5957 # A space is required before the # of a side comment
5958 # This allows something like:
5960 # Otherwise, it would have to be quoted:
5962 if ( !length($out_string) || $out_string =~ s/\s+$// ) {
5967 elsif ( $in_string =~ /\G([^\#\'\"]+)/gc ) {
5969 # neither quote nor side comment
5979 # looking for ending quote character
5981 if ( $in_string =~ /\G($quote_char)/gc ) {
5985 $quote_char = EMPTY_STRING;
5987 elsif ( $in_string =~ /\G([^$quote_char]+)/gc ) {
5989 # accumulate quoted text
6000 if ( !$quote_char ) {
6001 push @{$rline_hash},
6003 line => $out_string,
6004 line_no => $line_no,
6008 } ## end loop over lines
6012 if ( length($quote_start_line) > $max_len ) {
6014 substr( $quote_start_line, 0, $max_len - 3 ) . '...';
6017 Error: hit EOF reading file '$config_file' looking for end of quoted text
6018 which started at line $quote_start_line_no with quote character <$quote_char>:
6020 Please fix or use -npro to avoid reading this file
6023 return ( $rline_hash, $msg );
6024 } ## end sub strip_comments_and_join_quotes
6028 # Parse a command string containing multiple string with possible
6029 # quotes, into individual commands. It might look like this, for example:
6031 # -wba=" + - " -some-thing -wbb='. && ||'
6033 # There is no need, at present, to handle escaped quote characters.
6034 # (They are not perltidy tokens, so needn't be in strings).
6037 my @body_parts = ();
6038 my $quote_char = EMPTY_STRING;
6039 my $part = EMPTY_STRING;
6040 my $msg = EMPTY_STRING;
6042 # Check for external call with undefined $body - added to fix
6043 # github issue Perl-Tidy-Sweetened issue #23
6044 if ( !defined($body) ) { $body = EMPTY_STRING }
6048 # looking for ending quote character
6050 if ( $body =~ /\G($quote_char)/gc ) {
6051 $quote_char = EMPTY_STRING;
6053 elsif ( $body =~ /\G(.)/gc ) {
6057 # error..we reached the end without seeing the ending quote char
6059 if ( length($part) ) { push @body_parts, $part; }
6061 Did not see ending quote character <$quote_char> in this text:
6068 # accumulating characters and looking for start of a quoted string
6070 if ( $body =~ /\G([\"\'])/gc ) {
6073 elsif ( $body =~ /\G(\s+)/gc ) {
6074 if ( length($part) ) { push @body_parts, $part; }
6075 $part = EMPTY_STRING;
6077 elsif ( $body =~ /\G(.)/gc ) {
6081 if ( length($part) ) { push @body_parts, $part; }
6086 return ( \@body_parts, $msg );
6087 } ## end sub parse_args
6089 sub dump_long_names {
6092 print {*STDOUT} <<EOM;
6093 # Command line long names (passed to GetOptions)
6094 #--------------------------------------------------
6095 # here is a summary of the Getopt codes:
6096 # <none> does not take an argument
6097 # =s takes a mandatory string
6098 # :s takes an optional string
6099 # =i takes a mandatory integer
6100 # :i takes an optional integer
6101 # ! does not take an argument and may be negated
6102 # i.e., -foo and -nofoo are allowed
6103 # a double dash signals the end of the options list
6105 #--------------------------------------------------
6108 foreach my $name ( sort @names ) { print {*STDOUT} "$name\n" }
6110 } ## end sub dump_long_names
6112 sub dump_integer_option_range {
6113 my ($rinteger_option_range) = @_;
6114 print {*STDOUT} "Option, min, max, default\n";
6115 foreach my $key ( sort keys %{$rinteger_option_range} ) {
6116 my ( $min, $max, $default ) = @{ $rinteger_option_range->{$key} };
6117 foreach ( $min, $max, $default ) {
6118 $_ = 'undef' unless defined($_);
6120 print {*STDOUT} "$key, $min, $max, $default\n";
6123 } ## end sub dump_integer_option_range
6127 print {*STDOUT} "Default command line options:\n";
6128 foreach my $line ( sort @defaults ) { print {*STDOUT} "$line\n" }
6130 } ## end sub dump_defaults
6132 sub readable_options {
6134 # return options for this run as a string which could be
6135 # put in a perltidyrc file
6136 my ( $rOpts, $roption_string ) = @_;
6138 my $rGetopt_flags = \%Getopt_flags;
6139 my $readable_options = "# Final parameter set for this run.\n";
6140 $readable_options .=
6141 "# See utility 'perltidyrc_dump.pl' for nicer formatting.\n";
6142 foreach my $opt ( @{$roption_string} ) {
6143 my $flag = EMPTY_STRING;
6144 if ( $opt =~ /(.*)(!|=.*)$/ ) {
6148 if ( defined( $rOpts->{$opt} ) ) {
6149 $rGetopt_flags->{$opt} = $flag;
6152 foreach my $key ( sort keys %{$rOpts} ) {
6153 my $flag = $rGetopt_flags->{$key};
6154 my $value = $rOpts->{$key};
6156 my $suffix = EMPTY_STRING;
6158 if ( $flag =~ /^=/ ) {
6159 if ( $value !~ /^\d+$/ ) { $value = '"' . $value . '"' }
6160 $suffix = "=" . $value;
6162 elsif ( $flag =~ /^!/ ) {
6163 $prefix .= "no" unless ($value);
6168 $readable_options .=
6169 "# ERROR in dump_options: unrecognized flag $flag for $key\n";
6172 $readable_options .= $prefix . $key . $suffix . "\n";
6174 return $readable_options;
6175 } ## end sub readable_options
6178 print {*STDOUT} <<"EOM";
6179 This is perltidy, v$VERSION
6181 Copyright 2000-2025 by Steve Hancock
6183 Perltidy is free software and may be copied under the terms of the GNU
6184 General Public License, which is included in the distribution files.
6186 Documentation can be found using 'man perltidy'
6187 or at GitHub https://perltidy.github.io/perltidy/
6188 or at metacpan https://metacpan.org/pod/distribution/Perl-Tidy/bin/perltidy
6189 or at Sourceforge https://perltidy.sourceforge.net
6192 } ## end sub show_version
6196 print {*STDOUT} <<EOF;
6197 This is perltidy version $VERSION, a perl script indenter. Usage:
6199 perltidy [ options ] file1 file2 file3 ...
6200 (output goes to file1.tdy, file2.tdy, file3.tdy, ...)
6201 perltidy [ options ] file1 -o outfile
6202 perltidy [ options ] file1 -st >outfile
6203 perltidy [ options ] <infile >outfile
6205 Options have short and long forms. Short forms are shown; see
6206 man pages for long forms. Note: '=s' indicates a required string,
6207 and '=n' indicates a required integer.
6211 -o=file name of the output file (only if single input file)
6212 -oext=s change output extension from 'tdy' to s
6213 -opath=path change path to be 'path' for output files
6214 -b backup original to .bak and modify file in-place
6215 -bext=s change default backup extension from 'bak' to s
6216 -q deactivate error messages (for running under editor)
6217 -w include non-critical warning messages in the .ERR error output
6218 -log save .LOG file, which has useful diagnostics
6219 -f force perltidy to read a binary file
6220 -g like -log but writes more detailed .LOG file, for debugging scripts
6221 -opt write the set of options actually used to a .LOG file
6222 -npro ignore .perltidyrc configuration command file
6223 -pro=file read configuration commands from file instead of .perltidyrc
6224 -st send output to standard output, STDOUT
6225 -se send all error output to standard error output, STDERR
6226 -v display version number to standard output and quit
6229 -i=n use n columns per indentation level (default n=4)
6230 -t tabs: use one tab character per indentation level, not recommended
6231 -nt no tabs: use n spaces per indentation level (default)
6232 -et=n entab leading whitespace n spaces per tab; not recommended
6233 -io "indent only": just do indentation, no other formatting.
6234 -sil=n set starting indentation level to n; use if auto detection fails
6235 -ole=s specify output line ending (s=dos or win, mac, unix)
6236 -ple keep output line endings same as input (input must be filename)
6239 -fws freeze whitespace; this disables all whitespace changes
6240 and disables the following switches:
6241 -bt=n sets brace tightness, n= (0 = loose, 1=default, 2 = tight)
6242 -bbt same as -bt but for code block braces; same as -bt if not given
6243 -bbvt block braces vertically tight; use with -bl or -bli
6244 -bbvtl=s make -bbvt to apply to selected list of block types
6245 -pt=n paren tightness (n=0, 1 or 2)
6246 -sbt=n square bracket tightness (n=0, 1, or 2)
6247 -bvt=n brace vertical tightness,
6248 n=(0=open, 1=close unless multiple steps on a line, 2=always close)
6249 -pvt=n paren vertical tightness (see -bvt for n)
6250 -sbvt=n square bracket vertical tightness (see -bvt for n)
6251 -bvtc=n closing brace vertical tightness:
6252 n=(0=open, 1=sometimes close, 2=always close)
6253 -pvtc=n closing paren vertical tightness, see -bvtc for n.
6254 -sbvtc=n closing square bracket vertical tightness, see -bvtc for n.
6255 -ci=n sets continuation indentation=n, default is n=2 spaces
6256 -lp line up parentheses, brackets, and non-BLOCK braces
6257 -sfs add space before semicolon in for( ; ; )
6258 -aws allow perltidy to add whitespace (default)
6259 -dws delete all old non-essential whitespace
6260 -icb indent closing brace of a code block
6261 -cti=n closing indentation of paren, square bracket, or non-block brace:
6262 n=0 none, =1 align with opening, =2 one full indentation level
6263 -icp equivalent to -cti=2
6264 -wls=s want space left of tokens in string; i.e. -nwls='+ - * /'
6265 -wrs=s want space right of tokens in string;
6266 -sts put space before terminal semicolon of a statement
6267 -sak=s put space between keywords given in s and '(';
6268 -nsak=s no space between keywords in s and '('; i.e. -nsak='my our local'
6271 -fnl freeze newlines; this disables all line break changes
6272 and disables the following switches:
6273 -anl add newlines; ok to introduce new line breaks
6274 -bbs add blank line before subs and packages
6275 -bbc add blank line before block comments
6276 -bbb add blank line between major blocks
6277 -kbl=n keep old blank lines? 0=no, 1=some, 2=all
6278 -mbl=n maximum consecutive blank lines to output (default=1)
6279 -ce cuddled else; use this style: '} else {'
6280 -cb cuddled blocks (other than 'if-elsif-else')
6281 -cbl=s list of blocks to cuddled, default 'try-catch-finally'
6282 -dnl delete old newlines (default)
6283 -l=n maximum line length; default n=80
6284 -bl opening brace on new line
6285 -sbl opening sub brace on new line. value of -bl is used if not given.
6286 -bli opening brace on new line and indented
6287 -bar opening brace always on right, even for long clauses
6288 -vt=n vertical tightness (requires -lp); n controls break after opening
6289 token: 0=never 1=no break if next line balanced 2=no break
6290 -vtc=n vertical tightness of closing container; n controls if closing
6291 token starts new line: 0=always 1=not unless list 1=never
6292 -wba=s want break after tokens in string; i.e. wba=': .'
6293 -wbb=s want break before tokens in string
6294 -wn weld nested: combines opening and closing tokens when both are adjacent
6295 -wnxl=s weld nested exclusion list: provides some control over the types of
6296 containers which can be welded
6298 Following Old Breakpoints
6299 -kis keep interior semicolons. Allows multiple statements per line.
6300 -boc break at old comma breaks: turns off all automatic list formatting
6301 -bol break at old logical breakpoints: or, and, ||, && (default)
6302 -bom break at old method call breakpoints: ->
6303 -bok break at old list keyword breakpoints such as map, sort (default)
6304 -bot break at old conditional (ternary ?:) operator breakpoints (default)
6305 -boa break at old attribute breakpoints
6306 -cab=n break at commas after a comma-arrow (=>):
6307 n=0 break at all commas after =>
6308 n=1 stable: break unless this breaks an existing one-line container
6309 n=2 break only if a one-line container cannot be formed
6310 n=3 do not treat commas after => specially at all
6313 -ibc indent block comments (default)
6314 -isbc indent spaced block comments; may indent unless no leading space
6315 -msc=n minimum desired spaces to side comment, default 4
6316 -fpsc=n fix position for side comments; default 0;
6317 -csc add or update closing side comments after closing BLOCK brace
6318 -dcsc delete closing side comments created by a -csc command
6319 -cscp=s change closing side comment prefix to be other than '## end'
6320 -cscl=s change closing side comment to apply to selected list of blocks
6321 -csci=n minimum number of lines needed to apply a -csc tag, default n=6
6322 -csct=n maximum number of columns of appended text, default n=20
6323 -cscw causes warning if old side comment is overwritten with -csc
6325 -sbc use 'static block comments' identified by leading '##' (default)
6326 -sbcp=s change static block comment identifier to be other than '##'
6327 -osbc outdent static block comments
6329 -ssc use 'static side comments' identified by leading '##' (default)
6330 -sscp=s change static side comment identifier to be other than '##'
6332 Delete selected text
6333 -dac delete all comments AND pod
6334 -dbc delete block comments
6335 -dsc delete side comments
6338 Send selected text to a '.TEE' file
6339 -tac tee all comments AND pod
6340 -tbc tee block comments
6341 -tsc tee side comments
6345 -olq outdent long quoted strings (default)
6346 -olc outdent a long block comment line
6347 -ola outdent statement labels
6348 -okw outdent control keywords (redo, next, last, goto, return)
6349 -okwl=s specify alternative keywords for -okw command
6352 -mft=n maximum fields per table; default n=0 (no limit)
6353 -x do not format lines before hash-bang line (i.e., for VMS)
6354 -asc allows perltidy to add a ';' when missing (default)
6355 -dsm allows perltidy to delete an unnecessary ';' (default)
6357 Combinations of other parameters
6358 -gnu attempt to follow GNU Coding Standards as applied to perl
6359 -mangle remove as many newlines as possible (but keep comments and pods)
6360 -extrude insert as many newlines as possible
6362 Dump and die, debugging
6363 -dop dump options used in this run to standard output and quit
6364 -ddf dump default options to standard output and quit
6365 -dsn dump all option short names to standard output and quit
6366 -dln dump option long names to standard output and quit
6367 -dpro dump whatever configuration file is in effect to standard output
6368 -dtt dump all token types to standard output and quit
6371 -html write an html file (see 'man perl2web' for many options)
6372 Note: when -html is used, no indentation or formatting are done.
6373 Hint: try perltidy -html -css=mystyle.css filename.pl
6374 and edit mystyle.css to change the appearance of filename.html.
6375 -nnn gives line numbers
6376 -pre only writes out <pre>..</pre> code section
6377 -toc places a table of contents to subs at the top (default)
6378 -pod passes pod text through pod2html (default)
6379 -frm write html as a frame (3 files)
6380 -text=s extra extension for table of contents if -frm, default='toc'
6381 -sext=s extra extension for file content if -frm, default='src'
6383 A prefix of "n" negates short form toggle switches, and a prefix of "no"
6384 negates the long forms. For example, -nasc means don't add missing
6387 If you are unable to see this entire text, try "perltidy -h | more"
6388 For more detailed information, and additional options, try "man perltidy",
6389 or see https://metacpan.org/pod/distribution/Perl-Tidy/bin/perltidy