Mojo::Home - Detect And Access The Project Root Directory In Mojo


Mojolicious documentation Contained in the Mojolicious distribution.

Index


Code Index:

NAME

Top

Mojo::Home - Detect And Access The Project Root Directory In Mojo

SYNOPSIS

Top

  use Mojo::Home;

  my $home = Mojo::Home->new;
  $home->detect;

DESCRIPTION

Top

Mojo::Home is a container for home directories.

ATTRIBUTES

Top

Mojo::Home implements the following attributes.

app_class

  my $class = $home->app_class;
  $home     = $home->app_class('Foo::Bar');

Application class.

METHODS

Top

Mojo::Home inherits all methods from Mojo::Base and implements the following new ones.

detect

  $home = $home->detect;
  $home = $home->detect('My::App');

Detect home directory from application class.

lib_dir

  my $path = $home->lib_dir;

Path to lib directory.

list_files

  my $files = $home->list_files;
  my $files = $home->list_files('foo/bar');

List all files in directory and subdirectories recursively.

parse

  $home = $home->parse('/foo/bar');

Parse path.

rel_dir

  my $path = $home->rel_dir('foo/bar');

Generate absolute path for relative directory.

rel_file

  my $path = $home->rel_file('foo/bar.html');

Generate absolute path for relative file.

to_string

  my $string = $home->to_string;
  my $string = "$home";

Home directory.

SEE ALSO

Top

Mojolicious, Mojolicious::Guides, http://mojolicio.us.


Mojolicious documentation Contained in the Mojolicious distribution.

package Mojo::Home;
use Mojo::Base -base;
use overload
  'bool'   => sub {1},
  '""'     => sub { shift->to_string },
  fallback => 1;

use Cwd 'abs_path';
use File::Spec;
use FindBin;
use Mojo::Command;
use Mojo::Loader;

has app_class => 'Mojo::HelloWorld';

# "I'm normally not a praying man, but if you're up there,
#  please save me Superman."
sub detect {
  my ($self, $class) = @_;

  # Class
  $self->app_class($class) if $class;
  $class ||= $self->app_class;

  # Environment variable
  if ($ENV{MOJO_HOME}) {
    my @parts = File::Spec->splitdir(abs_path $ENV{MOJO_HOME});
    $self->{_parts} = \@parts;
    return $self;
  }

  # Try to find home from lib directory
  if ($class) {

    # Load
    my $file = Mojo::Command->class_to_path($class);
    unless ($INC{$file}) {
      if (my $e = Mojo::Loader->load($class)) { die $e if ref $e }
    }

    # Detect
    if (my $path = $INC{$file}) {

      # Directory
      $path =~ s/$file$//;
      my @home = File::Spec->splitdir($path);

      # Remove "lib" and "blib"
      while (@home) {
        last unless $home[-1] =~ /^b?lib$/ || $home[-1] eq '';
        pop @home;
      }

      # Turn into absolute path
      $self->{_parts} =
        [File::Spec->splitdir(abs_path(File::Spec->catdir(@home) || '.'))];
    }
  }

  # FindBin fallback
  $self->{_parts} = [split /\//, $FindBin::Bin] unless $self->{_parts};

  $self;
}

sub lib_dir {
  my $self = shift;

  # Directory found
  my $parts = $self->{_parts} || [];
  my $path = File::Spec->catdir(@$parts, 'lib');
  return $path if -d $path;

  # No lib directory
  undef;
}

sub list_files {
  my ($self, $dir) = @_;

  # Build portable directory
  my $parts = $self->{_parts} || [];
  my $root = File::Spec->catdir(@$parts);
  $dir = File::Spec->catdir($root, split '/', ($dir || ''));

  # Read directory
  my (@files, @dirs);
  opendir DIR, $dir or return [];
  for my $file (readdir DIR) {

    # Hidden file
    next if $file =~ /^\./;

    # File
    my $path = File::Spec->catfile($dir, $file);
    my $rel = File::Spec->abs2rel($path, $root);
    if (-f $path) {
      push @files, join '/', File::Spec->splitdir($rel);
    }

    # Directory
    elsif (-d $path) { push @dirs, join('/', File::Spec->splitdir($rel)) }
  }
  closedir DIR;

  # Walk directories
  for my $path (@dirs) {
    my $new = $self->list_files($path);
    push @files, @$new;
  }

  [sort @files];
}

# "And now to create an unstoppable army of between one million and two
#  million zombies!"
sub parse {
  my ($self, $path) = @_;
  my @parts = File::Spec->splitdir($path);
  $self->{_parts} = \@parts;
  $self;
}

sub rel_dir {
  my $self = shift;
  my $parts = $self->{_parts} || [];
  File::Spec->catdir(@$parts, split '/', shift);
}

sub rel_file {
  my $self = shift;
  my $parts = $self->{_parts} || [];
  File::Spec->catfile(@$parts, split '/', shift);
}

sub to_string {
  my $self = shift;
  my $parts = $self->{_parts} || [];
  File::Spec->catdir(@$parts);
}

1;
__END__