App-Easer

 view release on metacpan or  search on metacpan

docs/docs/15-tutorial-splitting.md  view on Meta::CPAN

```

For simplicity, we're exporting *all* subs.

## Moving a command, basic

Let's start taking a look at the command modules, beginning with the one
for the `done` sub-command:

```perl
package MuDu::Command::Done;
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';

use MuDu::Utils;

sub spec {
   return {
      help        => 'mark a task as completed',
      description => 'Archive a task as completed',
      supports    => [qw< done tick yay >],
      execute     => \&execute,
   }
}

sub execute ($m, $config, $args) { move_task($config, $args, 'done') }

1;
```

It's basically taking the command specification from the old global
hash, and putting it inside the `spec` function. The implementation in
`execute` is then linked directly, by taking a reference to it.


## Need a different style?

People used to other systems might prefer to have a different functions
for the different attributes inside the specification hash, like having
a sub for `help`, one for `description`, etc.

This can be easily accomplished by using a small helper function, put in
`MuDu::Utils` so that's automatically imported:

```perl
sub autospec ($package, %direct) {
   for my $key (qw< description help options supports >) {
      next if exists $direct{$key};
      my $sub = $package->can($key) or next;
      $direct{$key} = $sub->();
   }
   $direct{execute} //= $package;
   return \%direct;
}
```

The `execute` key is (conditionally) set to the package name. When
provided with a package name, the resolution process in [App::Easer][]
looks for a sub called `execute` inside that package, so it will suffice
to call our command implementation `sub execute`.

The specific way `autospec` is implemented (i.e. accepting an input hash
`%direct`) allows us to adopt different degrees of shifting stuff from
the hash to the functions. As an example, we go full-on with the
implementation for sub-command `add`:

```perl
package MuDu::Command::Add;
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use POSIX 'strftime';

use MuDu::Utils;

sub spec { __PACKAGE__->autospec() }
sub help        { return 'add a task' }
sub description { return 'Add a task, optionally setting it as waiting' }
sub supports    { return [qw< add new post >] }
sub options {
   return [
      {
         help   => 'add the tasks as waiting',
         getopt => 'waiting|w!'
      },
      {
         help   => 'set the editor for adding the task, if needed',
         getopt => 'editor|visual|e=s',
         environment => 'VISUAL',
         default     => 'vi',
      }
   ];
}
sub execute ($main, $config, $args) {
   my $id = strftime('%Y%m%d-%H%M%S', localtime);
   my $category = $config->{waiting} ? 'waiting' : 'ongoing';
   my $hint = path($config->{basedir})->child($category, $id);
   my $target = add_file($config, $hint, '');
   if ($args->@*) {
      $target->spew_utf8(join(' ', $args->@*) . "\n");
      return 0;
   }
   return 0 if edit_file($config, $target) && length get_title($target);
   $target->remove if -e $target;
   fatal("bailing out creating new task");
}

1;
```

As we can see, the `spec` function is implemented to call `autospec`,
this time only passing the `__PACKAGE__` name as the first parameter.

In sub-command `cat`, instead, we can opt for a midway and partially use
the hash input parameter for `autospec` and part the functions:

```perl
package MuDu::Command::Cat;



( run in 2.237 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )