Skip to content

Instantly share code, notes, and snippets.

@wolverian
Created December 22, 2010 18:10
Show Gist options
  • Save wolverian/751856 to your computer and use it in GitHub Desktop.
Save wolverian/751856 to your computer and use it in GitHub Desktop.
Perl directory/file change watcher and command runner for OS X
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
package App::watch;
use Moose;
use File::ChangeNotify;
use Path::Class qw(dir file);
with 'MooseX::Getopt';
has verbose => (
is => 'rw',
isa => 'Bool',
default => 0
);
has filter => (
is => 'rw',
isa => 'Str',
);
has command => (
is => 'rw',
isa => 'Str',
required => 1
);
sub run {
my ($self) = @_;
my $watcher = File::ChangeNotify->instantiate_watcher(
directories => $self->extra_argv,
($self->filter ? (filter => qr/\.clj$/) : ())
);
my @children;
my $pid;
while (my @events = $watcher->wait_for_events) {
$self->info("Got " . @events . " events");
$self->info("Killing children @children");
kill TERM => $_ for @children;
@children = ();
for my $event (@events) {
$self->info("Got event for '" . $event->path . "' of type '" . $event->type . "'");
if ($pid = fork) {
push @children, $pid;
$self->info("Forked '$pid'");
# Parent process continues loop
} else {
$self->run_command_for_event($event)
}
}
}
}
sub run_command_for_event {
my ($self, $event) = @_;
my $command = $self->command;
my $path = $event->path;
$path = -f $path ? file($path) : dir($path);
for ($command) {
s/%path/$path/g;
s/%abs_path/$path->absolute/ge;
}
$self->info("Running command '$command' in child $$");
system($command) == 0
or die "Execution of '$command' failed: $?\n";
$self->info("Exiting child $$");
}
sub info {
my ($self, $message) = @_;
warn "$message\n" if $self->verbose;
}
package main;
App::watch->new_with_options->run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment