NAME

Venus::Run - Run Class

ABSTRACT

Run Class for Perl 5

SYNOPSIS

package main;

use Venus::Run;

my $run = Venus::Run->new;

# bless({...}, 'Venus::Run')

DESCRIPTION

This package provides a modular command execution framework for Perl projects. It loads a configuration with commands, aliases, scripts, variables, and paths, and resolves them into full shell commands. This allows you to define reusable CLI behaviors using declarative config without writing wrappers or shell scripts. It supports layered configuration, caching, variable expansion, and recursive resolution, with support for custom flow control, Perl module injection, and user prompts. It also resets the PATH and PERL5LIB variables where appropriate. See vns for an executable file which loads this package and provides the CLI. See "FEATURES" for usage and configuration information.

ATTRIBUTES

This package has the following attributes:

cache

cache(hashref $data) (hashref)

The cache attribute is used to store resolved values and avoid redundant computation during command expansion.

Since 4.15

cache example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $cache = $run->cache;

# {}

config

config(hashref $data) (hashref)

The config attribute is used to store the configuration used to resolve commands, variables, paths, and other runtime behavior.

Since 4.15

config example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = $run->config;

# {...}

debug

debug(boolean $data) (boolean)

The debug attribute is used to determine whether to output additional content for the purpose of debugging command execution.

Since 4.15

debug example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $debug = $run->debug;

# false

handler

handler(coderef $data) (coderef)

The handler attribute holds the callback (i.e. coderef) invoked for each step or command returned for a resolved command or expression.

Since 4.15

handler example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $handler = $run->handler;

# sub {...}

INHERITS

This package inherits behaviors from:

Venus::Role::Utility

INTEGRATES

This package integrates behaviors from:

Venus::Role::Optional

METHODS

This package provides the following methods:

callback

callback(coderef $code, any @args) (any)

The callback method executes a against each fully-resolved command derived from the given arguments. This method prepares the runtime environment by expanding variables, updating paths, and loading libraries as defined in the config. It resolves the given arguments into executable commands and passes each one to the callback in sequence. The callback receives the resolved program name followed by its arguments. Environment variables are restored to their original state after execution. Returns the result of the last successful callback execution, or undef if none were executed.

Since 4.15

callback example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $callback = $run->callback;

# undef
callback example 2
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $data;

$run->config({
  exec => {
    info => 'perl -V',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
  },
});

my $callback = $run->callback(sub{join ' ', @_}, 'info');

# perl -Ilib -Ilocal/lib/perl5 -V

execute

execute(any @args) (any)

The execute method "resolves" the argument(s) provided and executes "callback" using the "handler" for each fully-resolved command encountered.

Since 4.15

execute example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $execute = $run->execute;

# undef
execute example 2
package main;

use Venus::Run;

my $run = Venus::Run->new;

$run->handler(sub{join ' ', @_});

my $execute = $run->execute('perl');

# ['perl']
execute example 3
package main;

use Venus::Run;

my $run = Venus::Run->new;

$run->config({
  exec => {
    info => 'perl -V',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
  },
});

$run->handler(sub{join ' ', @_});

my $execute = $run->execute('info');

# ['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-V'"]

new

new(any @args) (Venus::Run)

The new method constructs an instance of the package.

Since 4.15

new example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

# bless({...}, 'Venus::Run')
new example 2
package main;

use Venus;
use Venus::Run;

my $run = Venus::Run->new(debug => true);

# bless({...}, 'Venus::Run')
new example 3
package main;

use Venus;
use Venus::Run;

my $run = Venus::Run->new(debug => false, handler => sub {});

# bless({...}, 'Venus::Run')

resolve

resolve(hashref $config, any @data) (arrayref)

The resolve method expands a given item or command by recursively resolving aliases, variables, and configuration entries into a full command string or array. This method returns a list in list context.

Since 4.15

resolve example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $resolve = $run->resolve;

# []
resolve example 2
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $resolve = $run->resolve({}, 'perl');

# [['perl']]
resolve example 3
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {find => {perl => '/path/to/perl'}};

my $resolve = $run->resolve($config, 'perl -c');

# [['/path/to/perl', "'-c'"]]
resolve example 4
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    info => 'perl -V',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
  },
};

my $resolve = $run->resolve($config, 'info');

# [['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-V'"]]
resolve example 5
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    info => 'perl -V',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  load => [
    '-MVenus',
  ],
  perl => {
    perl => 'perl',
  },
};

my $resolve = $run->resolve($config, 'info');

# [['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-MVenus'", "'-V'"]]
resolve example 6
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    repl => '$REPL',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  load => [
    '-MVenus',
  ],
  perl => {
    perl => 'perl',
  },
  vars => {
    REPL => 'perl -dE0',
  },
};

my $resolve = $run->resolve($config, 'repl');

# [['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-MVenus'", "'-dE0'"]]
resolve example 7
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    eval => 'shim -E',
    says => 'eval "map log(eval), @ARGV"',
    shim => '$PERL -MVenus=true,false,log',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
  },
  vars => {
    PERL => 'perl',
  },
};

my $resolve = $run->resolve($config, 'says', 1);

# [['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-MVenus=true,false,log'", "'-E'", "\"map log(eval), \@ARGV\"", "'1'"]]
resolve example 8
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    cpan => 'cpanm -llocal -qn',
  },
};

my $resolve = $run->resolve($config, 'cpan', 'Venus');

