App-Easer

 view release on metacpan or  search on metacpan

lib/App/Easer/V2.pm  view on Meta::CPAN

   map { $self->_auto_child($_, $inflate) } qw< help commands tree >;
}

sub auto_commands ($self) { return $self->_auto_child('commands', 1) }

sub auto_help ($self) { return $self->_auto_child('help', 1) }

sub auto_tree ($self) { return $self->_auto_child('tree', 1) }

sub run_help ($self, $mode = 'help') { $self->auto_help->run($mode) }

sub full_help_text ($s, @as) { $s->auto_help->collect_help_for($s, @as) }

sub load_module ($sop, $module) {
   my $file = "$module.pm" =~ s{::}{/}grmxs;
   eval { require $file } or Carp::confess("module<$module>: $EVAL_ERROR");
   return $module;
}

# Gets a specification like "Foo::Bar::baz" and returns a reference to
# sub "baz" in "Foo::Bar". If no package name is set, returns a
# reference to a sub in the package of $self. FIXME document properly
sub ref_to_sub ($self, $spec) {
   Carp::confess("undefined specification in ref_to_sub")
     unless defined $spec;
   return $spec if ref($spec) eq 'CODE';
   my ($class, $function) =
     ref($spec) eq 'ARRAY'
     ? $spec->@*
     : $spec =~ m{\A (?: (.*) :: )? (.*) \z}mxs;
   return $self->can($function) unless length($class // '');
   $self->load_module($class)   unless $class->can($function);
   return $class->can($function);
} ## end sub ref_to_sub

sub instantiate ($sop, $class, @args) {
   $sop->load_module($class) unless $class->can('new');
   return $class->new(@args);
}

sub _reparent ($self, $child) {
   $child->parent($self);
   $self->child($child); # saves a weak reference to $child

   # 2024-08-27 propagate sources configurations
   if (! ref($child->_sources)) { # still default, my need to set it
      my ($first, @rest) = $self->sources;
      if (ref($first) eq 'REF') {  # new approach, propagate
         my $ssources = $$first;
         $child->_sources(my $csources = { $ssources->%* });
         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 = $_;
      if (!blessed($child)) {    # actually inflate it
         $child =
             ref($child) eq 'ARRAY' ? $self->instantiate($child->@*)
           : ref($child) eq 'HASH'  ? $self->instantiate($hashy, $child)
           :                          $self->instantiate($child);
      } ## end if (!blessed($child))
      $self->_reparent($child);  # returns $child
   } grep { defined $_ } @hints;
} ## end sub inflate_children

# fallback mechanism when finding a child, relies on fallback_to.
sub fallback ($self) {
   my $fto = $self->fallback_to;
   return $fto if !defined($fto) || $fto !~ m{\A(?: 0 | [1-9]\d* )\z};
   my @children = $self->list_children;
   return $children[$fto] if $fto <= $#children;
   return undef;
} ## end sub fallback ($self)

# execute what's set as the execute sub in the slot
sub execute ($self) {
   my $spec = $self->_rw or die "nothing to search for execution\n";
   my $sub = $self->ref_to_sub($spec) or die "nothing to execute\n";
   return $sub->($self);
}

sub pre_execute_schedule ($self, @specs) {
   if (my $spec = $self->_rw) {
      my $sub = $self->ref_to_sub($spec) or die "nothing for pre_execute_schedule\n";
      return $sub->($self, @specs);
   }

   # default approach is to append to the current ones
   $self->pre_execute([$self->pre_execute, @specs]);
   return $self;
}

sub pre_execute_run ($self) {
   if (my $spec = $self->_rw) {
      my $sub = $self->ref_to_sub($spec) or die "nothing to pre-execute\n";
      return $sub->($self);
   }

   # default is to run 'em all
   for my $spec ($self->pre_execute) {
      my $sub = $self->ref_to_sub($spec) or die "nothing to pre-execute\n";
      $sub->($self);
   }
   return $self;
}



( run in 0.375 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )