The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Venus::Run - Runner Class

ABSTRACT

Runner Class for Perl 5

SYNOPSIS

package main;

use Venus::Run;

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

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

DESCRIPTION

This package is a subclass of Venus::Task which provides a command execution system. This package loads the configuration file used for defining tasks (i.e. command-line operations) which can recursively resolve, injects environment variables, resets the PATH and PERL5LIB variables where appropriate, and executes the tasks by name. See vns for an executable file which loads this package and provides the CLI. See "FEATURES" for usage and configuration information.

INHERITS

This package inherits behaviors from:

Venus::Task

METHODS

This package provides the following methods:

args

args() (hashref)

The args method returns the task argument declarations.

Since 2.91

args example 1
# given: synopsis

package main;

my $args = $run->args;

# {
#   'command' => {
#     help => 'Command to run',
#     required => 1,
#   }
# }

cmds

cmds() (hashref)

The cmds method returns the task command declarations.

Since 2.91

cmds example 1
# given: synopsis

package main;

my $cmds = $run->cmds;

# {
#   'help' => {
#     help => 'Display help and usages',
#     arg => 'command',
#   },
#   'init' => {
#     help => 'Initialize the configuration file',
#     arg => 'command',
#   },
# }

conf

conf() (hashref)

The conf method loads the configuration file returned by "file", then decodes and returns the information as a hashref.

Since 2.91

conf example 1
# given: synopsis

package main;

my $conf = $run->conf;

# {}
conf example 2
# given: synopsis

package main;

local $ENV{VENUS_FILE} = 't/conf/.vns.pl';

my $conf = $run->conf;

# {...}
conf example 3
# given: synopsis

package main;

# e.g. current directory has only a .vns.yaml file

my $conf = $run->conf;

# {...}
conf example 4
# given: synopsis

package main;

# e.g. current directory has only a .vns.yml file

my $conf = $run->conf;

# {...}
conf example 5
# given: synopsis

package main;

# e.g. current directory has only a .vns.json file

my $conf = $run->conf;

# {...}
conf example 6
# given: synopsis

package main;

# e.g. current directory has only a .vns.js file

my $conf = $run->conf;

# {...}
conf example 7
# given: synopsis

package main;

# e.g. current directory has only a .vns.perl file

my $conf = $run->conf;

# {...}
conf example 8
# given: synopsis

package main;

# e.g. current directory has only a .vns.pl file

my $conf = $run->conf;

# {...}

file

file() (string)

The file method returns the configuration file specified in the VENUS_FILE environment variable, or the discovered configuration file in the current directory. The default name for a configuration file is in the form of .vns.*. Configuration files will be decoded based on their file extensions. Valid file extensions are yaml, yml, json, js, perl, and pl.

Since 2.91

file example 1
# given: synopsis

package main;

my $file = $run->file;

# undef
file example 2
# given: synopsis

package main;

local $ENV{VENUS_FILE} = 't/conf/.vns.pl';

my $file = $run->file;

# "t/conf/.vns.pl"
file example 3
# given: synopsis

package main;

# e.g. current directory has only a .vns.yaml file

my $file = $run->file;

# ".vns.yaml"
file example 4
# given: synopsis

package main;

# e.g. current directory has only a .vns.yml file

my $file = $run->file;

# ".vns.yml"
file example 5
# given: synopsis

package main;

# e.g. current directory has only a .vns.json file

my $file = $run->file;

# ".vns.json"
file example 6
# given: synopsis

package main;

# e.g. current directory has only a .vns.js file

my $file = $run->file;

# ".vns.js"
file example 7
# given: synopsis

package main;

# e.g. current directory has only a .vns.perl file

my $file = $run->file;

# ".vns.perl"
file example 8
# given: synopsis

package main;

# e.g. current directory has only a .vns.pl file

my $file = $run->file;

# ".vns.pl"
footer() (string)

The footer method returns examples and usage information used in usage text.

Since 2.91

# given: synopsis

package main;

my $footer = $run->footer;

# "..."

handler

handler(hashref $data) (any)

The handler method processes the data provided and executes the request then returns the invocant unless the program is exited.

Since 2.91

handler example 1
package main;

use Venus::Run;

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

$run->execute;

# ()
handler example 2
package main;

use Venus::Run;

my $run = Venus::Run->new(['help']);

$run->execute;

# ()
handler example 3
package main;

use Venus::Run;

my $run = Venus::Run->new(['--help']);

$run->execute;

# ()
handler example 4
package main;

use Venus::Run;

my $run = Venus::Run->new(['init']);

$run->execute;

# ()
handler example 5
package main;

use Venus::Run;

# on linux

my $run = Venus::Run->new(['echo']);

$run->execute;

# ()

# i.e. ['echo']
handler example 6
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   cpan: cpanm -llocal -qn
#
# ...

my $run = Venus::Run->new(['cpan', 'Venus']);

$run->execute;

# ()

# i.e. cpanm '-llocal' '-qn' Venus
handler example 7
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   cpan: cpanm -llocal -qn
#   deps: cpan --installdeps .
#
# ...

my $run = Venus::Run->new(['cpan', '--installdeps', '.']);

$run->execute;

# ()

# i.e. cpanm '-llocal' '-qn' '--installdeps' '.'
handler example 8
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   okay: $PERL -c
#
# ...
#
# libs:
# - -Ilib
# - -Ilocal/lib/perl5
#
# ...
#
# vars:
#   PERL: perl
#
# ...

my $run = Venus::Run->new(['okay', 'lib/Venus.pm']);

$run->execute;

# ()

# i.e. perl '-Ilib' '-Ilocal/lib/perl5' '-c'
handler example 9
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   repl: $REPL
#
# ...
#
# libs:
# - -Ilib
# - -Ilocal/lib/perl5
#
# ...
#
# vars:
#   PERL: perl
#   REPL: $PERL -dE0
#
# ...

my $run = Venus::Run->new(['repl']);

$run->execute;

# ()

# i.e. perl '-Ilib' '-Ilocal/lib/perl5' '-dE0'
handler example 10
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   exec: $PERL
#
# ...
#
# libs:
# - -Ilib
# - -Ilocal/lib/perl5
#
# ...
#
# vars:
#   PERL: perl
#
# ...

my $run = Venus::Run->new(['exec', '-MVenus=date', 'say date']);

$run->execute;

# ()

# i.e. perl '-Ilib' '-Ilocal/lib/perl5' '-MVenus=date' 'say date'
handler example 11
package main;

use Venus::Run;

# on linux

# in config
#
# ---
# exec:
#   test: $PROVE
#
# ...
#
# libs:
# - -Ilib
# - -Ilocal/lib/perl5
#
# ...
#
# vars:
#   PROVE: prove
#
# ...

my $run = Venus::Run->new(['test', 't']);

$run->execute;

# ()

# i.e. prove '-Ilib' '-Ilocal/lib/perl5' t
handler example 12
package main;

use Venus::Run;

# on linux

my $run = Venus::Run->new(['echo', 1, '|', 'less']);

$run->execute;

# ()

# i.e. echo 1 | less
handler example 13
package main;

use Venus::Run;

# on linux

my $run = Venus::Run->new(['echo', 1, '&&', 'echo', 2]);

$run->execute;

# ()

# i.e. echo 1 && echo 2
handler example 14
package main;

use Venus::Run;

# on linux

local $ENV{VENUS_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 $run = Venus::Run->new(['mypan']);

$run->execute;

# ()

# i.e. cpanm '-llocal' '-qn' '-M' 'https://pkg.myapp.com'
handler example 15
package main;

use Venus::Run;

# on linux

local $ENV{VENUS_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 $run = Venus::Run->new(['psql', 'backup']);

$run->execute;

# ()

# i.e. vns backup
handler example 16
package main;

use Venus::Run;

# on linux

local $ENV{VENUS_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 $run = Venus::Run->new(['psql', 'backup']);

$run->execute;

# VENUS_FILE=t/conf/psql.perl vns backup

local $ENV{VENUS_FILE} = 't/conf/psql.perl';

$run = Venus::Run->new(['backup']);

$run->execute;

# ()

# i.e. pg_backupcluster
handler example 17
package main;

use Venus::Run;

# on linux

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

local $ENV{VENUS_FILE} = 't/conf/flow.perl';

my $run = Venus::Run->new(['setup-term']);

$run->execute;

# ()

# i.e.
# cpanm '-llocal' '-qn' 'Term::ReadKey'
# cpanm '-llocal' '-qn' 'Term::ReadLine::Gnu'
handler example 18
package main;

use Venus::Run;

# on linux

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

local $ENV{VENUS_FILE} = 't/conf/asks.perl';

my $run = Venus::Run->new(['echo', '$PASS']);

$run->execute;

# ()

# i.e. echo '$PASS'
handler example 19
package main;

use Venus::Run;

# on linux

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

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

local $ENV{VENUS_FILE} = 't/conf/func.perl';

my $run = Venus::Run->new(['dump', '--', 'hello']);

$run->execute;

# ()

# i.e. perl -Ilib ... -E '(do "./t/path/etc/dump.pl")->(\@ARGV)' '--' hello
handler example 20
package main;

use Venus::Run;

# on linux

local $ENV{VENUS_FILE} = 't/conf/when.perl';

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

my $run = Venus::Run->new(['name']);

$run->execute;

# ()

# i.e. echo $OSNAME

# i.e. echo LINUX
handler example 21
package main;

use Venus::Run;

# on mswin32

local $ENV{VENUS_FILE} = 't/conf/when.perl';

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

my $run = Venus::Run->new(['name']);

$run->execute;

# ()

# i.e. echo $OSNAME

# i.e. echo WINDOWS
handler example 22
package main;

use Venus::Run;

# on linux

local $ENV{VENUS_FILE} = 't/conf/help.perl';

# in config
#
# ---
# exec:
#   exec: perl -c
#
# ...
# help:
#   exec: Usage: perl -c <FILE>
#
# ...

my $run = Venus::Run->new(['help', 'exec']);

$run->execute;

# ()

# i.e. Usage: perl -c <FILE>
handler example 23
package main;

use Venus::Run;

my $run = Venus::Run->new(['func', 'dump', 't/path/etc/dump.pl']);

$run->execute;

# ()
handler example 24
package main;

use Venus::Run;

my $run = Venus::Run->new(['with', 'asks', 't/conf/asks.perl']);

$run->execute;

# ()

init

init() (hashref)

The init method returns the default configuration to be used when initializing the system with a new configuration file.

Since 2.91

init example 1
# given: synopsis

package main;

my $init = $run->init;

# {
#   data => {
#     ECHO => 1,
#   },
#   exec => {
#     brew => 'perlbrew',
#     cpan => 'cpanm -llocal -qn',
#     docs => 'perldoc',
#     each => 'shim -nE',
#     edit => '$EDITOR $VENUS_FILE',
#     eval => 'shim -E',
#     exec => '$PERL',
#     info => '$PERL -V',
#     lint => 'perlcritic',
#     okay => '$PERL -c',
#     repl => '$REPL',
#     reup => 'cpanm -qn Venus',
#     says => 'eval "map log(eval), @ARGV"',
#     shim => '$PERL -MVenus=true,false,log',
#     test => '$PROVE',
#     tidy => 'perltidy',
#   },
#   libs => [
#     '-Ilib',
#     '-Ilocal/lib/perl5',
#   ],
#   path => [
#     './bin',
#     './dev',
#     './local/bin',
#   ],
#   perl => {
#     perl => 'perl',
#     prove => 'prove',
#   },
#   vars => {
#     PERL => 'perl',
#     PROVE => 'prove'
#     REPL => '$PERL -dE0'
#   },
# }

name

name() (string)

The name method returns the default name for the task. This is used in usage text and can be controlled via the VENUS_TASK_NAME environment variable, or the NAME package variable.

Since 2.91

name example 1
# given: synopsis

package main;

my $name = $run->name;

# "Venus::Run"
name example 2
# given: synopsis

package main;

local $ENV{VENUS_TASK_NAME} = 'venus-runner';

my $name = $run->name;

# "venus-runner"
name example 3
# given: synopsis

package main;

local $Venus::Run::NAME = 'venus-runner';

my $name = $run->name;

# "venus-runner"

opts

opts() (hashref)

The opts method returns the task options declarations.

Since 2.91

opts example 1
# given: synopsis

package main;

my $opts = $run->opts;

# {
#   'help' => {
#     help => 'Show help information',
#   }
# }

FEATURES

This package provides the following features:

config

The CLI provided by this package operates on a configuration file, typically having a base name of .vns with a Perl, JSON, or YAML file extension. Here is an example of a configuration file using YAML with the filename .vns.yaml.

---
data:
  ECHO: true
exec:
  cpan: cpanm -llocal -qn
  okay: $PERL -c
  repl: $PERL -dE0
  says: $PERL -E "map log(eval), @ARGV"
  test: $PROVE
libs:
- -Ilib
- -Ilocal/lib/perl5
load:
- -MVenus=true,false
path:
- ./bin
- ./dev
- -Ilocal/bin
perl:
  perl: perl
  prove: prove
vars:
  PERL: perl
  PROVE: prove
config-asks
---
asks:
  HOME: Enter your home dir

The configuration file's asks section provides a list of key/value pairs where the key is the name of the environment variable and the value is used as the message used by the CLI to prompt for input if the environment variable is not defined.

config-data
---
data:
  ECHO: true

The configuration file's data section provides a non-dynamic list of key/value pairs that will be used as environment variables.

config-exec
---
exec:
  okay: $PERL -c

The configuration file's exec section provides the main dynamic tasks which can be recursively resolved and expanded.

config-find
---
find:
  cpanm: /usr/local/bin/cpanm

The configuration file's find section provides aliases which can be recursively resolved and expanded for use in other tasks.

config-flow
---
flow:
  deps:
  - cpan Term::ReadKey
  - cpan Term::ReadLine::Gnu

The configuration file's flow section provides chainable tasks which are recursively resolved and expanded from other tasks.

config-from
---
from:
- /usr/share/vns/.vns.yaml

The configuration file's from section provides paths to other configuration files which will be merged before execution allowing the inheritance of of configuration values.

config-func
---
func:
  build: ./scripts/build.pl

The configuration file's func section provides a list of static key/value pairs where the key is the "subcommand" passed to the runner as the first arugment, and the value is the Perl script that will be loaded and executed. The Perl script is expected to return a subroutine reference and will be passed an array reference to the arguments provided.

config-help
---
help:
  build: Usage: vns build [<option>]

The configuration file's help section provides a list of static key/value pairs where the key is the "subcommand" to display help text for, and the value is the help text to be displayed.

config-libs
---
libs:
- -Ilib
- -Ilocal/lib/perl5

The configuration file's libs section provides a list of -I/path/to/lib "include" statements that will be automatically added to tasks expanded from the perl section.

config-load
---
load:
- -MVenus=true,false

The configuration file's load section provides a list of -MPackage "import" statements that will be automatically added to tasks expanded from the perl section.

config-path
---
path:
- ./bin
- ./dev
- -Ilocal/bin

The configuration file's path section provides a list of paths to be prepended to the PATH environment variable which allows programs to be found.

config-perl
---
perl:
  perl: perl

The configuration file's perl section provides the dynamic perl tasks which can serve as tasks with default commands (with options) and which can be recursively resolved and expanded.

config-task
---
task:
  setup: $PERL -MMyApp::Task::Setup -E0 --

The configuration file's task section provides the dynamic perl tasks which "load" Venus::Task derived packages, and which can be recursively resolved and expanded. These tasks will typically take the form of perl -Ilib -MMyApp::Task -E0 -- and will be automatically executed as a CLI.

config-vars
---
vars:
  PERL: perl

The configuration file's vars section provides a list of dynamic key/value pairs that can be recursively resolved and expanded and will be used as environment variables.

config-when
---
when:
  is_lin:
    data:
      OSNAME: LINUX
  is_win:
    data:
      OSNAME: WINDOWS

The configuration file's when section provides a configuration tree to be merged with the existing configuration based on the name current operating system. The is_$name key should correspond to one of the types specified by "type" in Venus::Os.

config-with
---
with:
  psql: ./psql-tools/.vns.yml

The configuration file's with section provides a list of static key/value pairs where the key is the "subcommand" passed to the runner as the first arugment, and the value is the configuration file where the subcommand task definitions are defined which the runner dispatches to.

vns-cli

Here are example usages of the configuration file mentioned, executed by the vns CLI, which is simply an executable file which loads this package.

# Mint a new configuration file
vns init

...

# Mint a new JSON configuration file
VENUS_FILE=.vns.json vns init

# Mint a new YAML configuration file
VENUS_FILE=.vns.yaml vns init

...

# Install a distribution
vns cpan $DIST

# i.e.
# cpanm --llocal -qn $DIST

# Check that a package can be compiled
vns okay $FILE

# i.e.
# perl -Ilib -Ilocal/lib/perl5 -c $FILE

# Use the Perl debugger as a REPL
vns repl

# i.e.
# perl -Ilib -Ilocal/lib/perl5 -dE0

# Evaluate arbitrary Perl expressions
vns exec ...

# i.e.
# perl -Ilib -Ilocal/lib/perl5 -MVenus=log -E $@

# Test the Perl project in the CWD
vns test t

# i.e.
# prove -Ilib -Ilocal/lib/perl5 t

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.