package File::CodeSearch::Files;
# Created on: 2009-08-11 06:20:53
# Create by: Ivan Wills
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$
use Moose;
use warnings;
use version;
use Readonly;
use Data::Dumper;
use Carp;
use English qw{ -no_match_vars };
use Config::General;
our $VERSION = version->new('0.6.0');
our %warned_once;
has ignore => (
is => 'rw',
isa => 'ArrayRef[Str]',
default => sub{[qw{ ignore }]},
);
has include => (
is => 'rw',
isa => 'ArrayRef[Str]',
);
has exclude => (
is => 'rw',
isa => 'ArrayRef[Str]',
);
has include_type => (
is => 'rw',
isa => 'ArrayRef[Str]',
default => sub{[]},
);
has exclude_type => (
is => 'rw',
isa => 'ArrayRef[Str]',
default => sub{[]},
);
has symlinks => (
is => 'rw',
isa => 'Bool',
default => 0,
);
has links => (
is => 'rw',
isa => 'HashRef',
default => sub {{}},
);
has type_suffixes => (
is => 'rw',
isa => 'HashRef',
default => sub {{
ignore => {
definite => [qw{ }],
possible => [qw{ }],
other_types => [qw{ build backups vcs images logs editors min }],
none => 0,
},
editors => {
definite => [qw{ ~\d*$ }],
possible => [qw{ }],
other_types => [qw{ vim }],
none => 0,
},
vim => {
definite => [qw{ (^|/)[.][^/]+[.]sw[ponx]$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
images => {
definite => [qw{ [.]png$ [.]jpe?g$ [.]gif$ [.]swf$ [.]ttf$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
logs => {
definite => [qw{ logs?(?:$|/) }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
backups => {
definite => [qw{ [.]orig$ [.]copy$ ~\d*$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
vcs => {
definite => [qw{ [.]git [.]bzr [.]svn CVS RCS }, ',v$' ],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
build => {
definite => [qw{
[_.]build
blib
(MY)?META[.](yml|json)
LICENCE
Changes
Build$
Makefile$
MANIFEST([.]SKIP)?
README
packages/[^/]/[.]build
Debian_CPANTS.txt
[.]class$
target/
cover_db
}],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
perl => {
definite => [qw{ [.]pl$ [.]pm$ [.]pod$ [.]PL$ }],
possible => [qw{ [.]t$ [.]cgi$ }],
other_types => [qw{ }],
none => 1,
bang => 'perl',
},
php => {
definite => [qw{ [.]php$ }],
possible => [qw{ [.]lib$ [.]pkg$ [.]t$ }],
other_types => [qw{ }],
none => 0,
},
c => {
definite => [qw{ [.]c$ [.]cpp$ [.]c[+][+]$ [.]h$ [.]hpp$ [.]hxx$ [.]h[+][+]$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
html => {
definite => [qw{ [.]html$ [.]xhtml$ }],
possible => [qw{ [.]xml$ }],
other_types => [qw{ }],
none => 0,
},
test => {
definite => [qw{ \/tx?\/[.]t$ test[.]pl$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
svg => {
definite => [qw{ svg }],
none => 0,
},
sql => {
definite => [qw{ [.]sql$ [.]plsql$ }],
none => 0,
},
css => {
definite => [qw{ [.]css$ }],
other_types => [qw{ scss less }],
none => 0,
},
scss => {
definite => [qw{ [.]scss$ }],
other_types => [qw{ }],
none => 0,
},
less => {
definite => [qw{ [.]less$ }],
other_types => [qw{ }],
none => 0,
},
javascript => {
definite => [qw{ [.]js$ }],
none => 0,
},
js => {
other_types => [qw{ javascript }],
none => 0,
},
json => {
definite => [qw{ [.]ja?son$ }],
none => 0,
},
xml => {
definite => [qw{ xml$ [.]xsd$ [.]xslt$ [.]dtd }],
possible => [qw{ }],
other_types => [qw{ svg }],
none => 0,
},
web => {
possible => [qw{ xml }],
other_types => [qw{ html svg css js }],
none => 0,
},
scripting => {
other_types => [qw{ perl php python ruby javascript }],
none => 0,
},
programing => {
definite => [qw{ }],
possible => [qw{ }],
other_types => [qw{ scripting c }],
none => 0,
},
package => {
definite => [qw{ [.]PL$ MANIFEST$ MANIFEST.SKIP$ META.yml$ MYMETA.yml$ README$ Changes$ Debian_CPANTS.txt$ Makefile$ LICENSE$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
config => {
definite => [qw{ }],
possible => [qw{ rc$ tab$ [.]cfg$ [.]conf$ [.]config$ }],
other_types => [qw{ yaml }],
none => 0,
},
binary => {
definite => [qw{ [.]jpe?g$ [.]png$ [.]gif$ [.]bmp$ [.]swf$ [.]psd$ [.]exe$ }],
possible => [qw{ }],
other_types => [qw{ }],
none => 0,
},
python => {
definite => [qw{ [.]py$ }],
none => 0,
},
yaml => {
definite => [qw{ [.]ya?ml$ }],
none => 0,
},
shell => {
definite => [qw{ [.](?:ba|k|z)sh\d?$ }],
none => 0,
},
ruby => {
definite => [qw{ [.]rb$ }],
none => 0,
},
groovy => {
definite => [qw{ [.]groovy$ }],
none => 0,
},
java => {
definite => [qw{ [.]java$ }],
none => 0,
},
min => {
definite => [qw{ [.]min[.](?:css|js)$ }],
none => 0,
},
jsp => {
definite => [qw{ [.]jps$ }],
none => 0,
},
ftl => {
definite => [qw{ [.]ftl$ }],
none => 0,
},
jt => {
other_types => [qw{ jsp ftl }],
none => 0,
},
}},
);
sub BUILD {
my ($self) = @_;
$ENV{HOME} ||= $ENV{USERPROFILE};
my $conf_file = "$ENV{HOME}/.csrc";
return if !-r $conf_file;
my $conf = Config::General->new($conf_file);
my %conf = $conf->getall();
$conf{file_types} ||= {};
for my $file_type ( keys %{ $conf{file_types} } ) {
$self->type_suffixes->{$file_type} ||= {};
for my $setting ( keys %{ $conf{file_types}{$file_type} } ) {
if ( $setting =~ s/^[+]//xms ) {
push @{ $self->type_suffixes->{$file_type}{$setting} }
, ref $conf{file_types}{$file_type}{$setting} eq 'ARRAY'
? @{ $conf{file_types}{$file_type}{$setting} }
: $conf{file_types}{$file_type}{$setting};
}
else {
$self->type_suffixes->{$file_type}{$setting}
= ref $conf{file_types}{$file_type}{$setting} eq 'ARRAY'
? $conf{file_types}{$file_type}{$setting}
: [ $conf{file_types}{$file_type}{$setting} ];
}
}
}
}
sub file_ok {
my ($self, $file) = @_;
for my $ignore (@{ $self->ignore }) {
return 0 if $self->types_match($file, $ignore);
}
return 1 if -d $file;
my $possible = 0;
my $matched = 0;
if ( @{ $self->include_type }) {
for my $type (@{ $self->include_type }) {
my $match = $self->types_match($file, $type);
$possible-- if $match == 2;
$matched += $match;
}
return 0 if $matched <= 0;
}
if (!$matched) {
for my $type (@{ $self->exclude_type }) {
my $match = $self->types_match($file, $type);
return 0 if $match && $match != 2;
$possible++ if $match == 2;
}
return 0 if $possible > 0;
}
if ($self->include) {
my $matches = 0;
for my $include (@{ $self->include }) {
$matches ||= $file =~ /$include/;
last if $matches;
}
return 0 if !$matches;
}
if ($self->exclude) {
for my $exclude (@{ $self->exclude }) {
return 0 if $file =~ /$exclude/;
}
}
return 1;
}
sub types_match {
my ($self, $file, $type) = @_;
my $types = $self->type_suffixes;
warn "No type $type" if !exists $types->{$type} && !$warned_once{$type}++;
return 0 if !exists $types->{$type};
for my $suffix ( @{ $types->{$type}{definite} } ) {
return 3 if $file =~ /$suffix/;
}
for my $suffix ( @{ $types->{$type}{possible} } ) {
return 2 if $file =~ /$suffix/;
}
if ( $types->{$type}{bang} ) {
if ( open my $fh, '<', $file ) {
my $line = <$fh>;
close $fh;
return 3 if $line && $line =~ /$types->{$type}{bang}/;
}
}
return 1 if $types->{$type}{none} && $file !~ m{ [^/] [.] [^/]+ $}xms;
for my $other ( @{ $types->{$type}{other_types} } ) {
my $match = $self->types_match($file, $other);
return $match if $match;
}
return 0;
}
1;
__END__
=head1 NAME
File::CodeSearch::Files - Handles the testing file types, symlinks and file name positive & negative matching.
=head1 VERSION
This documentation refers to File::CodeSearch::Files version 0.6.0.
=head1 SYNOPSIS
use File::CodeSearch::Files;
# Brief but working code example(s) here showing the most common usage(s)
# This section will be as far as many users bother reading, so make it as
# educational and exemplary as possible.
=head1 DESCRIPTION
=head1 SUBROUTINES/METHODS
=head2 C<BUILD>
Applies any configuration details found in the ~/.csrc file
=head2 C<file_ok ($file)>
Determines weather B<$file> should be searched
=head2 C<types_match ($file, $type)>
Checks that the file $file is of type $type and returns true if it is false
otherwise
=head1 DIAGNOSTICS
=head1 CONFIGURATION AND ENVIRONMENT
=head1 DEPENDENCIES
=head1 INCOMPATIBILITIES
=head1 BUGS AND LIMITATIONS
There are no known bugs in this module.
Please report problems to Ivan Wills (ivan.wills@gmail.com).
Patches are welcome.
=head1 AUTHOR
Ivan Wills - (ivan.wills@gmail.com)
=head1 LICENSE AND COPYRIGHT
Copyright (c) 2009 Ivan Wills (14 Mullion Close, Hornsby Heights, NSW Australia 2077).
All rights reserved.
This module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself. See L<perlartistic>. This program is
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
=cut