The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

IPC::PrettyPipe - manage human readable external command execution pipelines

VERSION

version 0.13

SYNOPSIS

  use IPC::PrettyPipe;

  my $pipe = IPC::PrettyPipe->new;

  $pipe->add( $command, %options );
  $pipe->add( cmd => $command, %options );

  $pipe->stream( $stream_op, $stream_file );

  $cmd = $pipe->add( $command );
  $cmd->add( $args );

  print $pipe->render, "\n";

DESCRIPTION

Connecting a series of programs via pipes is a time honored tradition. When it comes to displaying them for debug or informational purposes, simple dumps may suffice for simple pipelines, but when the number of programs and arguments grows large, it can become difficult to understand the overall structure of the pipeline.

IPC::PrettyPipe provides a mechanism to construct and output readable external command execution pipelines. It does this by treating commands, their options, and the options' values as separate entities so that it can produce nicely formatted output.

It is designed to be used in conjunction with other modules which actually execute pipelines, such as IPC::Run.

This module (and its siblings IPC::PrettyPipe::Cmd, IPC::PrettyPipe::Arg, and IPC::PrettyPipe::Stream) present the object-oriented interface for manipulating the underlying infrastructure.

For a simpler, more intuitive means of constructing pipelines, see IPC::PrettyPipe::DSL.

Pipeline Rendering (Pretty Printing)

IPC::PrettyPipe doesn't render a pipeline directly; instead it passes that job on to another object (which must consume the IPC::PrettyPipe::Renderer role).

By default IPC::PrettyPipe provides a renderer which uses Template::Tiny to render a pipeline as if it were to be fed to a POSIX shell (which can be handy for debugging complex pipelines).

The same renderer may be fed a different template to use, or it may be replaced via the "renderer" attribute.

Pipeline Execution

Just as with rendering, IPC::PrettyPipe doesn't execute a pipeline on its own. Instead it calls upon another object (which must consume the IPC::PrettyPipe::Executor role). By default it provides an executor which uses IPC::Run to run the pipeline. The executor may be replaced via the "executor" attribute.

Rewriting Commands' argument values

Sometimes it's not possible to fill in an argument's value until after a pipeline has been created. The "valsubst" method allows altering them after the fact.

ATTRIBUTES

argfmt

Optional. An IPC::PrettyPipe::Arg::Format object specifying the default prefix and separation attributes for arguments to commands. May be overridden by "argpfx" and "argsep".

argpfx

argsep

Optional. The default prefix and separation attributes for arguments to commands. See IPC::PrettyPipe::Arg for more details. These override any specified via the "argfmt" object.

streams

An arrayref of IPC::PrettyPipe::stream objects.

cmds

Optional. The value should be an arrayref of commands to load into the pipe. The contents of the array are passed to the "ffadd" method for processing.

merge_pipes

Typically, adding a pipe to a pipe via add results in the addition of a nested pipe. If merge_pipes is true, its commands will be directly added if the added pipe hasn't changed the default streams. This defaults to true.

executor

Optional. The means by which the pipeline will be executed. It may be either a class name or an object reference, and must consume the IPC::PrettyPipe::Executor role. It defaults to IPC::PrettyPipe::Execute::IPC::Run.

renderer

Optional. The means by which the pipeline will be rendered. It may be either a class name or an object reference, and must consume the IPC::PretyyPipe::Renderer role. It defaults to IPC::PrettyPipe::Render::Template::Tiny.

METHODS

new

  # initialize the pipe with commands
  $pipe = IPC::PrettyPipe->new(
    cmds => [ $cmd1, $cmd2 ],
    %attributes
  );

  # initialize the pipe with a single command
  $pipe = IPC::PrettyPipe->new( $cmd );

  # create an empty pipeline, setting defaults
  $pipe = IPC::PrettyPipe->new( %attributes );

See "ATTRIBUTES" for a description of the available attributes.

streams

  $streams = $pipe->streams;

A IPC::PrettyPipe::Queue object containing the IPC::PrettyPipe::Stream objects associated with the pipe.

cmds

  $cmds = $pipe->cmds;

Return a IPC::PrettyPipe::Queue object containing the IPC::PrettyPipe::Cmd objects associated with the pipe.

run

   $pipe->run

Execute the pipeline.

renderer

  $renderer = $self->renderer;
  $new_renderer = $self->renderer( $new_renderer );

Get or set a pipe's renderer.

render

  my $string = $pipe->render

Return the rendered pipeline;

add

  $cmd_obj = $pipe->add( cmd => $cmd, %options );