# [['cpanm', "'-llocal'", "'-qn'", "'Venus'"]]
resolve example 9
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {
  exec => {
    test => '$PROVE',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
    prove => 'prove',
  },
  vars => {
    PROVE => 'prove -j8',
  },
};

my $resolve = $run->resolve($config, 'test', 't');

# [['prove', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-j8'", "'t'"]]
resolve example 10
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {};

my $resolve = $run->resolve($config, 'echo 1 | less');

# [['echo', "'1'", '|', "'less'"]]
resolve example 11
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {};

my $resolve = $run->resolve($config, 'echo 1 && echo 2');

# [['echo', "'1'", '&&', 'echo', "'2'"]]
resolve example 12
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $config = {};

my $resolve = $run->resolve($config, 'echo 1 || echo 2');

# [['echo', "'1'", '||', 'echo', "'2'"]]
resolve example 13
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/from.perl');

# in config
#
# ---
# from:
# - /path/to/parent
#
# ...
#
# exec:
#   mypan: cpan -M https://pkg.myapp.com

# in config (/path/to/parent)
#
# ---
# exec:
#   cpan: cpanm -llocal -qn
#
# ...

my $config = $run->prepare_conf($run->config);

my $resolve = $run->resolve($config, 'mypan');

# [['cpanm', "'-llocal'", "'-qn'", "'-M'", "'https://pkg.myapp.com'"]]
resolve example 14
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/with.perl');

# in config
#
# ---
# with:
#   psql: /path/to/other
#
# ...

# in config (/path/to/other)
#
# ---
# exec:
#   backup: pg_backupcluster
#   restore: pg_restorecluster
#
# ...

my $config = $run->prepare_conf($run->config);

my $resolve = $run->resolve($config, 'psql', 'backup');

# [['pg_backupcluster']]
resolve example 15
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/psql.perl');

# in config
#
# ---
# exec:
#   backup: pg_backupcluster
#   restore: pg_restorecluster
#
# ...

my $config = $run->prepare_conf($run->config);

my $resolve = $run->resolve($config, 'backup');

# [['pg_backupcluster']]
resolve example 16
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/flow.perl');

# in config
#
# ---
# exec:
#   cpan: cpanm -llocal -qn
#
# ...
#
# flow:
#   setup-term:
#   - cpan Term::ReadKey
#   - cpan Term::ReadLine::Gnu
#
# ...

my $config = $run->prepare_conf($run->config);

my $resolve = $run->resolve($config, 'setup-term');

# [
#   ['cpanm', "'-llocal'", "'-qn'", "'Term::ReadKey'"],
#   ['cpanm', "'-llocal'", "'-qn'", "'Term::ReadLine::Gnu'"],
# ]
resolve example 17
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/asks.perl');

# in config
#
# ---
# asks:
#   PASS: What's the password
#
# ...

my $config = $run->prepare_vars($run->prepare_conf($run->config));

my $resolve = $run->resolve($config, 'echo', '$PASS');

# [['echo', "'secret'"]]
resolve example 18
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/func.perl');

# in config
#
# ---
# func:
#   dump: /path/to/dump.pl
#
# ...

# in dump.pl (/path/to/dump.pl)
#
# sub {
#   my ($args) = @_;
#
#   ...
# }

my $config = $run->config;

my $resolve = $run->resolve($config, 'dump', '--', 'hello');

# [['echo', "'secret'"]]
resolve example 19
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/when.perl');

# in config
#
# ---
# exec:
#   name: echo $OSNAME
#
# ...
# when:
#   is_lin:
#     data:
#       OSNAME: LINUX
#   is_win:
#     data:
#       OSNAME: WINDOWS
#
# ...

# assume Linux OS

my $config = $run->prepare_vars($run->prepare_conf($run->config));

my $resolve = $run->resolve($config, 'name');

# [['echo', "'LINUX'"]]
resolve example 20
package main;

use Venus::Run;

my $run = Venus::Run->from_file('t/conf/when.perl');

# in config
#
# ---
# exec:
#   name: echo $OSNAME
#
# ...
# when:
#   is_lin:
#     data:
#       OSNAME: LINUX
#   is_win:
#     data:
#       OSNAME: WINDOWS
#
# ...

# assume Windows OS

my $config = $run->prepare_vars($run->prepare_conf($run->config));

my $resolve = $run->resolve($config, 'name');

# [['echo', "'WINDOWS'"]]

result

result(any @args) (any)

The result method is an alias for the "execute" method, which executes the the "handler" for each fully-resolved command based on the arguments provided.

Since 4.15

result example 1
package main;

use Venus::Run;

my $run = Venus::Run->new;

my $result = $run->result;

# undef
result example 2
package main;

use Venus::Run;

my $run = Venus::Run->new;

$run->handler(sub{join ' ', @_});

my $result = $run->result('perl');

# ['perl']
result example 3
package main;

use Venus::Run;

my $run = Venus::Run->new;

$run->config({
  exec => {
    info => 'perl -V',
  },
  libs => [
    '-Ilib',
    '-Ilocal/lib/perl5',
  ],
  perl => {
    perl => 'perl',
  },
});

$run->handler(sub{join ' ', @_});

my $result = $run->result('info');

# ['perl', "'-Ilib'", "'-Ilocal/lib/perl5'", "'-V'"]

AUTHORS

Awncorp, awncorp@cpan.org

LICENSE

Copyright (C) 2022, Awncorp, awncorp@cpan.org.

This program is free software, you can redistribute it and/or modify it under the terms of the Apache license version 2.0.