a10c5b90947986615b328e90c735918eca1ccbd2
[gitmo/MooseX-Runnable.git] / lib / MooseX / Runnable / Invocation / Plugin / Restart / Auto.pm
1 package MooseX::Runnable::Invocation::Plugin::Restart::Auto;
2 use Moose::Role;
3 use MooseX::Types;
4 use MooseX::Types::Moose qw(ArrayRef RegexpRef Any Str);
5 use MooseX::Types::Path::Class qw(Dir);
6 use File::ChangeNotify;
7
8 # coerce ArrayRef[Dir], from ArrayRef[Any], via {[
9 #     map { warn $_; Path::Class::dir($_) } @$_,
10 # ]};
11
12 coerce RegexpRef, from Str, via { qr/$_/i };
13
14 use namespace::autoclean;
15
16 with 'MooseX::Runnable::Invocation::Plugin::Restart::Base';
17
18 has 'watch_regexp' => (
19     is       => 'ro',
20     isa      => RegexpRef,
21     required => 1,
22     coerce   => 1,
23     default  => sub { qr/^[^.].+[.]pmc?$/i },
24 );
25
26 has 'watch_directories' => (
27     is       => 'ro',
28     isa      => ArrayRef[Dir],
29     required => 1,
30     coerce   => 1,
31     default  => sub { [Path::Class::dir('.')] },
32 );
33
34 has 'watcher' => (
35     is         => 'ro',
36     isa        => 'File::ChangeNotify::Watcher',
37     lazy_build => 1,
38 );
39
40 sub _build_initargs_from_cmdline {
41     my ($self, @args) = @_;
42
43     my $regexp;
44     my @dirs;
45     my $next_type;
46     for my $arg (@args){
47         # if($arg eq '--inc'){
48         #     push @dirs, @INC;
49         # }
50         if($arg eq '--dir'){
51             $next_type = 'dir';
52         }
53         elsif($arg eq '--regexp' || $arg eq '--regex'){
54             # i call them regexps, other people call them "regexen" :P
55             $next_type = 'regexp';
56         }
57         elsif($next_type eq 'dir'){
58             push @dirs, $arg;
59         }
60         elsif($next_type eq 'regexp'){
61             $regexp = $arg;
62         }
63         else {
64             confess 'Invalid args passed to Restart::Auto';
65         }
66     }
67     my %result;
68     $result{watch_directories} = [map { Path::Class::dir($_) } @dirs] if @dirs;
69     $result{watch_regexp} = $regexp if $regexp;
70     return \%result;
71 }
72
73 sub _build_watcher {
74     my $self = shift;
75     my $w = File::ChangeNotify->instantiate_watcher(
76         directories => [map { $_->stringify } @{$self->watch_directories}],
77         filter      => $self->watch_regexp,
78     );
79
80     return $w;
81 }
82
83 sub run_parent_loop {
84     my $self = shift;
85     while(1){
86         my @events = $self->watcher->wait_for_events();
87         $self->restart;
88         sleep .5; # "debounce" the notifier
89     }
90 }
91
92 1;