package Venus::Cli; use 5.018; use strict; use warnings; use Venus::Class 'attr', 'base', 'with'; base 'Venus::Kind::Utility'; with 'Venus::Role::Optional'; require POSIX; # ATTRIBUTES attr 'init'; attr 'path'; attr 'args'; attr 'data'; attr 'logs'; attr 'opts'; attr 'vars'; # BUILDERS sub build_arg { my ($self, $data) = @_; return { init => $data, }; } # DEFAULTS sub default_args { my ($self) = @_; require Venus::Args; return Venus::Args->new($self->init); } sub default_data { my ($self) = @_; require Venus::Data; return Venus::Data->new($self->path); } sub default_init { my ($self) = @_; return [@ARGV]; } sub default_logs { my ($self) = @_; require Venus::Log; return Venus::Log->new('info'); } sub default_opts { my ($self) = @_; require Venus::Opts; return Venus::Opts->new(value => $self->init, specs => $self->options); } sub default_path { my ($self) = @_; require Venus::Path; require Venus::Space; return Venus::Path->new(Venus::Space->new(ref $self)->included || $0); } sub default_vars { my ($self) = @_; require Venus::Vars; return Venus::Vars->new; } # HOOKS sub _exit { POSIX::_exit(shift); } # METHODS sub arg { my ($self, $item) = @_; return defined $item ? $self->opts->unused->[$item] : undef; } sub execute { my ($self) = @_; return $self->opt('help') ? $self->okay : $self->fail; } sub exit { my ($self, $code, $method, @args) = @_; $self->$method(@args) if $method; $code ||= 0; _exit($code); } sub fail { my ($self, $method, @args) = @_; return $self->exit(1, $method, @args); } sub help { my ($self, @data) = @_; my $content = $self->data->string(@data ? @data : ('head1', 'OPTIONS')); my ($space) = $content =~ /(^\s+)/; return (defined $space) ? $content =~ s/^$space//mgr : $content; } sub log_debug { my ($self, @data) = @_; return $self->logs->debug(@data); } sub log_error { my ($self, @data) = @_; return $self->logs->error(@data); } sub log_fatal { my ($self, @data) = @_; return $self->logs->fatal(@data); } sub log_info { my ($self, @data) = @_; return $self->logs->info(@data); } sub log_trace { my ($self, @data) = @_; return $self->logs->trace(@data); } sub log_warn { my ($self, @data) = @_; return $self->logs->warn(@data); } sub okay { my ($self, $method, @args) = @_; return $self->exit(0, $method, @args); } sub opt { my ($self, $item) = @_; return defined $item ? $self->opts->get($item) : undef; } sub options { my ($self) = @_; return ['help|h']; } 1; =head1 NAME Venus::Cli - Cli Class =cut =head1 ABSTRACT Cli Class for Perl 5 =cut =head1 SYNOPSIS package main; use Venus::Cli; my $cli = Venus::Cli->new(['example', '--help']); # $cli->program; # "/path/to/executable" # $cli->arg(0); # "example" # $cli->opt('help'); # 1 =cut =head1 DESCRIPTION This package provides a superclass and methods for providing simple yet robust command-line interfaces. =cut =head1 ATTRIBUTES This package has the following attributes: =cut =head2 args args(Args $data) (Args) The args attribute holds a L object. I> =over 4 =item args example 1 # given: synopsis package main; my $args = $cli->args; =back =cut =head2 data data(Data $data) (Data) The data attribute holds a L object. I> =over 4 =item data example 1 # given: synopsis package main; my $data = $cli->data; =back =cut =head2 init init(ArrayRef $data) (ArrayRef) The init attribute holds the "initial" raw arguments provided to the CLI, defaulting to C<[@ARGV]>, used by L and L. I> =over 4 =item init example 1 # given: synopsis package main; my $init = $cli->init; # ["example", "--help"] =back =cut =head2 logs logs(Logs $logs) (Logs) The logs attribute holds a L object. I> =over 4 =item logs example 1 # given: synopsis package main; my $logs = $cli->logs; =back =cut =head2 opts opts(Opts $opts) (Opts) The opts attribute holds a L object. I> =over 4 =item opts example 1 # given: synopsis package main; my $opts = $cli->opts; =back =cut =head2 path path(Path $data) (Path) The path attribute holds a L object, meant to represent the path of the file where the CLI executable and POD is. I> =over 4 =item path example 1 # given: synopsis package main; my $path = $cli->path; =back =cut =head2 vars vars(Vars $vars) (Vars) The vars attribute holds a L object. I> =over 4 =item vars example 1 # given: synopsis package main; my $vars = $cli->vars; =back =cut =head1 INHERITS This package inherits behaviors from: L =cut =head1 INTEGRATES This package integrates behaviors from: L =cut =head1 METHODS This package provides the following methods: =cut =head2 arg arg(Str $pos) (Str) The arg method returns the element specified by the index in the unnamed arguments list, i.e. arguments not parsed as options. I> =over 4 =item arg example 1 # given: synopsis package main; my $arg = $cli->arg; # undef =back =over 4 =item arg example 2 # given: synopsis package main; my $arg = $cli->arg(0); # "example" =back =cut =head2 execute execute() (Any) The execute method is the default entrypoint of the program and runs the application. I> =over 4 =item execute example 1 package main; use Venus::Cli; my $cli = Venus::Cli->new([]); # e.g. # sub execute { # my ($self) = @_; # # return $self->opt('help') ? $self->okay : $self->fail; # } # my $result = $cli->execute; # ... =back =over 4 =item execute example 2 package main; use Venus::Cli; my $cli = Venus::Cli->new(['--help']); # e.g. # sub execute { # my ($self) = @_; # # return $self->opt('help') ? $self->okay : $self->fail; # } # my $result = $cli->execute; # ... =back =cut =head2 exit exit(Int $code, Str|CodeRef $code, Any @args) (Any) The exit method exits the program using the exit code provided. The exit code defaults to C<0>. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments. I> =over 4 =item exit example 1 # given: synopsis package main; my $exit = $cli->exit; # () =back =over 4 =item exit example 2 # given: synopsis package main; my $exit = $cli->exit(0); # () =back =over 4 =item exit example 3 # given: synopsis package main; my $exit = $cli->exit(1); # () =back =over 4 =item exit example 4 # given: synopsis package main; # my $exit = $cli->exit(1, 'log_info', 'Something failed!'); # () =back =cut =head2 fail fail(Str|CodeRef $code, Any @args) (Any) The fail method exits the program with the exit code C<1>. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments. I> =over 4 =item fail example 1 # given: synopsis package main; my $fail = $cli->fail; # () =back =over 4 =item fail example 2 # given: synopsis package main; # my $fail = $cli->fail('log_info', 'Something failed!'); # () =back =cut =head2 help help(Str @data) (Str) The help method returns the POD found in the file specified by the L method, defaulting to the C<=head1 OPTIONS> section. I> =over 4 =item help example 1 # given: synopsis package main; my $help = $cli->help; # "" =back =over 4 =item help example 2 # given: synopsis package main; # my $help = $cli->help('head1', 'NAME'); # "Example" =back =cut =head2 log_debug log_debug(Str @data) (Log) The log_debug method logs C information. I> =over 4 =item log_debug example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_debug(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 log_error log_error(Str @data) (Log) The log_error method logs C information. I> =over 4 =item log_error example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_error(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 log_fatal log_fatal(Str @data) (Log) The log_fatal method logs C information. I> =over 4 =item log_fatal example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_fatal(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 log_info log_info(Str @data) (Log) The log_info method logs C information. I> =over 4 =item log_info example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_info(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 log_trace log_trace(Str @data) (Log) The log_trace method logs C information. I> =over 4 =item log_trace example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_trace(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 log_warn log_warn(Str @data) (Log) The log_warn method logs C information. I> =over 4 =item log_warn example 1 # given: synopsis package main; # $cli->logs->level('trace'); # my $log = $cli->log_warn(time, 'Something failed!'); # "0000000000 Something failed!" =back =cut =head2 okay okay(Str|CodeRef $code, Any @args) (Any) The okay method exits the program with the exit code C<0>. Optionally, you can dispatch before exiting by providing a method name or coderef, and arguments. I> =over 4 =item okay example 1 # given: synopsis package main; my $okay = $cli->okay; # () =back =over 4 =item okay example 2 # given: synopsis package main; # my $okay = $cli->okay('log_info', 'Something worked!'); # () =back =cut =head2 opt opt(Str $name) (Str) The opt method returns the named option specified by the L method. I> =over 4 =item opt example 1 # given: synopsis package main; my $opt = $cli->opt; # undef =back =over 4 =item opt example 2 # given: synopsis package main; my $opt = $cli->opt('help'); # 1 =back =cut =head2 options options() (ArrayRef) The options method returns the list of L definitions. I> =over 4 =item options example 1 # given: synopsis package main; my $options = $cli->options; # ['help|h'] =back =cut