use v6.d;
unit module ScanDir;
class End {};
sub scan-dir(*@paths --> Supply) is export {
my $s = supply {
my %watched-dirs;
CATCH { when X::IO { }; default { warn $_ } }
sub start-watching(IO::Path $dir) {
return unless $dir ~~ :e;
return if %watched-dirs{$dir.Str};
%watched-dirs{$dir.Str} = True;
whenever $dir.watch {
my $path-io = .path.IO;
emit $path-io;
when $path-io ~~ :e & :d {
add-dir($path-io) unless %watched-dirs{$path-io.Str};
}
when $path-io ~~ :!e {
%watched-dirs{$path-io.Str}:delete
}
}
}
sub add-dir(*@todo) {
while @todo {
my $next = @todo.shift;
next unless $next ~~ :e & :r & :d;
start-watching($next);
for $next.dir {
emit $_;
when .e && .d {
@todo.push($_);
start-watching($_);
}
}
}
}
add-dir(@paths».IO);
emit End;
};
return $s.unique(
with => sub { $^a !~~ End && $^b !~~ End && $^a eq $^b },
expires => 0.1,
);
}