Instantly share code, notes, and snippets.

@bduggan /tailgrep.p6
Last active Sep 11, 2018

Embed
What would you like to do?
#!/usr/bin/env perl6
use JSON::Fast;
use Terminal::ANSIColor;
my @frames = < / - | - \ - >;
sub spinner {
@frames[$++ % +@frames];
}
sub download-spinners {
my $store = "~/.spinners.json";
unless $store.IO.e {
say "downloading spinners";
my $url='https://raw.githubusercontent.com'
~ '/sindresorhus/cli-spinners'
~ '/HEAD/spinners.json';
shell "curl -s $url > $store";
}
from-json( $store.IO.slurp );
}
multi MAIN(
Bool :$list-spinners!, #= list spinners
) {
say download-spinners.keys.sort.join("\t");
}
multi MAIN(
$expr, #= what to search for
$filename where *.IO.e, #= a filename to grep
Numeric :$wait = 2, #= when to notify
:$spinner is copy, #= which spinner
) {
my $spinners = download-spinners;
$spinner = $spinners.keys.pick unless $spinner;
@frames = $spinners{ $spinner }<frames><>;
exit MAIN(:list-spinners) unless @frames;
shell 'tput civis';
my $proc = Proc::Async.new(<<tail -f "$filename">>);
my $out = $proc.stdout;
my $last-seen = DateTime.now;
start react {
whenever $out.lines.grep( / "$expr" / ) {
.say
}
whenever $out.lines {
print " " ~ spinner() ~ "\r";
$last-seen = DateTime.now;
}
whenever Supply.interval(1) {
if DateTime.now - $last-seen > $wait {
say color('red')
~ "--$wait seconds, no lines--"
~ color('reset');
}
}
whenever signal(SIGINT) {
shell 'tput cnorm';
exit;
}
}
await $proc.start;
}
@AlexDaniel

This comment has been minimized.

Copy link

AlexDaniel commented Sep 4, 2018

my $proc = Proc::Async.new(<<tail -f $filename>>);

↑ That will not work with filenames that have spaces in them. I recommend:

my $proc = Proc::Async.new(<tail -f -->, $filename);

Same goes for the shelling out (shell "curl -s $url > $store";):

my $store-fh = $store.IO.open: :w;
run :out($store-fh), <curl -s -->, $url;
# maybe close $store-fh here
@bduggan

This comment has been minimized.

Copy link
Owner

bduggan commented Sep 9, 2018

↑ That will not work with filenames that have spaces in them. I recommend:

Good point -- I changed it to <<tail -f "$filename">>.

Same goes for the shelling out (shell "curl -s $url > $store";):

I've addressed this one by using ~ instead of %*ENV<HOME>, so now it is guaranteed that neither $url nor $store have a space.

@b2gills

This comment has been minimized.

Copy link

b2gills commented Sep 11, 2018

You can put the $proc.start in a whenever in the react block, so that you don't need start react

react {
    ...
        
    whenever $proc.start {
        done
    }
}

I would just use now instead of DateTime.now, as it is a lighter weight object.

You probably want .IO.f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment