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::Task - Task Class

ABSTRACT

Task Class for Perl 5

SYNOPSIS

  package Example;

  use base 'Venus::Task';

  package main;

  my $task = Example->new(['--help']);

  # bless({...}, 'Example')

DESCRIPTION

This package provides a superclass, methods, and a simple framework for creating CLIs (command-line interfaces).

ATTRIBUTES

This package has the following attributes:

data

  data(arrayref $data) (arrayref)

The data attribute is read-write, accepts (ArrayRef) values, and is optional.

Since 2.91

data example 1
  # given: synopsis

  package main;

  my $set_data = $task->data([1..4]);

  # [1..4]
data example 2
  # given: synopsis

  # given: example-1 data

  package main;

  my $get_data = $task->data;

  # [1..4]

tryer

  tryer(Venus::Try $data) (Venus::Try)

The tryer attribute is read-write, accepts (Venus::Try) values, and is optional.

Since 4.11

tryer example 1
  # given: synopsis

  package main;

  my $set_tryer = $task->tryer($task->try('execute'));

  # bless(..., "Venus::Try")
tryer example 2
  # given: synopsis

  # given: example-1 tryer

  package main;

  my $get_tryer = $task->tryer;

  # bless(..., "Venus::Try")

INHERITS

This package inherits behaviors from:

Venus::Kind::Utility

INTEGRATES

This package integrates behaviors from:

Venus::Role::Buildable

METHODS

This package provides the following methods:

args

  args() (hashref)

The args method can be overridden and returns a hashref suitable to be passed to the "set" in Venus::Cli method as type "arg". An "arg" is a CLI positional argument.

Since 2.91

args example 1
  # given: synopsis

  package main;

  my $args = $task->args;

  # {}
args example 2
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      name => {
        help => 'Name of user',
      },
    }
  }

  package main;

  my $task = Example->new;

  my $args = $task->args;

  # {
  #   name => {
  #     help => 'Name of user',
  #   },
  # }

auto

  auto(coderef $code) (Venus::Task)

The auto class method is similar to the "run" method but accepts a callback which will be invoked with the instansiated class before calling the "execute" method. This method is meant to be used directly in package scope outside of any routine, and will only auto-execute under the conditions that the caller is the "main" package space and the VENUS_TASK_AUTO environment variable is truthy.

Since 4.11

auto example 1
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new(['--help']);

  my $auto = $task->auto(sub{});

  # bless({...}, 'Venus::Task')
auto example 2
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  auto Example sub {
    my ($self) = @_;
    $self->tryer->no_default;
  };

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

cmds

  cmds() (hashref)

The cmds method can be overridden and returns a hashref suitable to be passed to the "set" in Venus::Cli method as type "cmd". A "cmd" is a CLI command which maps to an positional argument declare by "args".

Since 2.91

cmds example 1
  # given: synopsis

  package main;

  my $cmds = $task->cmds;

  # {}
cmds example 2
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      op => {
        help => 'Name of operation',
      },
    }
  }

  sub cmds {

    return {
      init => {
        help => 'Initialize the system',
        arg => 'op',
      },
    }
  }

  package main;

  my $task = Example->new;

  my $cmds = $task->cmds;

  # {
  #   init => {
  #     help => 'Initialize the system',
  #     arg => 'op',
  #   },
  # }

description

  description() (Venus::Task)

The description method doesn't exist on the Venus::Task superclass but if defined returns a string that will be used as the CLI "description" (before the arguments, options, and commands text).

Since 2.91

description example 1
  package Example;

  use base 'Venus::Task';

  sub description {

    "This text used in the description area of the usage text"
  }

  package main;

  my $task = Example->new;

  my $description = $task->description;

  # "..."

execute

  execute() (Venus::Task)

The execute method can be overridden and returns the invocant. This method prepares the Venus::Cli via "prepare", and runs the "startup", "handler", and "shutdown" sequences, passing "parsed" in Venus::Cli to each method. This method is not typically invoked directly, but instead by the "tryer" attribute via the "run" or "auto" class methods.

Since 2.91

execute example 1
  # given: synopsis

  package main;

  my $execute = $task->execute;

  # bless({...}, 'Venus::Task')
execute example 2
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      name => {
        help => 'Name of user',
      },
    }
  }

  sub opts {

    return {
      sudo => {
        help => 'Elevate user privileges',
        alias => ['s'],
      },
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  sub startup {
    my ($self) = @_;

    $self->{startup} = time;

    return $self;
  }

  sub handler {
    my ($self, $data) = @_;

    $self->{handler} = time;
    $self->{parsed} = $data;

    return $self;
  }

  sub shutdown {
    my ($self) = @_;

    $self->{shutdown} = time;

    return $self;
  }

  package main;

  my $task = Example->new(['admin', '-s']);

  my $execute = $task->execute;

  # bless({...}, 'Venus::Task')
execute example 3
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      name => {
        help => 'Name of user',
      },
    }
  }

  sub opts {

    return {
      sudo => {
        help => 'Elevate user privileges',
        alias => ['s'],
      },
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  sub handler {
    my ($self, $data) = @_;

    $self->{handler} = time;
    $self->{parsed} = $data;

    return $self;
  }

  package main;

  my $task = Example->new(['-s']);

  my $execute = $task->execute;

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

exit

  exit(number $code, string | coderef $code, any @args) (any)

The exit method exits the program using the exit code provided. The exit code defaults to 0. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments. If an exit code of undef is provided, the exit code will be determined by the result of the dispatching.

Since 2.91

exit example 1
  # given: synopsis

  package main;

  my $exit = $task->exit;

  # ()
exit example 2
  # given: synopsis

  package main;

  my $exit = $task->exit(0);

  # ()
exit example 3
  # given: synopsis

  package main;

  my $exit = $task->exit(1);

  # ()
exit example 4
  # given: synopsis

  package main;

  my $exit = $task->exit(1, 'log_error', 'oh no');

  # ()

fail

  fail(string | coderef $code, any @args) (any)

The fail method exits the program with the exit code 1. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments.

Since 2.91

fail example 1
  # given: synopsis

  package main;

  my $fail = $task->fail;

  # ()
fail example 2
  # given: synopsis

  package main;

  my $fail = $task->fail('log_error', 'oh no');

  # ()
  footer() (Venus::Task)

The footer method doesn't exist on the Venus::Task superclass but if defined returns a string that will be used as the CLI "footer" (after the arguments, options, and commands text).

Since 2.91

  package Example;

  use base 'Venus::Task';

  sub footer {

    "This text used in the footer area of the usage text"
  }

  package main;

  my $task = Example->new;

  my $footer = $task->footer;

  # "..."

handler

  handler(hashref $data) (Venus::Task)

The handler method can and should be overridden and returns the invocant. This method is where the central task operations are meant to happen. By default, if not overriden this method calls "usage" if a "help" flag is detected.

Since 2.91

handler example 1
  # given: synopsis

  package main;

  my $handler = $task->handler({});

  # bless({...}, 'Venus::Task')
handler example 2
  # given: synopsis

  package main;

  my $handler = $task->handler({help => 1});

  # bless({...}, 'Venus::Task')
handler example 3
  package Example;

  use base 'Venus::Task';

  sub handler {
    my ($self, $data) = @_;

    $self->{handler} = time;
    $self->{parsed} = $data;

    return $self;
  }

  package main;

  my $task = Example->new;

  my $handler = $task->handler({});

  # bless({...}, 'Venus::Task')
  header() (Venus::Task)

The header method doesn't exist on the Venus::Task superclass but if defined returns a string that will be used as the CLI "header" (after the title, before the arguments, options, and commands text).

Since 2.91

header example 1
  package Example;

  use base 'Venus::Task';

  sub header {

    "This text used in the header area of the usage text"
  }

  package main;

  my $task = Example->new;

  my $header = $task->header;

  # "..."

help

  help() (string)

The help method can be overridden and returns a string representing "help" text for the CLI. By default this method returns the result of "help" in Venus::Cli, based on the "cli" object.

Since 2.91

help example 1
  # given: synopsis

  package main;

  my $help = $task->help;

  # "Usage: application"
help example 2
  package Example;

  use base 'Venus::Task';

  sub name {

    return 'eg';
  }

  package main;

  my $task = Example->new;

  $task->prepare;

  my $help = $task->help;

  # "Usage: application"

log_debug

  log_debug(any @log_debug) (Venus::Log)

The log_debug method dispatches to the "debug" in Venus::Log method and returns the result.

Since 2.91

log_debug example 1
  # given: synopsis

  package main;

  my $log_debug = $task->log_debug('something' ,'happened');

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

log_error

  log_error(any @log_error) (Venus::Log)

The log_error method dispatches to the "error" in Venus::Log method and returns the result.

Since 2.91

log_error example 1
  # given: synopsis

  package main;

  my $log_error = $task->log_error('something' ,'happened');

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

log_fatal

  log_fatal(any @log_fatal) (Venus::Log)

The log_fatal method dispatches to the "fatal" in Venus::Log method and returns the result.

Since 2.91

log_fatal example 1
  # given: synopsis

  package main;

  my $log_fatal = $task->log_fatal('something' ,'happened');

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

log_info

  log_info(any @log_info) (Venus::Log)

The log_info method dispatches to the "info" in Venus::Log method and returns the result.

Since 2.91

log_info example 1
  # given: synopsis

  package main;

  my $log_info = $task->log_info('something' ,'happened');

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

log_level

  log_level() (string)

The log_level method can be overridden and returns a valid "level" in Venus::Log value. This method defaults to returning info.

Since 2.91

log_level example 1
  # given: synopsis

  package main;

  my $log_level = $task->log_level;

  # "info"

log_trace

  log_trace(any @log_trace) (Venus::Log)

The log_trace method dispatches to the "trace" in Venus::Log method and returns the result.

Since 2.91

log_trace example 1
  # given: synopsis

  package main;

  my $log_trace = $task->log_trace('something' ,'happened');

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

log_warn

  log_warn(any @log_warn) (Venus::Log)

The log_warn method dispatches to the "warn" in Venus::Log method and returns the result.

Since 2.91

log_warn example 1
  # given: synopsis

  package main;

  my $log_warn = $task->log_warn('something' ,'happened');

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

name

  name() (Venus::Task)

The name method can be overridden and returns the name of the task (and application). This method defaults to $0 if not overridden.

Since 2.91

name example 1
  # given: synopsis

  package main;

  my $name = $task->name;

  # "/path/to/application"
name example 2
  package Example;

  use base 'Venus::Task';

  sub name {

    return 'eg';
  }

  package main;

  my $task = Example->new;

  my $name = $task->name;

  # "eg"

okay

  okay(string | coderef $code, any @args) (any)

The okay method exits the program with the exit code 0. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments.

Since 2.91

okay example 1
  # given: synopsis

  package main;

  my $okay = $task->okay;

  # ()
okay example 2
  # given: synopsis

  package main;

  my $okay = $task->okay('log_info', 'yatta');

  # ()

opts

  opts() (hashref)

The opts method can be overridden and returns a hashref suitable to be passed to the "set" in Venus::Cli method as type "opt". An "opt" is a CLI option (or flag).

Since 2.91

opts example 1
  # given: synopsis

  package main;

  my $opts = $task->opts;

  # {}
opts example 2
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new;

  my $opts = $task->opts;

  # {
  #   help => {
  #     help => 'Display help',
  #     alias => ['h'],
  #   },
  # }

output

  output(string $level, string @messages) (Venus::Task)

The output method is configured as the "handler" in Venus::Log by "prepare", can be overridden and returns the invocant.

Since 2.91

output example 1
  # given: synopsis

  package main;

  $task->prepare;

  $task = $task->output('info', 'something happened');

  # bless({...}, 'Example')

pass

  pass(string | coderef $code, any @args) (any)

The pass method exits the program with the exit code 0. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments.

Since 3.10

pass example 1
  # given: synopsis

  package main;

  my $pass = $task->pass;

  # ()
pass example 2
  # given: synopsis

  package main;

  my $pass = $task->pass('log_info', 'yatta');

  # ()

prepare

  prepare() (Venus::Task)

The prepare method can be overridden, but typically shouldn't, is responsible for configuring the "cli" and "log" objects, parsing the arguments, and after returns the invocant.

Since 2.91

prepare example 1
  # given: synopsis

  package main;

  my $prepare = $task->prepare;

  # bless({...}, 'Venus::Task')
prepare example 2
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      name => {
        help => 'Name of user',
      },
    }
  }

  sub opts {

    return {
      sudo => {
        help => 'Elevate user privileges',
        alias => ['s'],
      },
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new;

  my $prepare = $task->prepare;

  # bless({...}, 'Venus::Task')
prepare example 3
  package Example;

  use base 'Venus::Task';

  sub args {

    return {
      name => {
        help => 'Name of user',
      },
    }
  }

  sub cmds {

    return {
      admin => {
        help => 'Run as an admin',
        arg => 'name',
      },
      user => {
        help => 'Run as a user',
        arg => 'name',
      },
    }
  }

  sub opts {

    return {
      sudo => {
        help => 'Elevate user privileges',
        alias => ['s'],
      },
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new(['admin', '-s']);

  my $prepare = $task->prepare;

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

run

  run(any @args) (Venus::Task)

The run class method will automatically execute the task class by instansiating the class and calling the "execute" method and returns the invocant. This method is meant to be used directly in package scope outside of any routine, and will only auto-execute under the conditions that the caller is the "main" package space and the VENUS_TASK_AUTO environment variable is truthy.

Since 2.91

run example 1
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new(['--help']);

  my $run = $task->run;

  # bless({...}, 'Venus::Task')
run example 2
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  run Example;

  # 'Example'

shutdown

  shutdown(hashref $data) (Venus::Task)

The shutdown method can be overridden and returns the invocant. This method is called by "execute" automatically after "handler" and is passed the result of "parsed" in Venus::Cli.

Since 2.91

shutdown example 1
  # given: synopsis

  package main;

  my $shutdown = $task->shutdown({});

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

startup

  startup(hashref $data) (Venus::Task)

The startup method can be overridden and returns the invocant. This method is called by "execute" automatically after "prepare" and before "handler", and is passed the result of "parsed" in Venus::Cli.

Since 2.91

startup example 1
  # given: synopsis

  package main;

  my $startup = $task->startup({});

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

system

  system(string @args) (Venus::Task)

The system method attempts to make a "system" in perlfunc call and returns the invocant. If the system call is unsuccessful an error is thrown.

Since 2.91

system example 1
  # given: synopsis

  package main;

  my $system = $task->system($^X, '-V');

  # bless({...},  'Example')
system example 2
  # given: synopsis

  package main;

  my $system = $task->system('/path/to/nowhere');

  # Exception! (isa Example::Error) (see error_on_system_call)

test

  test(string $type, string $name) (any)

The test method validates the values for the arg or opt specified and returns the value(s) associated. This method dispatches to "test" in Venus::Cli.

Since 3.10

test example 1
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new(['--help']);

  my ($help) = $task->prepare->test('opt', 'help');

  # true
test example 2
  package Example;

  use base 'Venus::Task';

  sub opts {

    return {
      help => {
        type => 'string',
        help => 'Display help',
        alias => ['h'],
      },
    }
  }

  package main;

  my $task = Example->new(['--help']);

  my ($help) = $task->prepare->test('opt', 'help');

  # Exception! (isa Venus::Cli::Error) (see error_on_arg_validation)

  # Invalid option: help: received (undef), expected (string)

usage

  usage() (Venus::Task)

The usage method exits the program with the exit code 1 after calling "log_info" with the result of "help". This method makes it easy to output the default help text and end the program if some condition isn't met.

Since 2.91

usage example 1
  # given: synopsis

  package main;

  my $usage = $task->usage;

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

ERRORS

This package may raise the following errors:

error: error_on_system_call

This package may raise an error_on_system_call exception.

example 1

  # given: synopsis;

  my $input = {
    throw => 'error_on_system_call',
    args => ['/path/to/nowhere', 'arg1', 'arg2'],
    error => $?,
  };

  my $error = $task->catch('error', $input);

  # my $name = $error->name;

  # "on_system_call"

  # my $message = $error->render;

  # "Can't make system call \"/path/to/nowhere arg1 arg2\": $?"

  # my $args = $error->stash('args');

  # []

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.