From: don Date: Mon, 14 Feb 2011 23:11:34 +0000 (+0000) Subject: New upstream release (closes: #613417) X-Git-Tag: debian/20170521-1~31 X-Git-Url: https://git.donarmstrong.com/?p=perltidy.git;a=commitdiff_plain;h=5c180637bf79ffc2af10f6654d308ce39e2f1f67 New upstream release (closes: #613417) --- diff --git a/BUGS b/BUGS index 12a470d..f43ea14 100644 --- a/BUGS +++ b/BUGS @@ -15,3 +15,17 @@ Perltidy open BUGS Since the --extrude option is typically only used for testing perltidy, this type of error should not normally occur in practice. + In some rare instances the formatting can oscillate between two states + The following example was sent by Denis Moskowitz, Oct 29 2010: + + grep { $_->foo ne 'bar' } # asdfa asdf asdf asdf asdf asdf asdf asdf + asdf asdf asdf @baz; + + With standard parameters this oscillates between the above and: + + grep { $_->foo ne 'bar' } # asdfa asdf asdf asdf asdf asdf asdf asdf + asdf asdf asdf @baz; + + A workaround here would be to make a slight change to the side comment + length. + diff --git a/CHANGES b/CHANGES index b04607e..1d8905b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,53 @@ Perltidy Change Log + 2010 12 17 + - added new flag -it=n or --iterations=n + This flag causes perltidy to do n complete iterations. + For most purposes the default of n=1 should be satisfactory. However n=2 + can be useful when a major style change is being made, or when code is being + beautified on check-in to a source code control system. The run time will be + approximately proportional to n, and it should seldom be necessary to use a + value greater than n=2. Thanks to Jonathan Swartz + + - A configuration file pathname begins with three dots, e.g. + ".../.perltidyrc", indicates that the file should be searched for starting + in the current directory and working upwards. This makes it easier to have + multiple projects each with their own .perltidyrc in their root directories. + Thanks to Jonathan Swartz for this patch. + + - Added flag --notidy which disables all formatting and causes the input to be + copied unchanged. This can be useful in conjunction with hierarchical + F<.perltidyrc> files to prevent unwanted tidying. + Thanks to Jonathan Swartz for this patch. + + - Added prefilters and postfilters in the call to the Tidy.pm module. + Prefilters and postfilters. The prefilter is a code reference that + will be applied to the source before tidying, and the postfilter + is a code reference to the result before outputting. + + Thanks to Jonathan Swartz for this patch. He writes: + This is useful for all manner of customizations. For example, I use + it to convert the 'method' keyword to 'sub' so that perltidy will work for + Method::Signature::Simple code: + + Perl::Tidy::perltidy( + prefilter => sub { $_ = $_[0]; s/^method (.*)/sub $1 \#__METHOD/gm; return $_ }, + postfilter => sub { $_ = $_[0]; s/^sub (.*?)\s* \#__METHOD/method $1/gm; return $_ } + ); + + - The starting indentation level of sections of code entabbed with -et=n + is correctly guessed if it was also produced with the same -et=n flag. This + keeps the indentation stable on repeated formatting passes within an editor. + Thanks to Sam Kington and Glenn. + + - Functions with prototype '&' had a space between the function and opening + peren. This space now only occurs if the flag --space-function-paren (-sfp) + is set. Thanks to Zrajm Akfohg. + + - Patch to never put spaces around a bare word in braces beginning with ^ as in: + my $before = ${^PREMATCH}; + even if requested with the -bt=0 flag because any spaces cause a syntax error in perl. + Thanks to Fabrice Dulanoy. + 2009 06 16 - Allow configuration file to be 'perltidy.ini' for Windows systems. i.e. C:\Documents and Settings\User\perltidy.ini diff --git a/MANIFEST b/MANIFEST index f3b4e31..24bb10c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -31,6 +31,8 @@ examples/perlxmltok.pl examples/pt.bat examples/testfa.t examples/testff.t +examples/filter_example.pl +examples/filter_example.in lib/Perl/Tidy.pm pm2pl t/test.t diff --git a/META.yml b/META.yml index b6a8460..54aac27 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name: Perl-Tidy -version: 20090616 +version: 20101217 abstract: indent and reformat perl scripts license: ~ author: diff --git a/TODO b/TODO index 8b0aa0f..bb1f874 100644 --- a/TODO +++ b/TODO @@ -1,27 +1,6 @@ Perltidy TODO List This is a partial "wish-list" of features to add and things to do. - Perltidy not idempotent - Perltidy does a single pass but iterates locally to try to satisfy the - various constraints and formatting parameters, but in some cases it can - take a second pass to reach a stable format, particularly when major - format style changes are made. It would be useful to have a flag to - force a second pass, say --passes=2. - - For now, a workaround for a single file is - - perltidy file.pl -st | perltidy -o file.tdy - - The starting indentation level is not correctly guessed when tabs are used - When formatting a snippet which does not begin at zero indentation, - perltidy must guess the starting indentation. The -sil flag can be used - to specify this, but this is tedious. In general we cannot know the - indentation and can only guess, but we can at least require that if - perltidy is run twice on the same snippet, with the same parameters, - that the indentation be correctly guessed on the second pass. Currently, - this is only true if there are no tabs in the leading whitespace. A - patch has been submitted to fix this but it needs a little work still. - -b does not work through the Tidy module The use of -b in the following does not work: diff --git a/bin/perltidy b/bin/perltidy index c9c8ffc..b39c71f 100755 --- a/bin/perltidy +++ b/bin/perltidy @@ -305,6 +305,11 @@ name of .perltidyrc. There must not be a space on either side of the would cause file F to be used instead of the default F<.perltidyrc>. +A pathname begins with three dots, e.g. ".../.perltidyrc", indicates that +the file should be searched for starting in the current directory and +working upwards. This makes it easier to have multiple projects each with +their own .perltidyrc in their root directories. + =item B<-opt>, B<--show-options> Write a list of all options used to the F<.LOG> file. @@ -325,6 +330,15 @@ as non-text, and this flag forces perltidy to process them. =over 4 +=item B<--notidy> + +This flag disables all formatting and causes the input to be copied unchanged +to the output except for possible changes in line ending characters and any +pre- and post-filters. This can be useful in conjunction with a hierarchical +set of F<.perltidyrc> files to avoid unwanted code tidying. See also +L for a way to avoid tidying specific +sections of code. + =item B<-l=n>, B<--maximum-line-length=n> The default maximum line length is n=80 characters. Perltidy will try @@ -434,6 +448,17 @@ input comes from a filename (rather than stdin, for example). If perltidy has trouble determining the input file line ending, it will revert to the default behavior of using the line ending of the host system. +=item B<-it=n>, B<--iterations=n> + +This flag causes perltidy to do B complete iterations. The reason for this +flag is that code beautification is a somewhat iterative process and in some +cases the output from perltidy can be different if it is applied a second time. +For most purposes the default of B should be satisfactory. However B +can be useful when a major style change is being made, or when code is being +beautified on check-in to a source code control system. The run time will be +approximately proportional to B, and it should seldom be necessary to use a +value greater than B. This flag has no effect when perltidy is used to generate html. + =back =head2 Code Indentation Control @@ -2794,7 +2819,7 @@ perlstyle(1), Perl::Tidy(3) =head1 VERSION -This man page documents perltidy version 20090616. +This man page documents perltidy version 20101217. =head1 CREDITS @@ -2819,7 +2844,7 @@ see the CHANGES file. =head1 COPYRIGHT -Copyright (c) 2000-2008 by Steve Hancock +Copyright (c) 2000-2010 by Steve Hancock =head1 LICENSE diff --git a/debian/changelog b/debian/changelog index 54c7130..b10f0b1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +perltidy (20101217-1) unstable; urgency=low + + * New upstream release (closes: #613417) + + -- Don Armstrong Mon, 14 Feb 2011 15:10:43 -0800 + perltidy (20090616-1) unstable; urgency=low * New upstream release diff --git a/docs/perltidy.1 b/docs/perltidy.1 index d7941da..0805ace 100644 --- a/docs/perltidy.1 +++ b/docs/perltidy.1 @@ -124,7 +124,7 @@ .\" ======================================================================== .\" .IX Title "PERLTIDY 1" -.TH PERLTIDY 1 "2009-06-16" "perl v5.10.0" "User Contributed Perl Documentation" +.TH PERLTIDY 1 "2010-12-13" "perl v5.10.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -429,6 +429,11 @@ name of .perltidyrc. There must not be a space on either side of the .Sp would cause file \fItestcfg\fR to be used instead of the default \fI.perltidyrc\fR. +.Sp +A pathname begins with three dots, e.g. \*(L".../.perltidyrc\*(R", indicates that +the file should be searched for starting in the current directory and +working upwards. This makes it easier to have multiple projects each with +their own .perltidyrc in their root directories. .IP "\fB\-opt\fR, \fB\-\-show\-options\fR" 4 .IX Item "-opt, --show-options" Write a list of all options used to the \fI.LOG\fR file. @@ -443,6 +448,14 @@ as non-text, and this flag forces perltidy to process them. .IX Header "FORMATTING OPTIONS" .SS "Basic Options" .IX Subsection "Basic Options" +.IP "\fB\-\-notidy\fR" 4 +.IX Item "--notidy" +This flag disables all formatting and causes the input to be copied unchanged +to the output except for possible changes in line ending characters and any +pre\- and post-filters. This can be useful in conjunction with a hierarchical +set of \fI.perltidyrc\fR files to avoid unwanted code tidying. See also +\&\*(L"Skipping Selected Sections of Code\*(R" for a way to avoid tidying specific +sections of code. .IP "\fB\-l=n\fR, \fB\-\-maximum\-line\-length=n\fR" 4 .IX Item "-l=n, --maximum-line-length=n" The default maximum line length is n=80 characters. Perltidy will try @@ -542,6 +555,16 @@ endings as the input file, if possible. It should work for input comes from a filename (rather than stdin, for example). If perltidy has trouble determining the input file line ending, it will revert to the default behavior of using the line ending of the host system. +.IP "\fB\-it=n\fR, \fB\-\-iterations=n\fR" 4 +.IX Item "-it=n, --iterations=n" +This flag causes perltidy to do \fBn\fR complete iterations. The reason for this +flag is that code beautification is a somewhat iterative process and in some +cases the output from perltidy can be different if it is applied a second time. +For most purposes the default of \fBn=1\fR should be satisfactory. However \fBn=2\fR +can be useful when a major style change is being made, or when code is being +beautified on check-in to a source code control system. The run time will be +approximately proportional to \fBn\fR, and it should seldom be necessary to use a +value greater than \fBn=2\fR. This flag has no effect when perltidy is used to generate html. .SS "Code Indentation Control" .IX Subsection "Code Indentation Control" .IP "\fB\-ci=n\fR, \fB\-\-continuation\-indentation=n\fR" 4 @@ -2879,7 +2902,7 @@ purpose of this rule is to prevent generating confusing filenames such as \&\fIperlstyle\fR\|(1), \fIPerl::Tidy\fR\|(3) .SH "VERSION" .IX Header "VERSION" -This man page documents perltidy version 20090616. +This man page documents perltidy version 20101217. .SH "CREDITS" .IX Header "CREDITS" Michael Cartmell supplied code for adaptation to \s-1VMS\s0 and helped with @@ -2903,7 +2926,7 @@ see the \s-1CHANGES\s0 file. .Ve .SH "COPYRIGHT" .IX Header "COPYRIGHT" -Copyright (c) 2000\-2008 by Steve Hancock +Copyright (c) 2000\-2010 by Steve Hancock .SH "LICENSE" .IX Header "LICENSE" This package is free software; you can redistribute it and/or modify it diff --git a/examples/filter_example.in b/examples/filter_example.in new file mode 100644 index 0000000..70172e5 --- /dev/null +++ b/examples/filter_example.in @@ -0,0 +1,16 @@ +# input file for testing filter_example.pl +use Method::Signatures::Simple; + + method foo { $self->bar } + + # with signature + method foo($bar, %opts) { $self->bar(reverse $bar) if $opts{rev}; + } + + # attributes + method foo : lvalue { $self->{foo} +} + + # change invocant name + method +foo ($class: $bar) { $class->bar($bar) } diff --git a/examples/filter_example.pl b/examples/filter_example.pl new file mode 100644 index 0000000..7704ca4 --- /dev/null +++ b/examples/filter_example.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl -w +use Perl::Tidy; + +# Illustrate use of prefilter and postfilter parameters to perltidy. +# This example program uses a prefilter it to convert the 'method' +# keyword to 'sub', and a postfilter to convert back, so that perltidy will +# work for Method::Signature::Simple code. +# NOTE: This program illustrates the use of filters but has not been +# extensively tested. + +# usage: +# perl filter_example.pl filter_example.in +# +# How it works: +# 1. First the prefilter changes lines beginning with 'method foo' to 'sub +# METHOD_foo' +# 2. Then perltidy formats the code +# 3. Then the postfilter changes 'sub METHOD_' to 'method ' everywhere. +# (This assumes that there are no methods named METHOD_*, and that the keyword +# method always begins a line in the input file). +# +# Debugging hints: +# 1. Try commenting out the postfilter and running with +# the --notidy option to see what the prefilter alone is doing. +# 2. Then run with both pre- and post ters with --notidy to be sure +# that the postfilter properly undoes the prefilter. + +my $arg_string = undef; +Perl::Tidy::perltidy( + argv => $arg_string, + prefilter => + sub { $_ = $_[0]; s/^\s*method\s+(\w.*)/sub METHOD_$1/gm; return $_ }, + postfilter => + sub { $_ = $_[0]; s/sub\s+METHOD_/method /gm; return $_ } +); +__END__ + +# Try running on the following code (file filter_example.in): + +use Method::Signatures::Simple; + + method foo { $self->bar } + + # with signature + method foo($bar, %opts) { $self->bar(reverse $bar) if $opts{rev}; + } + + # attributes + method foo : lvalue { $self->{foo} +} + + # change invocant name + method +foo ($class: $bar) { $class->bar($bar) } diff --git a/lib/Perl/Tidy.pm b/lib/Perl/Tidy.pm index c190f80..35cea35 100644 --- a/lib/Perl/Tidy.pm +++ b/lib/Perl/Tidy.pm @@ -1,3 +1,4 @@ +# ############################################################ # # perltidy - a perl script indenter and formatter @@ -27,7 +28,7 @@ # # perltidy Tidy.pm # -# Code Contributions: +# Code Contributions: See ChangeLog.html for a complete history. # Michael Cartmell supplied code for adaptation to VMS and helped with # v-strings. # Hugh S. Myers supplied sub streamhandle and the supporting code to @@ -37,6 +38,15 @@ # Sebastien Aperghis-Tramoni supplied a patch for the defined or operator. # Dan Tyrell contributed a patch for binary I/O. # Ueli Hugenschmidt contributed a patch for -fpsc +# Sam Kington supplied a patch to identify the initial indentation of +# entabbed code. +# jonathan swartz supplied patches for: +# * .../ pattern, which looks upwards from directory +# * --notidy, to be used in directories where we want to avoid +# accidentally tidying +# * prefilter and postfilter +# * iterations option +# # Many others have supplied key ideas, suggestions, and bug reports; # see the CHANGES file. # @@ -61,11 +71,12 @@ use vars qw{ @ISA = qw( Exporter ); @EXPORT = qw( &perltidy ); +use Cwd; use IO::File; use File::Basename; BEGIN { - ( $VERSION = q($Id: Tidy.pm,v 1.74 2009/06/16 13:56:49 perltidy Exp $) ) =~ s/^.*\s+(\d+)\/(\d+)\/(\d+).*$/$1$2$3/; # all one line for MakeMaker + ( $VERSION = q($Id: Tidy.pm,v 1.74 2010/12/17 13:56:49 perltidy Exp $) ) =~ s/^.*\s+(\d+)\/(\d+)\/(\d+).*$/$1$2$3/; # all one line for MakeMaker } sub streamhandle { @@ -335,6 +346,8 @@ sub make_temporary_filename { dump_options_category => undef, dump_options_range => undef, dump_abbreviations => undef, + prefilter => undef, + postfilter => undef, ); # don't overwrite callers ARGV @@ -383,6 +396,8 @@ EOM my $source_stream = $input_hash{'source'}; my $stderr_stream = $input_hash{'stderr'}; my $user_formatter = $input_hash{'formatter'}; + my $prefilter = $input_hash{'prefilter'}; + my $postfilter = $input_hash{'postfilter'}; # various dump parameters my $dump_options_type = $input_hash{'dump_options_type'}; @@ -769,6 +784,20 @@ EOM $rpending_logfile_message ); next unless ($source_object); + # Prefilters and postfilters: The prefilter is a code reference + # that will be applied to the source before tidying, and the + # postfilter is a code reference to the result before outputting. + if ($prefilter) { + my $buf = ''; + while ( my $line = $source_object->get_line() ) { + $buf .= $line; + } + $buf = $prefilter->($buf); + + $source_object = Perl::Tidy::LineSource->new( \$buf, $rOpts, + $rpending_logfile_message ); + } + # register this file name with the Diagnostics package $diagnostics_object->set_input_file($input_file) if $diagnostics_object; @@ -863,9 +892,19 @@ EOM if ( defined($line_separator) ) { $binmode = 1 } else { $line_separator = "\n" } - my $sink_object = - Perl::Tidy::LineSink->new( $output_file, $tee_file, - $line_separator, $rOpts, $rpending_logfile_message, $binmode ); + my ( $sink_object, $postfilter_buffer ); + if ($postfilter) { + $sink_object = + Perl::Tidy::LineSink->new( \$postfilter_buffer, $tee_file, + $line_separator, $rOpts, $rpending_logfile_message, + $binmode ); + } + else { + $sink_object = + Perl::Tidy::LineSink->new( $output_file, $tee_file, + $line_separator, $rOpts, $rpending_logfile_message, + $binmode ); + } #--------------------------------------------------------------- # initialize the error logger @@ -898,65 +937,106 @@ EOM Perl::Tidy::Debugger->new( $fileroot . $dot . "DEBUG" ); } - #--------------------------------------------------------------- - # create a formatter for this file : html writer or pretty printer - #--------------------------------------------------------------- + # loop over iterations + my $max_iterations = $rOpts->{'iterations'}; + my $sink_object_final = $sink_object; + for ( my $iter = 1 ; $iter <= $max_iterations ; $iter++ ) { + my $temp_buffer; - # we have to delete any old formatter because, for safety, - # the formatter will check to see that there is only one. - $formatter = undef; + # local copies of some debugging objects which get deleted + # after first iteration, but will reappear after this loop + my $debugger_object = $debugger_object; + my $logger_object = $logger_object; + my $diagnostics_object = $diagnostics_object; - if ($user_formatter) { - $formatter = $user_formatter; - } - elsif ( $rOpts->{'format'} eq 'html' ) { - $formatter = - Perl::Tidy::HtmlWriter->new( $fileroot, $output_file, - $actual_output_extension, $html_toc_extension, - $html_src_extension ); - } - elsif ( $rOpts->{'format'} eq 'tidy' ) { - $formatter = Perl::Tidy::Formatter->new( + # output to temp buffer until last iteration + if ( $iter < $max_iterations ) { + $sink_object = + Perl::Tidy::LineSink->new( \$temp_buffer, $tee_file, + $line_separator, $rOpts, $rpending_logfile_message, + $binmode ); + } + else { + $sink_object = $sink_object_final; + + # terminate some debugging output after first pass + # to avoid needless output. + $debugger_object = undef; + $logger_object = undef; + $diagnostics_object = undef; + } + + #--------------------------------------------------------------- + # create a formatter for this file : html writer or pretty printer + #--------------------------------------------------------------- + + # we have to delete any old formatter because, for safety, + # the formatter will check to see that there is only one. + $formatter = undef; + + if ($user_formatter) { + $formatter = $user_formatter; + } + elsif ( $rOpts->{'format'} eq 'html' ) { + $formatter = + Perl::Tidy::HtmlWriter->new( $fileroot, $output_file, + $actual_output_extension, $html_toc_extension, + $html_src_extension ); + } + elsif ( $rOpts->{'format'} eq 'tidy' ) { + $formatter = Perl::Tidy::Formatter->new( + logger_object => $logger_object, + diagnostics_object => $diagnostics_object, + sink_object => $sink_object, + ); + } + else { + die "I don't know how to do -format=$rOpts->{'format'}\n"; + } + + unless ($formatter) { + die + "Unable to continue with $rOpts->{'format'} formatting\n"; + } + + #--------------------------------------------------------------- + # create the tokenizer for this file + #--------------------------------------------------------------- + $tokenizer = undef; # must destroy old tokenizer + $tokenizer = Perl::Tidy::Tokenizer->new( + source_object => $source_object, logger_object => $logger_object, + debugger_object => $debugger_object, diagnostics_object => $diagnostics_object, - sink_object => $sink_object, + starting_level => $rOpts->{'starting-indentation-level'}, + tabs => $rOpts->{'tabs'}, + entab_leading_space => $rOpts->{'entab-leading-whitespace'}, + indent_columns => $rOpts->{'indent-columns'}, + look_for_hash_bang => $rOpts->{'look-for-hash-bang'}, + look_for_autoloader => $rOpts->{'look-for-autoloader'}, + look_for_selfloader => $rOpts->{'look-for-selfloader'}, + trim_qw => $rOpts->{'trim-qw'}, ); - } - else { - die "I don't know how to do -format=$rOpts->{'format'}\n"; - } - unless ($formatter) { - die "Unable to continue with $rOpts->{'format'} formatting\n"; - } + #--------------------------------------------------------------- + # now we can do it + #--------------------------------------------------------------- + process_this_file( $tokenizer, $formatter ); - #--------------------------------------------------------------- - # create the tokenizer for this file - #--------------------------------------------------------------- - $tokenizer = undef; # must destroy old tokenizer - $tokenizer = Perl::Tidy::Tokenizer->new( - source_object => $source_object, - logger_object => $logger_object, - debugger_object => $debugger_object, - diagnostics_object => $diagnostics_object, - starting_level => $rOpts->{'starting-indentation-level'}, - tabs => $rOpts->{'tabs'}, - indent_columns => $rOpts->{'indent-columns'}, - look_for_hash_bang => $rOpts->{'look-for-hash-bang'}, - look_for_autoloader => $rOpts->{'look-for-autoloader'}, - look_for_selfloader => $rOpts->{'look-for-selfloader'}, - trim_qw => $rOpts->{'trim-qw'}, - ); + #--------------------------------------------------------------- + # close the input source and report errors + #--------------------------------------------------------------- + $source_object->close_input_file(); - #--------------------------------------------------------------- - # now we can do it - #--------------------------------------------------------------- - process_this_file( $tokenizer, $formatter ); + # line source for next iteration (if any) comes from the current + # temporary buffer + if ( $iter < $max_iterations ) { + $source_object = + Perl::Tidy::LineSource->new( \$temp_buffer, $rOpts, + $rpending_logfile_message ); + } - #--------------------------------------------------------------- - # close the input source and report errors - #--------------------------------------------------------------- - $source_object->close_input_file(); + } # end loop over iterations # get file names to use for syntax check my $ifname = $source_object->get_input_file_copy_name(); @@ -1006,6 +1086,17 @@ EOM $sink_object->close_output_file() if $sink_object; $debugger_object->close_debug_file() if $debugger_object; + if ($postfilter) { + my $new_sink = + Perl::Tidy::LineSink->new( $output_file, $tee_file, + $line_separator, $rOpts, $rpending_logfile_message, + $binmode ); + my $buf = $postfilter->($postfilter_buffer); + foreach my $line ( split( "\n", $buf ) ) { + $new_sink->write_line($line); + } + } + my $infile_syntax_ok = 0; # -1 no 0=don't know 1 yes if ($output_file) { @@ -1178,6 +1269,7 @@ sub generate_options { npro recombine! valign! + notidy ); my $category = 13; # Debugging @@ -1226,6 +1318,7 @@ sub generate_options { $add_option->( 'backup-file-extension', 'bext', '=s' ); $add_option->( 'force-read-binary', 'f', '!' ); $add_option->( 'format', 'fmt', '=s' ); + $add_option->( 'iterations', 'it', '=i' ); $add_option->( 'logfile', 'log', '!' ); $add_option->( 'logfile-gap', 'g', ':i' ); $add_option->( 'outfile', 'o', '=s' ); @@ -1521,6 +1614,7 @@ sub generate_options { hanging-side-comments indent-block-comments indent-columns=4 + iterations=1 keep-old-blank-lines=1 long-block-line-count=8 look-for-autoloader @@ -1819,6 +1913,21 @@ sub process_command_line { "Only one -pro=filename allowed, using '$2' instead of '$config_file'\n"; } $config_file = $2; + + # resolve /.../, meaning look upwards from directory + if ( defined($config_file) ) { + if ( my ( $start_dir, $search_file ) = + ( $config_file =~ m{^(.*)\.\.\./(.*)$} ) ) + { + $start_dir = '.' if !$start_dir; + $start_dir = Cwd::realpath($start_dir); + if ( my $found_file = + find_file_upwards( $start_dir, $search_file ) ) + { + $config_file = $found_file; + } + } + } unless ( -e $config_file ) { warn "cannot find file given with -pro=$config_file: $!\n"; $config_file = ""; @@ -2062,6 +2171,20 @@ sub check_options { } } + # check iteration count and quietly fix if necessary: + # - iterations option only applies to code beautification mode + # - it shouldn't be nessary to use more than about 2 iterations + if ( $rOpts->{'format'} ne 'tidy' ) { + $rOpts->{'iterations'} = 1; + } + elsif ( defined( $rOpts->{'iterations'} ) ) { + if ( $rOpts->{'iterations'} <= 0 ) { $rOpts->{'iterations'} = 1 } + elsif ( $rOpts->{'iterations'} > 5 ) { $rOpts->{'iterations'} = 5 } + } + else { + $rOpts->{'iterations'} = 1; + } + # see if user set a non-negative logfile-gap if ( defined( $rOpts->{'logfile-gap'} ) && $rOpts->{'logfile-gap'} >= 0 ) { @@ -2132,6 +2255,26 @@ EOM } } +sub find_file_upwards { + my ( $search_dir, $search_file ) = @_; + + $search_dir =~ s{/+$}{}; + $search_file =~ s{^/+}{}; + + while (1) { + my $try_path = "$search_dir/$search_file"; + if ( -f $try_path ) { + return $try_path; + } + elsif ( $search_dir eq '/' ) { + return undef; + } + else { + $search_dir = dirname($search_dir); + } + } +} + sub expand_command_abbreviations { # go through @ARGV and expand any abbreviations @@ -2816,7 +2959,7 @@ sub show_version { print <<"EOM"; This is perltidy, v$VERSION -Copyright 2000-2009, Steve Hancock +Copyright 2000-2010, Steve Hancock Perltidy is free software and may be copied under the terms of the GNU General Public License, which is included in the distribution files. @@ -6011,6 +6154,12 @@ sub write_line { my $line_type = $line_of_tokens->{_line_type}; my $input_line = $line_of_tokens->{_line_text}; + if ( $rOpts->{notidy} ) { + write_unindented_line($input_line); + $last_line_type = $line_type; + return; + } + # _line_type codes are: # SYSTEM - system-specific code before hash-bang line # CODE - line of perl code (including comments) @@ -7844,6 +7993,21 @@ sub set_white_space_flag { } else { $tightness = $tightness{$last_token} } + #================================================================= + # Patch for fabrice_bug.pl + # We must always avoid spaces around a bare word beginning with ^ as in: + # my $before = ${^PREMATCH}; + # Because all of the following cause an error in perl: + # my $before = ${ ^PREMATCH }; + # my $before = ${ ^PREMATCH}; + # my $before = ${^PREMATCH }; + # So if brace tightness flag is -bt=0 we must temporarily reset to bt=1. + # Note that here we must set tightness=1 and not 2 so that the closing space + # is also avoided (via the $j_tight_closing_paren flag in coding) + if ( $type eq 'w' && $token =~ /^\^/ ) { $tightness = 1 } + + #================================================================= + if ( $tightness <= 0 ) { $ws = WS_YES; } @@ -7967,7 +8131,7 @@ sub set_white_space_flag { # 'w' and 'i' checks for something like: # myfun( &myfun( ->myfun( # ----------------------------------------------------- - elsif (( $last_type =~ /^[wU]$/ ) + elsif (( $last_type =~ /^[wUG]$/ ) || ( $last_type =~ /^[wi]$/ && $last_token =~ /^(\&|->)/ ) ) { $ws = WS_NO unless ($rOpts_space_function_paren); @@ -8921,10 +9085,12 @@ sub set_white_space_flag { # that this is a block and not an anonomyous # hash (blktype.t, blktype1.t) && ( $block_type !~ /^[\{\};]$/ ) - + # patch: and do not add semi-colons for recently # added block types (see tmp/semicolon.t) - && ( $block_type !~ /^(switch|case|given|when|default)$/) + && ( $block_type !~ + /^(switch|case|given|when|default)$/ ) + # it seems best not to add semicolons in these # special block types: sort|map|grep && ( !$is_sort_map_grep{$block_type} ) @@ -20885,6 +21051,7 @@ sub new { starting_level => undef, indent_columns => 4, tabs => 0, + entab_leading_space => undef, look_for_hash_bang => 0, trim_qw => 1, look_for_autoloader => 1, @@ -20938,6 +21105,7 @@ sub new { _starting_level => $args{starting_level}, _know_starting_level => defined( $args{starting_level} ), _tabs => $args{tabs}, + _entab_leading_space => $args{entab_leading_space}, _indent_columns => $args{indent_columns}, _look_for_hash_bang => $args{look_for_hash_bang}, _trim_qw => $args{trim_qw}, @@ -21622,6 +21790,7 @@ sub find_starting_indentation_level { my $i = 0; my $structural_indentation_level = -1; # flag for find_indentation_level + # keep looking at lines until we find a hash bang or piece of code my $msg = ""; while ( $line = $tokenizer_self->{_line_buffer_object}->peek_ahead( $i++ ) ) @@ -21632,8 +21801,8 @@ sub find_starting_indentation_level { $starting_level = 0; last; } - next if ( $line =~ /^\s*#/ ); # must not be comment - next if ( $line =~ /^\s*$/ ); # must not be blank + next if ( $line =~ /^\s*#/ ); # skip past comments + next if ( $line =~ /^\s*$/ ); # skip past blank lines ( $starting_level, $msg ) = find_indentation_level( $line, $structural_indentation_level ); if ($msg) { write_logfile_entry("$msg") } @@ -21689,7 +21858,17 @@ sub find_indentation_level { $know_input_tabstr = 0; - if ( $tokenizer_self->{_tabs} ) { + # When -et=n is used for the output formatting, we will assume that + # tabs in the input formatting were also produced with -et=n. This may + # not be true, but it is the best guess because it will keep leading + # whitespace unchanged on repeated formatting on small pieces of code + # when -et=n is used. Thanks to Sam Kington for this patch. + if ( my $tabsize = $tokenizer_self->{_entab_leading_space} ) { + $leading_whitespace =~ s{^ (\t*) } + { " " x (length($1) * $tabsize) }xe; + $input_tabstr = " " x $tokenizer_self->{_indent_columns}; + } + elsif ( $tokenizer_self->{_tabs} ) { $input_tabstr = "\t"; if ( length($leading_whitespace) > 0 ) { if ( $leading_whitespace !~ /\t/ ) { @@ -28245,6 +28424,8 @@ Perl::Tidy - Parses and beautifies perl source formatter => $formatter, # callback object (see below) dump_options => $dump_options, dump_options_type => $dump_options_type, + prefilter => $prefilter_coderef, + postfilter => $postfilter_coderef, ); =head1 DESCRIPTION @@ -28362,6 +28543,23 @@ If the B parameter is given, it must be the reference to a hash. This hash will receive all abbreviations used by Perl::Tidy. See the demo program F for example usage. +=item prefilter + +A code reference that will be applied to the source before tidying. It is +expected to take the full content as a string in its input, and output the +transformed content. + +=item postfilter + +A code reference that will be applied to the tidied result before outputting. +It is expected to take the full content as a string in its input, and output +the transformed content. + +Note: A convenient way to check the function of your custom prefilter and +postfilter code is to use the --notidy option, first with just the prefilter +and then with both the prefilter and postfilter. See also the file +B in the perltidy distribution. + =back =head1 EXAMPLE @@ -28537,7 +28735,7 @@ to perltidy. =head1 VERSION -This man page documents Perl::Tidy version 20090616. +This man page documents Perl::Tidy version 20101217. =head1 AUTHOR