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