File::Corresponding - Find corresponding files in the directory tree


File-Corresponding documentation Contained in the File-Corresponding distribution.

Index


Code Index:

NAME

Top

File::Corresponding - Find corresponding files in the directory tree

PREAMBLE

Top

In a source tree it is common to have files with the same name, but in different places in the directory tree. A typical MVC application could look something like this:

 Book       lib/Controller/Book.pm
 Borrower   lib/Controller/Borrower.pm
 Book       lib/Model/Schema/Book.pm
 Borrower   lib/Model/Schema/Borrower.pm
 Book       lib/root/templates/Book.t
 Borrower   lib/root/templates/Borrower.t
 Book       lib/t/controller-book.t
 Borrower   lib/t/controller-borrower.t
 Book       lib/t/model-schema-book.t
 Borrower   lib/t/model-schema-borrower.t

Here we clearly have two types of things; a Book and a Borrower.

The Controller/Book.pm, Model/Schema/Book.pm, root/templates/Book.t, t/controller-book.t, and t/model-schema-book.t represent different aspects of the same Book entity; they correspond to each other.

Since the files belong to each other it is useful for the programmer to easily navigate between them.

This module helps with that.

SYNOPSIS

Top

Config file

Given a config file .corresponding_file in the current directory or your $HOME directory:

  ---
  file_groups:
    -
      name: All MyApp classes
      file_profiles:
        -
          name: Cat Controller
          regex: / Controller . (\w+) \.pm $ /x
          sprintf: Controller/%s.pm
        -
          name: DBIC Schema
          regex: "|Model/Schema.(\w+)\.pm$|"
          sprintf: Model/Schema/%s.pm
        -
          name: Template
          regex: /root.template.(\w+)\.pm$/
          sprintf: root/template/%s.pm




From the command line

  $ corresponding_file Controller/Book.pm
  Model/Schema/Book.pm
  $ cd ..
  $ corresponding_file lib/Controller/Book.pm
  lib/Model/Schema/Book.pm




From your editor

Emacs

Devel::PerlySense has a feature "Go to Project's Other Files" for navigating to related files.

Actually, it doesn't yet. But it will.

From your program

By using File::Corresponding as a library, you can use the resulting File::Corresponding::File::Found objects to display more information than just the file name.

DESCRIPTION

Top

File::Corresponding uses a configuration of groups of File Profiles to identify corresponding files.

Using a .corresponding_file config file, and the command line script corresponding_file, you can easily look up corresponding files.

It's obviously better if you let your editor do the tedious bits for you, like passing the file name to the script, letting you choose which of the corresponding files you meant, and opening the file in the editor.

That's left as an exercise for the reader (well you are a programmer, aren't you?).

THE CONFIG FORMAT

Top

Study the SYNOPSIS example.

A File Profile for e.g. "Controller" files includes a regex to match a Controller file name with e.g. "Book" in it, and a sprintf string template to render any found files with "Book" in them as a Controller file.

Regex definitions are whatever comes after "qr" in e.g. qr/file.pm/i, i.e. "/file.pm/i". As you can see, you can use regex modifiers, and even use other delimiters (which is handy, since you're likely to match "/").

The regex should match the intended file. The first capturing parenthesis must contain the entity file fragmen that is common to all files in the group.

The sprintf string should contain a %s to fill in the captured file fragment from any other File Profile in the Group.

Only existing files are reported.

SEE ALSO

Top

AUTHOR

Top

Johan Lindström, <johanl[ÄT]DarSerMan.com>

BUGS AND CAVEATS

Top

BUG REPORTS

Please report any bugs or feature requests to bug-file-corresponding@rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=File-Corresponding. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

CAVEATS

Currently File::Corresponding supports the simple case in the SYNOPSIS above, where the Controller/Book.pm can easily be translated to Model/Schema/Book.pm. It does not yet support the more complicated translation from Controller/Book.pm to t/controller-book.t and back.

KNOWN BUGS

COPYRIGHT & LICENSE

Top

*** DEVELOPER API DOCS ***

Top

ERROR HANDLING MODEL

Top

Failures will result in a die.

ATTRIBUTES

Top

profile_groups : ArrayRef[File::Corresponding::Group]

Group config objects.

METHODS

Top

corresponding($file) : ArrayRef[File::Corresponding::File::Found]

Find files corresponding to $file (given the config in ->profile_groups) and return found @files.

If the same file is found via many Groups, it will be reported once per group (so if you only use this to display the file name, make sure to unique the file names).

load_config_file($config_file) : 1

Load yaml $config_file, or die with an error message.


File-Corresponding documentation Contained in the File-Corresponding distribution.
package File::Corresponding;
use Moose;
our $VERSION = 0.003;



use Moose::Autobox;
use YAML::Tiny;
use Data::Dumper;

use File::Corresponding::Group;


has profile_groups => (
    is => "rw",
    isa => "ArrayRef[File::Corresponding::Group]",
    default => sub { [] },
);



sub corresponding {
    my $self = shift;
    my ($file) = @_;

    my $found_files = $self->profile_groups ->map(sub { $_->corresponding($file)->flatten });

    return $found_files;
}



sub load_config_file {
    my $self = shift;
    my ($file) = @_;

    my $yaml = YAML::Tiny->read($file)
            or die("Could not read config file ($file):\n" . YAML::Tiny->errstr);
    my $config = $yaml->[0];

    my $die = sub {
        my $element = shift;
        die("Missing element '$element' in config file ($file)\n" . Dumper($config));
    };

    my $file_groups = $config->{file_groups} or $die->("file_groups");

    $self->profile_groups(
        $file_groups->map( sub {
            my $group = $_;
            my $name = $group->{name} || "";
            
            my $file_profiles = $group->{file_profiles} or $die->("file_profiles");
            my $profiles = $file_profiles->map( sub {
                File::Corresponding::File::Profile->new($_),
            });

            File::Corresponding::Group->new({
                name          => $name,
                file_profiles => $profiles,
            });
        }),
    );
    

    #print Dumper($config); use Data::Dumper;



    return 1;
}



1;



__END__