Skip to content

Instantly share code, notes, and snippets.

@bduggan 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

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 Author

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

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
You can’t perform that action at this time.