App-Easer
view release on metacpan or search on metacpan
docs/docs/10-tutorial-base.md view on Meta::CPAN
## Boilerplate and high level structure
Let's start with setting up the skeleton for our application:
```perl
#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use App::Easer 'run';
my $application = {
factory => {prefixes => {'#' => 'TuDu#'}},
configuration => {
'auto-leaves' => 1,
'help-on-stderr' => 1,
},
commands => {
MAIN => { ... },
dump => { ... },
list => { ... },
show => { ... },
cat => { ... },
add => { ... },
edit => { ... },
done => { ... },
wait => { ... },
resume => { ... },
remove => { ... },
},
};
exit run($application, [@ARGV]);
package TuDu;
use Path::Tiny 'path';
use POSIX 'strftime';
...
```
The `factory` top level configuration lays the ground for putting the
implementation inside a separate package `TuDu`. That particular prefix
setting is used as follows:
- a name like `#foobar` will be turned into `TuDu#foobar`;
- this will be resolved into function `TuDu::foobar` (i.e. function
`foobar` inside package `TuDu`.
As a result, we have a shortcut to point towards functions inside the
`TuDu` package for our implementations.
We are setting a couple of high-level configurations:
- `auto-leaves`: every command without explicit children will be treated
as a leaf command, so it will not get a `help` and a `commands`
sub-commands;
- `help-on-stderr`: help messages (from `help` and `commands`) will be
printed on standard error instead of standard output. This makes it
more difficult to pipe them through a pager (like `more` or `less`),
but avoids that the help messages might be accidentally considered
part of the "real" output of the command.
The rest of the `$application` hash reference is initialized with a
skeleton of all the sub-commands that we aim to support. The structure
is pretty flat - all "real" sub-commands are in fact children to the
`MAIN` entry point.
## Setting the MAIN entry point
Let's flesh out the `MAIN` entry point. This will collect the *global*
configuration options (e.g. where the configuration file is placed,
where to place the tasks, etc.) as well as doing some housekeeping to
ease the work of the "real" commands:
```perl
# inside hash at $application->{commands}:
MAIN => {
help => 'to-do application',
description => 'A simple to-do application',
children => [qw< list show cat add edit done wait resume remove >],
sources => '+SourcesWithFiles',
'config-files' => ["$ENV{HOME}/.tudu.conf", '/etc/tudu.conf'],
options => [
{
help => 'path to the configuration file',
getopt => 'config|c=s',
environment => 'TUDU_CONFIG',
},
{
help => 'base directory where tasks are kept',
getopt => 'basedir|dir|d=s',
environment => 'TUDU_BASEDIR',
default => "$ENV{HOME}/.tudu",
},
{
help => 'max number of attempts to find non-colliding id',
getopt => 'attempts|max-attempts|M=i',
default => 9,
},
],
commit => '#ensure_basedir',
},
```
The `help` and `descriptions` are useful ways to provide clues to the
users about how to use this command. Of the two, `help` is used where a
concise description is needed, while `description` is used in the help
page regarding the command itself, so it's generally more verbose.
As anticipated, `children` points to all sub-commands, because this
specific application has a flat hierarchy. For fancier hierarchies,
[Defining commands hierarchy][] is the tutorial to look for.
The next section deals with managing input options. The `sources`
key points to `+SourcesWithFiles`, which means that the following
sources will be used for gathering options, in order:
( run in 0.548 second using v1.01-cache-2.11-cpan-39bf76dae61 )