App-Easer
view release on metacpan or search on metacpan
- Fix documentation for using residual_args, addresses GH #8
https://github.com/polettix/App-Easer/issues/8
- Fix automatic truncation of options with hyphens, addresses GH #9
https://github.com/polettix/App-Easer/issues/9
- Remove bug in using Params::Validate, addresses GH #11
https://github.com/polettix/App-Easer/issues/11, still no test.
- Allow for shorter help message via "usage", addresses GH #12
https://github.com/polettix/App-Easer/issues/12
- Improve documentation and user interface for options with transmit=>1,
addresses GH #13 https://github.com/polettix/App-Easer/issues/13
- Add documentation for "sources" callbacks, addresses GH #14
https://github.com/polettix/App-Easer/issues/14
- Fix using the right name when specified and different from getopt,
addresses GH #15 https://github.com/polettix/App-Easer/issues/15
- Fix help message for multi-valued defaults
- Fix detecting sub-commands with registered stuff (used in bundling)
2.007001 2023-03-11 15:20:07 CET
- Ensure consistent listing of sub-commands when they are auto-loaded from
modules in @INC via prefixes.
docs/docs/15-tutorial-splitting.md view on Meta::CPAN
Alas, life is not always that easy, and in many cases we might end up in
the need to cope with more complicated stuff. In this cases, a good
strategy is to break the problem down and try to address the different
parts one by one.
This breaking, sometimes, is meant *almost* phisically. I mean, it's
good to *break* the code into multiple files, so that we can concentrate
on one or another aspect at any time.
Depending on the style of implementation, this might be done by setting
up small execution callbacks towards more generic libraries, or calling
stuff in those libraries directly. At the end of the day, it's a matter
of size and preferences.
For this reason, in this tutorial we will try to break the `tudu`
application down in many different sub-modules, possibly in anticipation
that, one day, they will grow independently big.
## The main program
[App::Easer][] allows us to keep the very minimum inside the main
lib/App/Easer/Tutorial/V2_008.pod view on Meta::CPAN
[2024/09/07 16:34:49] [ INFO] this is INFO
What's happening?
The C<commit> callback set in the parent is run immediately after
options collections is completed I<in the parent>. At this stage, the
program has not seen the option's value in the child yet. As a result,
it uses whatever it has at that stage, i.e. the default C<info> value.
To address this specific issue, C<final_commit> comes to the rescue. In
the default arrangement, I<all> C<final_commit> callbacks are called in
reverse order from the chosen leaf command up to the command root,
immediately after the leaf command has completed collecting options.
Let's try it out:
# THIS PROGRAM DOES NOT WORK AS INTENDED TOO (YET)
#!/usr/bin/env perl
use v5.24;
use warnings;
use English;
lib/App/Easer/Tutorial/V2_008.pod view on Meta::CPAN
the command's object instance and consume the behaviour from there.
The I<downside> of this approach is that you need to implement your main
command as a I<class> instead of a hash definition like every example
seen so far. So while definitely possible, you might not know (yet) how
to do it.
=head3 Use a common base via C<hashy_class>
Although every command/sub-command definition seen in the example so far
has been provided as a simple hash reference full of keys and callbacks,
we've already seen that each command in a command chain is eventually
instantiated as a class object.
Each of these objects are normally instances of class
C<App::Easer::V2::Command>, but they need not be. By setting key
C<hashy_class> in the command's definition to a different class...
that's what will be used eventually.
This means that you might define a class derived from
C<App::Easer::V2::Command> and add the shared behaviour there; each
lib/App/Easer/Tutorial/V2_008.pod view on Meta::CPAN
So one alternative is to encapsulate common behaviours in one or more
object instances, then save them as configuration options that are set
in the leaf configuration using method C<leaf> to retrieve it (e.g. from
the root command) and method C<set_config> to set the object.
=head4 Use shared state
If your application is small(ish) and defined in a single hash as all
eexamples so far, it's still possible to use global variables or lexical
variables accessible from all callbacks, like this:
my $shared_object = My::Class->new(...);
my $app = {
...
execute => sub ($self) {
$shared_object->do_this;
...
};
lib/App/Easer/V2.pm view on Meta::CPAN
if (my $next = $ssources->{next}) {
my @csources =
ref($next) eq 'ARRAY' ? $next->@*
: ref($next) eq 'CODE' ? $next->($child)
: Carp::confess(); # no clue
$csources->{current} = \@csources;
}
}
}
# propagate pre-execute callbacks down the line
$child->pre_execute_schedule($self->pre_execute);
return $child;
}
# transform one or more children "hints" into instances.
sub inflate_children ($self, @hints) {
my $hashy = $self->hashy_class;
map {
my $child = $_;
lib/App/Easer/V2.pod view on Meta::CPAN
in the new L</Sources as hash reference> way of setting C<sources>,
after the final roundup of options done by C<final_collect>, the
C<final_commit> method/callback is executed.
By default, this triggers calling it all up the commands ladder, i.e.
from the leaf command that will be executed up to the root command. This
allows setting "final configurations" (like a logger) in the
C<final_commit> method of the topmost command, once and for all.
It is anyway possible to set callbacks or override the method at each
intermediate or at the leaf level, of course. In this case, the return
value of the method/callback will be used to determine whether to
continue up the ladder or not; I<true> values will continue the call
chain, I<false> values will interrupt it.
It's also possible to break the chain of calls by setting the key to a
I<false> value.
It MUST be considered that the method is specific to each command, which
usually does not have an I<updated> view of the whole configuration,
( run in 0.589 second using v1.01-cache-2.11-cpan-8d75d55dd25 )