#!/usr/bin/perl

#######################################################################
#      $URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/Perl-Critic/bin/perlcritic $
#     $Date: 2006-05-29 17:26:56 -0700 (Mon, 29 May 2006) $
#   $Author: chrisdolan $
# $Revision: 438 $
########################################################################

package main;

use strict;
use warnings;
use Pod::Usage;
use File::Spec;
use Getopt::Long;
use List::Util qw(first);
use English qw(-no_match_vars);
use Perl::Critic::Utils;

our $VERSION = 0.17;
$VERSION = eval $VERSION;  ## no critic

#----------------------------------------------------------------------------
# Globals

my @files = ();
my %FORMAT_OF = (
    1 => "%f:%l:%c:%m\n",
    2 => "%f: (%l:%c) %m\n",
    3 => "%m at line %l, column %c.  %e.  (Severity: %s)\n",
    4 => "%f: %m at line %l, column %c.  %e.  (Severity: %s)\n",
    5 => "%m at line %l, near '%r'.  (Severity: %s)\n",
    6 => "%f: %m at line %l near '%r'.  (Severity: %s)\n",
    7 => "[%p] %m at line %l, column %c.  (Severity: %s)\n",
    8 => "[%p] %m at line %l, near '%r'.  (Severity: %s)\n",
    9 => "%m at line %l, column %c.\n  %p (Severity: %s)\n%d\n",
   10 => "%m at line %l, near '%r'.\n  %p (Severity: %s)\n%d\n",
);

#-----------------------------------------------------------------------------
# Begin script.  Only execute if not in a test harness

if ( !$ENV{HARNESS_ACTIVE} ) {
    my %options    = get_options();
    @files         = get_input(@ARGV);
    my $violations = critique(\%options, @files);
    my $status     = defined $violations ? ( $violations ? 2 : 0 ) : 1;
    exit $status;
}

#-----------------------------------------------------------------------------
# Begin subroutines

sub get_options {

    my %opts = _parse_command_line();
    _dispatch_special_requests( %opts );
    _validate_options( %opts );

    # Convert severity shortcut options.  If multiple shortcuts
    # are given, the lowest one wins.  If an explicit -severity
    # option has been given, then the shortcuts are ignored.
    $opts{severity} ||=  first { exists $opts{$_} } (1 .. 5);


    # If -top is specified, default the severity level to 1, unless an
    # explicit severity is defined.  This provides us flexibility to
    # report top-offenders across just some or all of the severity levels.
    # We also default the -top count to twenty if non is given
    if ( exists $opts{top} ) {
        $opts{severity} ||= 1;
        $opts{top} ||= 20;
    }

    #Override profile, if -noprofile is specified
    if ( exists $opts{noprofile} ) {
        $opts{profile} = q{};
    }

    # I've adopted the convention of using key-value pairs for
    # arguments to most functions.  And to increase legibility,
    # I have also adopted the familiar command-line practice
    # of denoting argument names with a leading dash (-).
    my %dashed_opts = map { ( "-$_" => $opts{$_} ) } keys %opts;
    return %dashed_opts;
}

#-----------------------------------------------------------------------------

sub _parse_command_line {

    my %opts      = ();
    my @opt_specs = qw(severity=i profile=s noprofile verbose=s force list
        help|? man Version Safari top:i 5 4 3 2 1 include=s@ exclude=s@);

    Getopt::Long::Configure('no_ignore_case');
    GetOptions( \%opts, @opt_specs ) || pod2usage();           #Exits

    return %opts;
}

#-----------------------------------------------------------------------------

sub _dispatch_special_requests {
    my (%opts) = @_;
    if ( $opts{help}    ) { pod2usage( -verbose => 0 )      }  #Exits
    if ( $opts{man}     ) { pod2usage( -verbose => 2 )      }  #Exits
    if ( $opts{Version} ) { print "$VERSION\n"; exit 0;     }  #Exits
    if ( $opts{list}    ) { print policy_listing(); exit 0; }  #Exits

    return 1;
}

#-----------------------------------------------------------------------------

