#!/usr/bin/perl -CA

eval 'exec /usr/bin/perl -CA -S $0 ${1+"$@"}'
    if 0; # not running under some shell

use strict;
use Getopt::Long;
use Pod::Usage;
use App::HI;
use List::Util;
use Getopt::Long qw(:config bundling);

my %o; my %ol = (
    "help|h"             => "this help",
    "trunc|t=i"          => "truncate the line to this many characters",
    "nixnics|noex|x"     => "don't use the nicknames from Term::ANSIColorx::Colornicknames",
    "command|c=s"        => "fork and exe this command and pipe it through hi; for SHELL = hi in Makefiles",
    "file|f=s@"          => "read regex/color pairs from file(s)",
    "supress-cmd-say"    => "don't print the command after forking",
    "list|list-colors|l" => "list (many of) the known colors",
);

$o{trunc} = $ENV{TRUNCATE} if exists $ENV{TRUNCATE};
$o{nixnics} = $ENV{NO_EXTRA} if exists $ENV{NO_EXTRA};

if( not GetOptions(\%o, keys %ol) or $o{help} ) {
    my $ml = List::Util::max(map {length} keys %ol);
    print sprintf('%*s  %s', $ml, $_, $ol{$_}), "\n" for sort keys %ol;
    exit 0;
}

if( $o{command} ) {
    close STDIN;
    open STDIN, "-|", "$o{command}" or die "couldn't open command \"$o{command}\"";
    print "«$o{command}»\n" unless $o{'supress-cmd-say'};
}

binmode STDIN,  ":utf8";
binmode STDOUT,  ":utf8";
binmode STDERR,  ":utf8";

our $VERSION = '2.7193';

if( $o{file} ) {
    for my $file (@{$o{file}}) {
        my $array;
        unless( $array = do $file ) {
            die "$file: $@" if $@;
            die "$file: could not load: $!";
        }
        die "$file: invalid syntax" unless ref $array eq "ARRAY";
        unshift @ARGV, @{$array};
    }
}

my $app_invocation = $o{list} ? "list_colors" : "fire_filter";

App::HI->$app_invocation(%o);

=head1 NAME

hi - highlight things in a stream of output

=head1 SYNOPSIS

  hi [options] [regex color [regex color [regex color [...]]]]
      --list-colors --list -l: list the available colors and exit
      --nixnics --noex -x:     do not use the extended color nicknames
      --trunc -t:              truncate lines to this width (argument required)
      --help -h:               this help
      --command -c:            fork and execute this command and pipe it through hi
      --file -f:               read regex/color pairs from file(s)

=head1 EXAMPLES

Intended as a pipe colorizer

  ps auxfw | hi jettero sky root red ^nobody orange

  sudo tail -f /var/log/vsftpd.log | hi CONNECT.* umber OK.UPLOAD.* lime

  getent passwd | hi -f username -f shell '\d+' pink

=head1 FILE

Regex and color pairs may be supplied not only via parameters, but also using
one or several external files (see L<EXAMPLES>).  Each file should contain a
valid Perl code returns ARRAYref.  The contents of it will be prepended to
the ARGV AS-IS, see below.

  [
      jettero             => 'sky',
      root                => 'red',
      '(?<=:)/[^:]+(?=:)' => 'lime',
  ],

=head1 limited Makefile support

  SHELL = hi interesting.*thing umber
  default:

Although, the output probably isn't quite what you'd expect.  Make prints the
commands before it forks the subshell.  So whatever C<hi> prints instead
already has all the make substitutions completed.  C<ls $(something)> turns
into C<ls /whatever/something/was>.  Worse, C<-c> gets passed whatever the
Makefile executes, not just commands it would have (or did) print.

It's probably not usable like this without some clever make tricks.

=head1 REPORTING BUGS

You can report bugs either via rt.cpan.org or via the issue tracking system on
github.  I'm likely to notice either fairly quickly.

=head1 AUTHOR

Paul Miller C<< <jettero@cpan.org> >>

=head1 COPYRIGHT

Copyright 2014 Paul Miller -- released under the GPL

=head1 SEE ALSO

perl(1), L<Term::ANSIColor>, L<Term::ANSIColorx::AutoFilterFH>, L<Term::ANSIColorx::ColorNicknames>
