#!/usr/bin/env perl

=encoding utf8

=head1 NAME

ppll

=cut

use autodie;
use strict;
use utf8::all;
use v5.20;
use warnings;

use FindBin;

use lib "$FindBin::Bin/../lib";

require App::ppll;

exit App::ppll->new->call;

=head1 SYNOPSIS

    ppll [OPTIONS] COMMAND [ARGS]
    ppll [OPTIONS] -c COMMAND [PARAMETERS]
    ppll --help
    ppll --version

=head1 DESCRIPTION

=head2 PARAMETERS AND JOBS

‘Parameters’ is what makes C<ppll> run. In one way or another C<ppll> is
given a number of parameters, and it will create and run one ‘job’ for each
parameter.

If no parameter-related option is used C<ppll> will read the parameters from
STDIN. Ordinarily, each line read becomes one parameter, but there are options
to control this.

The other important input to C<ppll> is the ‘command’. The command-line
arguments after all options make up the command and its arguments.

Each job will execute the command. All occurrences of C<{}> in any part of the
command (and its arguments) will be replaced with the job’s parameter. If there
are no such occurrences the parameter will be appended as an additional
argument.

For example:

    ppll echo {} <<EOF
    cow
    pig
    sheep
    EOF

Will create jobs that execute C<echo cow>, C<echo pig> and so on. An other way
to do the same thing would be:

    ppll echo <<EOF
    cow
    pig
    sheep
    EOF

C<{}> becomes useful when it’s not supposed to be the last argument, e.g:

    ppll cp {} farm/ <<EOF
    cow
    pig
    sheep
    EOF

Or when it’s supposed to be just a part of an argument, or show up more than
once, e.g:

    ppll curl -o photo-of-a-{}.jpg http://example.com/img/{}.jpg <<EOF
    cow
    pig
    sheep
    EOF

The above would run
C<curl -o photo-of-a-cow.jpg http://example.com/img/cow.jpg>, etc.

=head3 JOB CONTROL

The default is to run several such jobs in parallel. Once a job is finished
another one is started, until there are no more jobs to run.

The number of jobs run at the same time is controlled by the B<--jobs> option.
The default is one per CPU (but not necessarily one on each CPU).

If a job fails (exits with a code other than 0), no more jobs will be started.
C<ppll> I<attempts to> stop other running jobs.

The B<--force> option tells C<ppll> to not care about failed jobs and always
keep starting new ones. Any failed jobs are still noted and will still affect
C<ppll>’s own exit code.

=head3 SERIAL LINES, PARALLEL FIELDS

This feature deserves its own section.

It can be used to parallelise heavy tasks, while also making sure certain tasks
are run in a particular order.

Each line of input will create a ‘group’ of parameters, that will be run before
the next group starts. Each line is split up into individual parameters (using
the C<IFS> environment variable), that will be run at the same time.

An example:

    ppll --slpf wake-up.sh <<EOF
    rooster
    hens chickens
    cows pigs sheep
    cat
    EOF

The above would run C<wake-up.sh> first for C<rooster>. I<Then> it would run it
for C<hens> and C<chickens>, at the same time, but after the C<rooster> job has
completed. Then C<cows>, C<pigs> and C<sheep> in parallel, and so on.

=head1 OPTIONS

=head2 GENERAL

=over

=item B<--help>

=item B<-h>

=item B<-?>

Print (this) help and exit.

=item B<--version>

=item B<-V>

Print B<ppll>’s version and exit.

=back

=head2 PARAMETERS AND JOBS

=over

=item B<--command> I<COMMAND>

=item B<-C> I<COMMAND>

Run I<COMMAND> as a shell command with each parameter passed as an argument.
This allows for shell constructs, such as piping, redirecting, etc.

If used then the rest of the command-line arguments are used as parameters,
instead of a command.

More or less the same as:

    ppll $SHELL -c <COMMAND> -

(C<$SHELL> defaults to C</bin/sh>.)