sub _validate_options {
    my (%opts) = @_;
    my $msg = q{};


    if ( $opts{noprofile} && $opts{profile} ) {
        $msg .= qq{Warning: Can't use -noprofile with -profile option.\n};
    }

    if ( $opts{verbose} && $opts{verbose} !~ m{(?: \d+ | %[mflcedrps] )}mx){
        $msg .= qq{Warning: -verbose arg '$opts{verbose}' looks odd.  };
        $msg .= qq{Perhaps you meant to say '-verbose 3 $opts{verbose}'\n};
    }

    if ( exists $opts{top} && $opts{top} < 0 ) {
        $msg .= qq{Warning: -top argument '$opts{top}' is negative.  };
        $msg .= qq{Perhaps you meant to say '$opts{top} -top'.\n};
    }

    if (exists $opts{severity} && ($opts{severity}<1 || $opts{severity}>5)){
        $msg .= qq{Warning: -severity arg '$opts{severity}' out of range.  };
        $msg .= qq{Severities range from '1' (lowest) to '5' (highest).\n};
    }


    if ( $msg ) {
        pod2usage( -exitstatus => 1, -message => $msg, -verbose => 0); #Exits
    }


    return 1;
}

#-----------------------------------------------------------------------------

sub get_input {

    if (@_) {

        # Test to make sure all the specified files or directories
        # actually exist.  If any one of them is bogus, then die.
        if ( my $nonexistant = first { ! -e $_ } @_ ) {
            my $msg = qq{No such file or directory: '$nonexistant'};
            pod2usage( -exitstatus => 1, -message => $msg, -verbose => 0);
        }

        # Reading code from files or dirs.  If argument is a file,
        # then we process it as-is (even though it may not actually
        # be Perl code).  If argument is a directory, recursively
        # search the directory for files that look like Perl code.
        return map { -d $_ ? all_perl_files($_) : $_ } @_;
    }
    else {

        # Reading code from STDIN.  All the code is slurped into
        # a string.  PPI will barf if the string is just whitespace.
        my $code_string = do { local $RS = undef; <STDIN> };
        $code_string =~ m{ \S+ }mx || die qq{Nothing to critique.\n};
        return \$code_string;    #Convert to SCALAR ref for PPI
    }
}

#------------------------------------------------------------------------------

sub critique {

    my ( $opts, @files ) = @_;
    @files || die "No perl files were found.\n";

    # Perl::Critic has lots of dependencies, so loading is delayed
    # until it is really needed.  This hack reduces startup time for
    # doing other things like getting the version number or dumping
    # the man page. Arguably, those things are pretty rare, but hey,
    # why not save a few seconds if you can.

    require Perl::Critic;
    my $critic = Perl::Critic->new( %{$opts} );
    my $count  = undef;


    eval {

        for my $file (@files) {
            my @violations = $critic->critique($file);
            render_report( $file, $opts, @violations );
            $count += scalar @violations;
        }
    };


    warn qq{$EVAL_ERROR} if $EVAL_ERROR;
    return $count;
}

#------------------------------------------------------------------------------

sub render_report {

    my ( $file, $opts_ref, @violations ) = @_;


    if( ! @violations ){
        print "$file source OK\n";
        return;
    }


    $file = -f $file ? $file : 'stdin';
    my $default_verbosity = @files > 1 ? 4 : 3;  #@files is global!
    my $fmt = _get_format( $opts_ref->{-verbose} || $default_verbosity );
    $fmt =~ s{ \%f }{$file}mxg;  #HACK! Violation objects don't know the file
    Perl::Critic::Violation::set_format( $fmt );

    print @violations;
    return scalar @violations;
}

#-----------------------------------------------------------------------------

sub _get_format {
    my ( $verbosity ) = @_;
    my $is_integer = $verbosity =~ m{ \A [+-]? \d+ \z }mx;
    return $is_integer ? $FORMAT_OF{abs $verbosity} : _interpolate($verbosity);
}


#-----------------------------------------------------------------------------

sub _interpolate {
    my ( $literal ) = @_;
    return eval "\"$literal\"";  ## no critic 'StringyEval';
}

#-----------------------------------------------------------------------------


sub policy_listing {

    my $namespace = shift;
    my @listing = ();

    # Again, this require/import hack is just to delay loading of
    # Perl::Critic until we absolutely have to.

    require Perl::Critic::Config;
    Perl::Critic::Config->import( -namespace => $namespace );
    my $config = Perl::Critic::Config->new(-severity => 1);
    my @policies = sort {ref $a cmp ref $b}  @{ $config->policies() };

    # Append header
    my $format = '%-60.60s %1s %1s';
    my $header = sprintf $format, qw(PolicyName D U);
    my $h_rule = q{-} x length $header;
    push @listing, "$header\n", "$h_rule\n";

    # Append body
    for my $policy ( @policies ) {
        my $name = ref $policy;
        $name =~ s{\A Perl::Critic::Policy::}{}mxg;
        my $def_sev  = $policy->default_severity();
        my $user_sev = $policy->get_severity();
        my $line = sprintf $format, $name, $def_sev, $user_sev;
        push @listing, "$line\n";
    }

    # Append footer
    push @listing, "$h_rule\n";
    push @listing, "D = Default severity\n";
    push @listing, "U = User-defined severity\n";

    return @listing;
}

1;

__END__

#-----------------------------------------------------------------------------

=pod

=for stopwords DGR INI-style vim-fu minibuffer -noprofile

=head1 NAME

C<perlcritic> - Command-line interface to critique Perl source

=head1 SYNOPSIS

  perlcritic [ -12345 | -severity number ] [ -noprofile | -profile file ]
             [ -top [ number ]] [ -include pattern ] [ -exclude pattern ]
             [ -verbose number | format ] [ -force ] [ -Version ]
             [ -list ] [ -help ] [ -man ]   [ FILE | DIRECTORY ]

=head1 DESCRIPTION

C<perlcritic> is a Perl source code analyzer.  It is the executable
front-end to the L<Perl::Critic> engine, which attempts to identify
awkward, hard to read, error-prone, or unconventional constructs in
your code.  Most of the rules are based on Damian Conway's book B<Perl
Best Practices>.  However, C<perlcritic> is B<not> limited to
enforcing PBP, and it will even support rules that contradict Conway.
All rules can easily be configured or disabled to your liking.

If you want to integrate C<perlcritic> with your build process, the
L<Test::Perl::Critic> module provides a nice interface that is
suitable for test scripts.  For ultimate convenience (at the expense
of some flexibility) see the L<criticism> pragma.

Win32 and ActivePerl users can find PPM distributions of Perl::Critic
at L<http://theoryx5.uwinnipeg.ca/ppms/>.

=head1 USAGE EXAMPLES

Before getting into all the gory details, here are some basic usage
examples to help get you started.

  #Report only most severe violations (severity = 5)
  perlcritic YourModule.pm

  #Same as above, but read input from STDIN
  perlcritic

  #Recursively process all Perl files beneath directory
  perlcritic /some/directory

  #Report slightly less severe violations too (severity >= 4)
  perlcritic -4 YourModule.pm

  #Report all violations, regardless of severity (severity >= 1)
  perlcritic -1 YourModule.pm

  #Report top 20 most severe violations (severity >= 1)
  perlcritic -top YourModule.pm

  #Report top 20 violations with severity >= 3
  perlcritic -3 -top YourModule.pm

  #Report additional violations of Policies that match m/variables/ix
  perlcritic -include variables YourModule.pm

=head1 ARGUMENTS

The arguments are paths to the files you wish to analyze.  You may
specify multiple files.  If an argument is a directory, C<perlcritic>
will analyze all Perl files below the directory.  If no arguments
are specified, then input is read from STDIN.

=head1 OPTIONS

Option names can be abbreviated to uniqueness and can be stated with
singe or double dashes, and option values can be separated from the
option name by a space or '=' (as with L<Getopt::Long>).  Option names
are also case-sensitive.

=over 8

=item -profile FILE

Directs C<perlcritic> to use a profile named by FILE rather than looking
for the default F<.perlcriticrc> file in the current directory or your
home directory.  See L<"CONFIGURATION"> for more information.

=item -noprofile

Directs C<perlcritic> not to load any configuration file, thus reverting
to the default configuration for all Policies.

=item -severity N

Directs C<perlcritic> to only report violations of Policies with a
severity greater than C<N>.  Severity values are integers ranging from
1 (least severe) to 5 (most severe).  The default is 5.  For a given
C<-profile>, decreasing the C<-severity> will usually produce more
violations.  Users can redefine the C<severity> for any Policy in
their F<.perlcriticrc> file.  See L<"CONFIGURATION"> for more
information.

=item -5 | -4 | -3 | -2 | -1

These are shortcuts for setting the C<-severity> option.  For example
C<"-4"> is equivalent to C<"-severity 4">.  If multiple shortcuts are
specified, then the lowest one wins.  If an explicit C<-severity>
option is given, then all shortcut options are silently ignored.  NOTE:
Be careful not to put one of the severity shortcut options immediately
after the C<-top> flag or C<perlcritic> will interpret it as the
number of violations to report.

=item -top [ N ]

Directs C<perlcritic> to report only the top C<N> Policy violations in
each file, ranked by their severity.  If C<N> is not specified, it
defaults to 20.  If the C<-severity> option (or one of the shortcuts)
is not explicitly given, the C<-top> option implies that the minimum
severity level is 1. Users can redefine the severity for any Policy in
their F<.perlcriticrc> file.  See L<"CONFIGURATION"> for more
information.  NOTE: Be careful not to put one of the severity shortcut
options immediately after the C<-top> flag or C<perlcritic> will
interpret it as the number of violations to report.

=item -include PATTERN

Directs C<perlcritic> to report additional violations of all Policy
modules that match the regex C</PATTERN/imx>.  Use this option to
temporarily override your profile and/or the severity settings at the
command-line.  For example:

  perlcritic --include=layout my_file.pl

This would cause C<perlcritic> to report violations of all the
C<CodeLayout::*> policies even if they have a severity level that is
less than the default level of 5, or have been disabled in your
F<.perlcriticrc> file.  You can specify multiple C<-include> options
and you can use it in conjunction with the C<-exclude> option.  Note
that C<-exclude> takes precedence over C<-include> when a Policy
matches both patterns.

=item -exclude PATTERN

Directs C<perlcritic> to not report violations of any Policy modules
that match the regex C</PATTERN/imx>.  Use this option to temporarily
override your profile and/or the severity settings at the
command-line.  For example:

  perlcritic --exclude=strict my_file.pl

This would cause C<perlcritic> to not report violations of the
C<RequireUseStrict> and C<ProhibitNoStrict> policies even though they
have the highest severity level.  You can specify multiple C<-exclude>
options and you can use it in conjunction with the C<-include> option.
Note that C<-exclude> takes precedence over C<-include> when a Policy
matches both patterns.

=item -force

Directs C<perlcritic> to ignore the magical C<## no critic>
pseudo-pragmas in the source code. See L<"BENDING THE RULES"> for more
information.

=item -verbose N | FORMAT

Sets the verbosity level or format for reporting violations.  If given
a number (C<N>), C<perlcritic> reports violations using one of the
predefined formats described below.  If given a string (C<FORMAT>), it
is interpreted to be an actual format specification.  If the
C<-verbose> option is not specified, it defaults to either 3 or 4,
depending on whether multiple files were given as arguments to
C<perlcritic>.

  Verbosity     Format Specification
  -----------   --------------------------------------------------------------------
   1            "%f:%l:%c:%m\n",
   2            "%f: (%l:%c) %m\n",
   3            "%m at line %l, column %c.  %e.  (Severity: %s)\n",
   4            "%f: %m at line %l, column %c.  %e.  (Severity: %s)\n",
   5            "%m at line %l, near '%r'.  (Severity: %s)\n",
   6            "%f: %m at line %l near '%r'.  (Severity: %s)\n",
   7            "[%p] %m at line %l, column %c.  (Severity: %s)\n",
   8            "[%p] %m at line %l, near '%r'.  (Severity: %s)\n",
   9            "%m at line %l, column %c.\n  %p (Severity: %s)\n%d\n",
  10            "%m at line %l, near '%r'.\n  %p (Severity: %s)\n%d\n"

Formats are a combination of literal and escape characters similar to
the way C<sprintf> works.  See L<String::Format> for a full
explanation of the formatting capabilities.  Valid escape characters
are:

  Escape    Meaning
  -------   ------------------------------------------------------------------------
  %m        Brief description of the violation
  %f        Name of the file where the violation occurred.
  %l        Line number where the violation occurred
  %c        Column number where the violation occurred
  %e        Explanation of violation or page numbers in PBP
  %d        Full diagnostic discussion of the violation
  %r        The string of source code that caused the violation
  %P        Name of the Policy module that created the violation
  %p        Name of the Policy without the Perl::Critic::Policy:: prefix
  %s        The severity level of the violation

The purpose of these formats is to provide some compatibility with
editors that have an interface for parsing certain kinds of input. See
L<"EDITOR INTEGRATION"> for more information about that.

=item -list

Displays a listing of all the L<Perl::Critic::Policy> modules that are
found on this machine.  For each Policy, the default severity and
user-defined severity is also shown.  If the user has not overridden
the severity for a particular Policy in their F<.perlcriticrc> file,
then the user-defined severity will be the same as the default
severity.  This can be useful for discovering the Policy modules that
you have available and tuning the severity levels in your
F<.perlcriticrc> file.

=item -Safari

Report "Perl Best Practice" citations as section numbers from
L<http://safari.oreilly.com> instead of page numbers from the actual
book.  NOTE: This feature is not implemented yet.

=item -help

=item -?

Displays a brief summary of options and exits.

=item -man

Displays the complete C<perlcritic> manual and exits.

=item -Version

=item -V

Displays the version number of C<perlcritic> and exits.

=back

=head1 CONFIGURATION

The default configuration file is called F<.perlcriticrc>.
Perl::Critic::Config will look for this file in the current directory
first, and then in your home directory.  Alternatively, you can set
the C<PERLCRITIC> environment variable to explicitly point to a
different file in another location.  If none of these files exist, and
the C<-profile> option is not given on the command line, then all
Policies will be loaded with their default configuration.

The format of the configuration file is an series of INI-style
sections that contain key-value pairs separated by '='. Comments
should start with '#' and can be placed on a separate line or after
the name-value pairs if you desire.  The general recipe is a series of
blocks like this:

    [Perl::Critic::Policy::Category::PolicyName]
    severity = 1
    arg1 = value1
    arg2 = value2

C<Perl::Critic::Policy::Category::PolicyName> is the full name of a
module that implements the policy.  The Policy modules distributed
with Perl::Critic have been grouped into categories according to the
table of contents in Damian Conway's book B<Perl Best Practices>. For
brevity, you can omit the C<'Perl::Critic::Policy'> part of the
module name.

C<severity> is the level of importance you wish to assign to the
Policy.  All Policy modules are defined with a default severity value
ranging from 1 (least severe) to 5 (most severe).  However, you may
disagree with the default severity and choose to give it a higher or
lower severity, based on your own coding philosophy.

The remaining key-value pairs are configuration parameters that will
be passed into the constructor of that Policy.  The constructors for
most Policy modules do not support arguments, and those that do should
have reasonable defaults.  See the documentation on the appropriate
Policy module for more details.

Instead of redefining the severity for a given Policy, you can
completely disable a Policy by prepending a '-' to the name of the
module in your configuration file.  In this manner, the Policy will
never be loaded, regardless of the C<-severity> given on the
command line.

A simple configuration might look like this:

    #--------------------------------------------------------------
    # I think these are really important, so always load them

    [TestingAndDebugging::RequireUseStrict]
    severity = 5

    [TestingAndDebugging::RequireUseWarnings]
    severity = 5

    #--------------------------------------------------------------
    # I think these are less important, so only load when asked

    [Variables::ProhibitPackageVars]
    severity = 2

    [ControlStructures::ProhibitPostfixControls]
    allow = if unless  #My custom configuration
    severity = 2

    #--------------------------------------------------------------
    # I do not agree with these at all, so never load them

    [-NamingConventions::ProhibitMixedCaseVars]
    [-NamingConventions::ProhibitMixedCaseSubs]

    #--------------------------------------------------------------
    # For all other Policies, I accept the default severity,
    # so no additional configuration is required for them.

A few sample configuration files are included in this distribution
under the F<t/samples> directory. The F<perlcriticrc.none> file
demonstrates how to disable Policy modules.  The
F<perlcriticrc.levels> file demonstrates how to redefine the severity
level for any given Policy module.  The F<perlcriticrc.pbp> file
configures Perl::Critic to load only Policies described in Damian
Conway's book "Perl Best Practices."

=head1 THE POLICIES

A large number of Policy modules are distributed with Perl::Critic.
They are described briefly in the companion document
L<Perl::Critic::PolicySummary> and in more detail in the individual
modules themselves.

=head1 BENDING THE RULES

Perl::Critic takes a hard-line approach to your code: either you
comply or you don't.  In the real world, it is not always practical
(or even possible) to fully comply with coding standards.  In such
cases, it is wise to show that you are knowingly violating the
standards and that you have a Damn Good Reason (DGR) for doing so.

To help with those situations, you can direct Perl::Critic to ignore
certain lines or blocks of code by using pseudo-pragmas:

    require 'LegacyLibaray1.pl';  ## no critic
    require 'LegacyLibrary2.pl';  ## no critic

    for my $element (@list) {

        ## no critic

        $foo = "";               #Violates 'ProhibitEmptyQuotes'
        $barf = bar() if $foo;   #Violates 'ProhibitPostfixControls'
        #Some more evil code...

        ## use critic

        #Some good code...
        do_something($_);
    }

The C<"## no critic"> comments direct Perl::Critic to ignore the
remaining lines of code until the end of the current block, or until a
C<"## use critic"> comment is found (whichever comes first).  If the
C<"## no critic"> comment is on the same line as a code statement,
then only that line of code is overlooked.  To direct perlcritic to
ignore the C<"## no critic"> comments, use the C<-force> option.

A bare C<"## no critic"> comment disables all the active Policies.  If
you wish to disable only specific Policies, add a list of Policy names
as arguments just as you would for the C<"no strict"> or C<"no
warnings"> pragma.  For example, this would disable the
C<ProhibitEmptyQuotes> and C<ProhibitPostfixControls> policies until
the end of the block or until the next C<"## use critic"> comment
(whichever comes first):

  ## no critic (EmptyQuotes, PostfixControls);

  $foo = "";                  #Now exempt from ValuesAndExpressions::ProhibitEmptyQuotes
  $barf = bar() if $foo;      #Now exempt ControlStructures::ProhibitPostfixControls
  $long_int = 10000000000;    #Still subjected to ValuesAndExpression::RequireNumberSeparators

Since the Policy names are matched against the arguments as regular
expressions, you can abbreviate the Policy names or disable an entire
family of Policies in one shot like this:

  ## no critic 'NamingConventions';

  my $camelHumpVar = 'foo';  #Now exempt from NamingConventions::ProhibitMixedCaseVars
  sub camelHumpSub {}        #Now exempt from NamingConventions::ProhibitMixedCaseSubs

The argument list must be enclosed in parens and must contain one or
more comma-separated barewords (i.e. don't use quotes).  The <"## no
critic"> pragmas can be nested, and Policies named by an inner pragma
will be disabled along with those already disabled an outer pragma.

Use this feature wisely.  C<"## no critic"> should be used in the
smallest possible scope, or only on individual lines of code. And you
should always be as specific as possible about which policies you want
to disable (i.e. never use a bare C<"## no critic">).  If Perl::Critic
complains about your code, try and find a compliant solution before
resorting to this feature.

=head1 IMPORTANT CHANGES

Perl-Critic is evolving rapidly.  As such, some of the interfaces have
changed in ways that are not backward-compatible.  If you have been
using an older version of Perl-Critic and/or you have been developing
custom Policy modules, please read this section carefully.

=head2 VERSION 0.16

Starting in version 0.16, you can add a list Policy names as arguments
to the C<"## no critic"> pseudo-pragma.  This feature allows you to
disable specific policies.  So if you have been in the habit of adding
additional words after C<"no critic">, then those words might cause
unexpected results.  If you want to append other stuff to the C<"## no
critic"> comment, then terminate the pseudo-pragma with a semi-colon,
and then start another comment.  For example:

  #This may not work as expected.
  $email = 'foo@bar.com';  ## no critic for literal '@'

  #This will work.
  $email = 'foo@bar.com';  ## no critic; #for literal '@'

  #This is even better.
  $email = 'foo@bar.com'; ## no critic (RequireInterpolation);

=head2 VERSION 0.14

Starting in version 0.14, the interface to L<Perl::Critic::Violation>
changed.  This will also break any custom Policy modules that you
might have written for earlier modules.  See L<DEVELOPER.pod> for an
up-to-date guide on creating Policy modules.

The notion of "priority" was also replaced with "severity" in version
0.14.  Consequently, the default behavior of Perl::Critic is to only
load the most "severe" Policy modules, rather than loading all of
them.  This decision was based on user-feedback suggesting that
Perl-Critic should be less "critical" for new users, and should steer
them toward gradually increasing the strictness as they adopt better
coding practices.


=head2 VERSION 0.11

Starting in version 0.11, the internal mechanics of Perl-Critic were
rewritten so that only one traversal of the PPI document tree is
required.  Unfortunately, this will break any custom Policy modules
that you might have written for earlier versions.  Converting your
policies to work with the new version is pretty easy and actually
results in cleaner code.  See L<DEVELOPER.pod> for an up-to-date guide
on creating Policy modules.

=head1 EDITOR INTEGRATION

For ease-of-use, C<perlcritic> can be integrated with your favorite text
editor.  The output-formatting capabilities of C<perlcritic> are
specifically intended for use with the "grep" or "compile" modes
available in editors like C<emacs> and C<vim>.  In these modes, you can
run an arbitrary command and the editor will parse the output into an
interactive buffer that you can click on and jump to the relevant line
of code.

=head2 EMACS

Entering C<'Meta-x compile'> causes emacs to switch to compile-mode.
Next, enter the following command in the minibuffer:

  perlcritic -verbose 1 path/to/your/file

When the results are displayed, pressing [Enter] on any of the
Violation messages will move the pointer to the relevant location
within the file.  Type C<'Ctrl-h a compile'> for information about
compile-mode.

=head2 VIM

Configure the grep format as follows:

  set grepformat=%f:%l:%c:m
  set grepprg=perlcritic\ -verbose\ 1\ %

Then, you can run perlcritic on the current buffer with:

  :grep

Navigation and display instructions can be found under C<:help grep>.
Someone with stronger Vim-fu may wish to convert this to a real macro.

=head2 gVIM

Fritz Mehner recently added support for C<perlcritic> to his fantastic
gVIM plugin.  In addition to providing a very Perlish IDE, Fritz's
plugin enables one-click access to C<perlcritic> and many other very
useful utilities.  And all is seamlessly integrated into the
editor. See L<http://lug.fh-swf.de/vim/vim-perl/screenshots-en.html>
for complete details.

=head1 EXIT STATUS

If C<perlcritic> has any errors itself, exits with status == 1.  If there
are no errors, but C<perlcritic> finds Policy violations in your source
code, exits with status == 2.  If there were no errors and no
violations were found, exits with status == 0.

=head1 THE L<Perl::Critic> PHILOSOPHY

  Coding standards are deeply personal and highly subjective.  The
  goal of Perl::Critic is to help you write code that conforms with a
  set of best practices.  Our primary goal is not to dictate what
  those practices are, but rather, to implement the practices
  discovered by others.  Ultimately, you make the rules --
  Perl::Critic is merely a tool for encouraging consistency.  If there
  is a policy that you think is important or that we have overlooked,
  we would be very grateful for contributions, or you can simply load
  your own private set of policies into Perl::Critic.

=head1 EXTENDING THE CRITIC

The modular design of Perl::Critic is intended to facilitate the
addition of new Policies.  You'll need to have some understanding of
L<PPI>, but most Policy modules are pretty straightforward and only
require about 20 lines of code.  Please see the
L<Perl::Critic::DEVELOPER> file included in this distribution for a
step-by-step demonstration of how to create new Policy modules.

If you develop any new Policy modules, feel free to send them to
<thaljef@cpan.org> and I'll be happy to put them into the Perl::Critic
distribution.  Or if you'd like to work on the Perl::Critic project
directly, check out our repository at L<http://perlcritic.tigris.org>.
To subscribe to our mailing list, send a message to
C<dev-subscribe@perlcritic.tigris.org>.

=head1 BUGS

Scrutinizing Perl code is hard for humans, let alone machines.  If you
find any bugs, particularly false-positives or false-negatives from a
Perl::Critic::Policy, please submit them to
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Critic>.  Thanks.

=head1 CREDITS

Adam Kennedy - For creating L<PPI>, the heart and soul of L<Perl::Critic>.

Damian Conway - For writing B<Perl Best Practices>, finally :)

Chris Dolan - For contributing the best features and Policy modules.

Giuseppe Maxia - For all the great ideas and positive encouragement.

and Sharon, my wife - For putting up with my all-night code sessions.

=head1 AUTHOR

Jeffrey Ryan Thalhammer <thaljef@cpan.org>

=head1 COPYRIGHT

Copyright (c) 2005-2006 Jeffrey Ryan Thalhammer.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.  The full text of this license
can be found in the LICENSE file included with this module.

=cut