Create an IPC::PrettyPipe::Cmd object, add it to the IPC::PrettyPipe object, and return a handle to it. %options are the same as for the IPC::PrettyPipe::Cmd constructor.

add may also be passed a single parameter, which may be one of:

$cmd_obj = $pipe->add( $cmd_name );

The name of a command

$cmd_obj = $pipe->add( $cmd_obj );

An existing IPC::PrettyPipe::Cmd object

$pipe_obj = $pipe->add( $pipe_obj );

An existing IPC::PrettyPipe object. This is intended to allow pipes to be nested. However, nested pipes with non-default streams may not be supported by the pipe executor.

ffadd

  $pipe->ffadd( @cmds );

A more relaxed means of adding commands. @cmds may contain any of the following items:

  • an IPC::PrettyPipe::Cmd object

  • A command name (i.e. a string), for a command without arguments.

  • A string which matches a stream specification ("Stream Specification" in IPC::PrettyPipe::Stream::Utils), which will cause a new I/O stream to be attached to the pipeline. If the specification requires an additional parameter, the next value in @cmds will be used for that parameter.

  • An arrayref. The first element is the command name; the rest are its arguments; these are passed to IPC::PrettyPipe::Cmd::new as the cmd and args parameters.

  • An IPC::PrettyPipe::Arg::Format object, specifying the argument prefix and separator attributes for successive commands.

stream

  $pipe->stream( $stream_spec );
  $pipe->stream( $stream_spec, $file );

Add an I/O stream to the pipeline. See "Stream Specification" in IPC::PrettyPipe::Stream::Utils for more information.

valmatch

  $n = $pipe->valmatch( $pattern );

Returns the number of commands with a value matching the passed regular expression. (This is not equal to the number of total values which matched. To determine this, iterate over each command, calling it's valmatch method ).

valsubst

   $pipe->valsubst( $pattern, $value, %attr );

Replace arguments to options whose arguments match the Perl regular expression $pattern with $value. The following attributes are available:

firstvalue

The first matched argument will be replaced with this value

lastvalue

The last matched argument will be replaced with this value.

Note that matching is done on a per-command basis, not per-argument basis, so that if a command has multiple matching values, they will all use the same replacement string. To perform more specific changes, use each command's valsubst method directly.

Here's an example where the commands use parameters input and output to indicate where they should write. The strings "stdout" and "stdin" are special and indicate the standard streams. Using valsubst allows an easy update of the pipeline after construction to specify the correct streams.

  $p = new IPC::PrettyPipe;

  $p->add( cmd => 'cmd1',
           args => [ [ input  => 'INPUT',
                       output => 'OUTPUT' ] ] );

  $p->add( cmd => 'cmd2',
           args => [ [ input  => 'INPUT',
                       output => 'OUTPUT' ] ] );

  $p->add( cmd => 'cmd3',
           args => [ [ input  => 'INPUT',
                       output => 'OUTPUT' ] ] );

  $p->valsubst( qr/OUTPUT/, 'stdout',
                lastvalue => 'output_file' );

  $p->valsubst( qr/INPUT/, 'stdin',
                firstvalue => 'input_file' );

  print $p->render, "\n"

results in

        cmd1 \
          input input_file \
          output stdout \
  |     cmd2 \
          input stdin \
          output stdout \
  |     cmd3 \
          input stdin \
          output output_file

OPERATORS

|=

The |= operator is equivalent to calling the "add" method on the pipe:

  $pipe |= $cmd;
  $pipe |= $other_pipe;

is the same as

  $pipe->add( $cmd );
  $pipe->add( $other_pipe );

|

The | operator is equivalent to creating a new pipe and adding the operands of the | operator, e.g.

  $pipe1 | $obj

is the same as

  do {
    my $tpipe = IPC::PrettyPipe->new;
    $tpipe->add( $pipe1 );
    $tpipe->add( $obj );
    $tpipe
  };

where $obj may be either an IPC::PrettyPipe or IPC::PrettyPipe::Cmd object.

SUPPORT

Bugs

Please report any bugs or feature requests to bug-ipc-prettypipe@rt.cpan.org or through the web interface at: https://rt.cpan.org/Public/Dist/Display.html?Name=IPC-PrettyPipe

Source

Source is available at

  https://gitlab.com/djerius/ipc-prettypipe

and may be cloned from

  https://gitlab.com/djerius/ipc-prettypipe.git

AUTHOR

Diab Jerius <djerius@cpan.org>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory.

This is free software, licensed under:

  The GNU General Public License, Version 3, June 2007