=item B<--delimiter> I<DELIMITER>

=item B<-d> I<DELIMITER>

Use I<DELIMITER>, as a regex,  to split lines into fields. Implies B<--fields>.

=item B<--empty>

Include empty parameters. These are otherwise discarded.

=item B<--fields>

=item B<-f>

Alias for C<--mode fields>.

=item B<--force>

=item B<-k>

Keep starting new jobs even if a job has failed.

=item B<--jobs> I<N>

=item B<-j> I<N>

Run (up to) this many jobs in parallel.

=item B<--lines>

=item B<-l>

Alias for C<--mode lines>.

=item B<--mode> I<MODE>

How input should be turned into parameters. I<MODE> is one of:

=over

=item C<auto> (default)

If there’s only one line of input, behave as if C<fields>, otherwise as if
C<lines>.

=item C<fields>

Split lines into fields and use each field as a parameter.
Splitting is done using a delimiter set with B<--delimiter>, or the C<IFS>
environment variable.

=item C<lines>

Use each line as a parameter.

=item C<slpf>

Split each line into parameters. All parameters from a single line will be run
in parallel, but lines will be run serially.

=back

See also: B<--fields>, B<--lines>, B<--serial-lines-parallel-fields>

=item B<--random>

=item B<-R>

Shuffle the parameters.

=item B<--replace-string> I<STRING>

=item B<-replstr> I<STRING>

=item B<-I=s> I<STRING>

Use I<STRING> instead of C<{}> as a placeholder for the parameter.

=item B<--reverse>

=item B<-r>

Use the parameters in reverse order.

=item B<--sequence> I<SPEC>

=item B<-s> I<SPEC>

Use I<SPEC> as parameters.

I<SPEC> is in one of the forms:

=over

=item C<N..M>

Parameters are from I<N> to I<M>, inclusive.

=item C<M>

Parameters are from 1 to I<M>, inclusive.

=back

=item B<--serial-lines-parallel-fields>

=item B<-slpf>

Alias for C<--mode slpf>.

=back

=head2 OUTPUT

=over

=item B<--colour>

=item B<--color>

=item B<--no-colour>

=item B<--no-color>

Turn on or off ANSI colours in the output.

The default is to enable colours if STDOUT is a TTY.

=item B<--markers>

=item B<--no-markers>

Prefix (the default), or don’t prefix, jobs’ STDOUT and STDERR output with
C<E<gt>> or C<≫>, respectively.

=item B<--quiet>

=item B<-q>

Print less. Can be repeated for less and less.

=item B<--summary>

=item B<-S>

=item B<--no-summary>

Print (the default if there’s more than one parameter), or don’t print, a
summary of how many jobs ran and which of them failed.

=item B<--timestamp-format> I<FORMAT>

Format timestamps using I<FORMAT>. See L<DateTime::strftime|DateTime::strftime>.

The default is C<%T.%3N>.

Implies B<--timestamps>.

=item B<--timestamps>

=item B<-t>

Prefix lines from jobs’ output with a timestamp. The time printed will be the
I<approximate> time the line was printed by the job.

=item B<--verbose>

=item B<-v>

Print more. Can be repeated for more and more.

=back

=head1 DIAGNOSTICS

=head1 CONFIGURATION AND ENVIRONMENT

C<ppll> uses some environment variables in some cases:

=over

=item C<COLUMNS>

If set then used when printing things across the whole width of the terminal. If
not set then C<ppll> will try to work out the terminal width in other ways,
falling back to 80.

=item C<IFS>

Used for splitting lines into fields, e.g. with C<--fields> or
C<--serial-lines-parallel-fields>.

=item C<SHELL>

Used with C<--commmand> (C<-c>).

=back

=head1 DEPENDENCIES

=head1 INCOMPATIBILITIES

=head1 BUGS AND LIMITATIONS

=head1 AUTHOR

=head1 LICENSE AND COPYRIGHT

=cut
