| Filename | /usr/local/share/perl/5.18.2/App/Cmd/Setup.pm |
| Statements | Executed 51 statements in 2.48ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.43ms | 37.8ms | App::Cmd::Setup::BEGIN@72 |
| 1 | 1 | 1 | 1.19ms | 1.26ms | App::Cmd::Setup::BEGIN@73 |
| 1 | 1 | 1 | 654µs | 970µs | App::Cmd::Setup::BEGIN@77 |
| 1 | 1 | 1 | 406µs | 454µs | App::Cmd::Setup::BEGIN@74 |
| 1 | 1 | 1 | 42µs | 400µs | App::Cmd::Setup::_make_app_class |
| 1 | 1 | 1 | 20µs | 33µs | PONAPI::CLI::BEGIN@1 |
| 1 | 1 | 1 | 8µs | 8µs | App::Cmd::Setup::_make_x_isa_y |
| 1 | 1 | 1 | 8µs | 274µs | App::Cmd::Setup::BEGIN@82 |
| 1 | 1 | 1 | 8µs | 18µs | App::Cmd::Setup::BEGIN@167 |
| 1 | 1 | 1 | 8µs | 16µs | App::Cmd::Setup::BEGIN@80 |
| 1 | 1 | 1 | 5µs | 8µs | PONAPI::CLI::BEGIN@2 |
| 4 | 2 | 1 | 5µs | 5µs | App::Cmd::Setup::__ANON__[:114] |
| 1 | 1 | 1 | 3µs | 3µs | App::Cmd::Setup::BEGIN@75 |
| 3 | 1 | 1 | 3µs | 3µs | App::Cmd::Setup::__ANON__[:142] |
| 1 | 1 | 1 | 2µs | 2µs | App::Cmd::Setup::BEGIN@76 |
| 1 | 1 | 1 | 2µs | 2µs | App::Cmd::Setup::import |
| 1 | 1 | 1 | 1µs | 1µs | App::Cmd::Setup::_command_base_class |
| 1 | 1 | 1 | 800ns | 800ns | App::Cmd::Setup::_app_base_class |
| 0 | 0 | 0 | 0s | 0s | App::Cmd::Setup::_make_command_class |
| 0 | 0 | 0 | 0s | 0s | App::Cmd::Setup::_make_plugin_class |
| 0 | 0 | 0 | 0s | 0s | App::Cmd::Setup::_plugin_base_class |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | 2 | 20µs | 2 | 46µs | # spent 33µs (20+13) within PONAPI::CLI::BEGIN@1 which was called:
# once (20µs+13µs) by PONAPI::CLI::BEGIN@5 at line 1 # spent 33µs making 1 call to PONAPI::CLI::BEGIN@1
# spent 13µs making 1 call to strict::import |
| 2 | 2 | 53µs | 2 | 11µs | # spent 8µs (5+3) within PONAPI::CLI::BEGIN@2 which was called:
# once (5µs+3µs) by PONAPI::CLI::BEGIN@5 at line 2 # spent 8µs making 1 call to PONAPI::CLI::BEGIN@2
# spent 3µs making 1 call to warnings::import |
| 3 | package App::Cmd::Setup; | ||||
| 4 | 1 | 500ns | $App::Cmd::Setup::VERSION = '0.330'; | ||
| 5 | # ABSTRACT: helper for setting up App::Cmd classes | ||||
| 6 | |||||
| 7 | #pod =head1 OVERVIEW | ||||
| 8 | #pod | ||||
| 9 | #pod App::Cmd::Setup is a helper library, used to set up base classes that will be | ||||
| 10 | #pod used as part of an App::Cmd program. For the most part you should refer to | ||||
| 11 | #pod L<the tutorial|App::Cmd::Tutorial> for how you should use this library. | ||||
| 12 | #pod | ||||
| 13 | #pod This class is useful in three scenarios: | ||||
| 14 | #pod | ||||
| 15 | #pod =begin :list | ||||
| 16 | #pod | ||||
| 17 | #pod = when writing your App::Cmd subclass | ||||
| 18 | #pod | ||||
| 19 | #pod Instead of writing: | ||||
| 20 | #pod | ||||
| 21 | #pod package MyApp; | ||||
| 22 | #pod use base 'App::Cmd'; | ||||
| 23 | #pod | ||||
| 24 | #pod ...you can write: | ||||
| 25 | #pod | ||||
| 26 | #pod package MyApp; | ||||
| 27 | #pod use App::Cmd::Setup -app; | ||||
| 28 | #pod | ||||
| 29 | #pod The benefits of doing this are mostly minor, and relate to sanity-checking your | ||||
| 30 | #pod class. The significant benefit is that this form allows you to specify | ||||
| 31 | #pod plugins, as in: | ||||
| 32 | #pod | ||||
| 33 | #pod package MyApp; | ||||
| 34 | #pod use App::Cmd::Setup -app => { plugins => [ 'Prompt' ] }; | ||||
| 35 | #pod | ||||
| 36 | #pod Plugins are described in L<App::Cmd::Tutorial> and L<App::Cmd::Plugin>. | ||||
| 37 | #pod | ||||
| 38 | #pod = when writing abstract base classes for commands | ||||
| 39 | #pod | ||||
| 40 | #pod That is: when you write a subclass of L<App::Cmd::Command> that is intended for | ||||
| 41 | #pod other commands to use as their base class, you should use App::Cmd::Setup. For | ||||
| 42 | #pod example, if you want all the commands in MyApp to inherit from MyApp::Command, | ||||
| 43 | #pod you may want to write that package like this: | ||||
| 44 | #pod | ||||
| 45 | #pod package MyApp::Command; | ||||
| 46 | #pod use App::Cmd::Setup -command; | ||||
| 47 | #pod | ||||
| 48 | #pod Do not confuse this with the way you will write specific commands: | ||||
| 49 | #pod | ||||
| 50 | #pod package MyApp::Command::mycmd; | ||||
| 51 | #pod use MyApp -command; | ||||
| 52 | #pod | ||||
| 53 | #pod Again, this form mostly performs some validation and setup behind the scenes | ||||
| 54 | #pod for you. You can use C<L<base>> if you prefer. | ||||
| 55 | #pod | ||||
| 56 | #pod = when writing App::Cmd plugins | ||||
| 57 | #pod | ||||
| 58 | #pod L<App::Cmd::Plugin> is a mechanism that allows an App::Cmd class to inject code | ||||
| 59 | #pod into all its command classes, providing them with utility routines. | ||||
| 60 | #pod | ||||
| 61 | #pod To write a plugin, you must use App::Cmd::Setup. As seen above, you must also | ||||
| 62 | #pod use App::Cmd::Setup to set up your App::Cmd subclass if you wish to consume | ||||
| 63 | #pod plugins. | ||||
| 64 | #pod | ||||
| 65 | #pod For more information on writing plugins, see L<App::Cmd::Manual> and | ||||
| 66 | #pod L<App::Cmd::Plugin>. | ||||
| 67 | #pod | ||||
| 68 | #pod =end :list | ||||
| 69 | #pod | ||||
| 70 | #pod =cut | ||||
| 71 | |||||
| 72 | 2 | 455µs | 1 | 37.8ms | # spent 37.8ms (2.43+35.4) within App::Cmd::Setup::BEGIN@72 which was called:
# once (2.43ms+35.4ms) by PONAPI::CLI::BEGIN@5 at line 72 # spent 37.8ms making 1 call to App::Cmd::Setup::BEGIN@72 |
| 73 | 2 | 495µs | 1 | 1.26ms | # spent 1.26ms (1.19+65µs) within App::Cmd::Setup::BEGIN@73 which was called:
# once (1.19ms+65µs) by PONAPI::CLI::BEGIN@5 at line 73 # spent 1.26ms making 1 call to App::Cmd::Setup::BEGIN@73 |
| 74 | 2 | 355µs | 1 | 454µs | # spent 454µs (406+48) within App::Cmd::Setup::BEGIN@74 which was called:
# once (406µs+48µs) by PONAPI::CLI::BEGIN@5 at line 74 # spent 454µs making 1 call to App::Cmd::Setup::BEGIN@74 |
| 75 | 2 | 15µs | 1 | 3µs | # spent 3µs within App::Cmd::Setup::BEGIN@75 which was called:
# once (3µs+0s) by PONAPI::CLI::BEGIN@5 at line 75 # spent 3µs making 1 call to App::Cmd::Setup::BEGIN@75 |
| 76 | 2 | 14µs | 1 | 2µs | # spent 2µs within App::Cmd::Setup::BEGIN@76 which was called:
# once (2µs+0s) by PONAPI::CLI::BEGIN@5 at line 76 # spent 2µs making 1 call to App::Cmd::Setup::BEGIN@76 |
| 77 | 2 | 380µs | 1 | 970µs | # spent 970µs (654+315) within App::Cmd::Setup::BEGIN@77 which was called:
# once (654µs+315µs) by PONAPI::CLI::BEGIN@5 at line 77 # spent 970µs making 1 call to App::Cmd::Setup::BEGIN@77 |
| 78 | |||||
| 79 | # 0.06 is needed for load_optional_class | ||||
| 80 | 3 | 51µs | 2 | 23µs | # spent 16µs (8+8) within App::Cmd::Setup::BEGIN@80 which was called:
# once (8µs+8µs) by PONAPI::CLI::BEGIN@5 at line 80 # spent 16µs making 1 call to App::Cmd::Setup::BEGIN@80
# spent 8µs making 1 call to UNIVERSAL::VERSION |
| 81 | |||||
| 82 | 1 | 6µs | 1 | 266µs | # spent 274µs (8+266) within App::Cmd::Setup::BEGIN@82 which was called:
# once (8µs+266µs) by PONAPI::CLI::BEGIN@5 at line 90 # spent 266µs making 1 call to Sub::Exporter::__ANON__[Sub/Exporter.pm:337] |
| 83 | -as => '_import', | ||||
| 84 | exports => [ qw(foo) ], | ||||
| 85 | collectors => [ | ||||
| 86 | -app => \'_make_app_class', | ||||
| 87 | -command => \'_make_command_class', | ||||
| 88 | -plugin => \'_make_plugin_class', | ||||
| 89 | ], | ||||
| 90 | 1 | 392µs | 1 | 274µs | }; # spent 274µs making 1 call to App::Cmd::Setup::BEGIN@82 |
| 91 | |||||
| 92 | # spent 2µs within App::Cmd::Setup::import which was called:
# once (2µs+0s) by PONAPI::CLI::BEGIN@5 at line 5 of lib/PONAPI/CLI.pm | ||||
| 93 | 1 | 6µs | 1 | 470µs | goto &_import; # spent 470µs making 1 call to Sub::Exporter::__ANON__[Sub/Exporter.pm:337] |
| 94 | } | ||||
| 95 | |||||
| 96 | 1 | 2µs | # spent 800ns within App::Cmd::Setup::_app_base_class which was called:
# once (800ns+0s) by App::Cmd::Setup::_make_app_class at line 109 | ||
| 97 | |||||
| 98 | # spent 400µs (42+358) within App::Cmd::Setup::_make_app_class which was called:
# once (42µs+358µs) by Sub::Exporter::__ANON__[/usr/local/share/perl/5.18.2/Sub/Exporter.pm:159] at line 151 of Sub/Exporter.pm | ||||
| 99 | 1 | 400ns | my ($self, $val, $data) = @_; | ||
| 100 | 1 | 300ns | my $into = $data->{into}; | ||
| 101 | |||||
| 102 | 1 | 300ns | $val ||= {}; | ||
| 103 | Carp::confess "invalid argument to -app setup" | ||||
| 104 | 1 | 700ns | if grep { $_ ne 'plugins' } keys %$val; | ||
| 105 | |||||
| 106 | 1 | 8µs | 1 | 2µs | Carp::confess "app setup requested on App::Cmd subclass $into" # spent 2µs making 1 call to UNIVERSAL::isa |
| 107 | if $into->isa('App::Cmd'); | ||||
| 108 | |||||
| 109 | 1 | 2µs | 2 | 9µs | $self->_make_x_isa_y($into, $self->_app_base_class); # spent 8µs making 1 call to App::Cmd::Setup::_make_x_isa_y
# spent 800ns making 1 call to App::Cmd::Setup::_app_base_class |
| 110 | |||||
| 111 | 1 | 6µs | 2 | 287µs | if ( ! Class::Load::load_optional_class( $into->_default_command_base ) ) { # spent 284µs making 1 call to Class::Load::load_optional_class
# spent 2µs making 1 call to App::Cmd::_default_command_base |
| 112 | 1 | 2µs | 1 | 1µs | my $base = $self->_command_base_class; # spent 1µs making 1 call to App::Cmd::Setup::_command_base_class |
| 113 | Sub::Install::install_sub({ | ||||
| 114 | 4 | 10µs | # spent 5µs within App::Cmd::Setup::__ANON__[/usr/local/share/perl/5.18.2/App/Cmd/Setup.pm:114] which was called 4 times, avg 1µs/call:
# 3 times (4µs+0s) by App::Cmd::_setup_command at line 34 of App/Cmd.pm, avg 1µs/call
# once (800ns+0s) by App::Cmd::plugin_search_path at line 497 of App/Cmd.pm | ||
| 115 | 1 | 4µs | 1 | 36µs | into => $into, # spent 36µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:118] |
| 116 | as => '_default_command_base', | ||||
| 117 | }); | ||||
| 118 | } | ||||
| 119 | |||||
| 120 | # TODO Check this is right. -- kentnl, 2010-12 | ||||
| 121 | # | ||||
| 122 | # my $want_plugin_base = $self->_plugin_base_class; | ||||
| 123 | 1 | 300ns | my $want_plugin_base = 'App::Cmd::Plugin'; | ||
| 124 | |||||
| 125 | 1 | 100ns | my @plugins; | ||
| 126 | 1 | 1µs | for my $plugin (@{ $val->{plugins} || [] }) { | ||
| 127 | $plugin = String::RewritePrefix->rewrite( | ||||
| 128 | { | ||||
| 129 | '' => 'App::Cmd::Plugin::', | ||||
| 130 | '=' => '' | ||||
| 131 | }, | ||||
| 132 | $plugin, | ||||
| 133 | ); | ||||
| 134 | Class::Load::load_class( $plugin ); | ||||
| 135 | unless( $plugin->isa( $want_plugin_base ) ){ | ||||
| 136 | die "$plugin is not a " . $want_plugin_base; | ||||
| 137 | } | ||||
| 138 | push @plugins, $plugin; | ||||
| 139 | } | ||||
| 140 | |||||
| 141 | Sub::Install::install_sub({ | ||||
| 142 | 3 | 8µs | # spent 3µs within App::Cmd::Setup::__ANON__[/usr/local/share/perl/5.18.2/App/Cmd/Setup.pm:142] which was called 3 times, avg 967ns/call:
# 3 times (3µs+0s) by App::Cmd::_setup_command at line 42 of App/Cmd.pm, avg 967ns/call | ||
| 143 | 1 | 3µs | 1 | 23µs | into => $into, # spent 23µs making 1 call to Sub::Install::__ANON__[Sub/Install.pm:118] |
| 144 | as => '_plugin_plugins', | ||||
| 145 | }); | ||||
| 146 | |||||
| 147 | 1 | 6µs | return 1; | ||
| 148 | } | ||||
| 149 | |||||
| 150 | 1 | 5µs | # spent 1µs within App::Cmd::Setup::_command_base_class which was called:
# once (1µs+0s) by App::Cmd::Setup::_make_app_class at line 112 | ||
| 151 | |||||
| 152 | sub _make_command_class { | ||||
| 153 | my ($self, $val, $data) = @_; | ||||
| 154 | my $into = $data->{into}; | ||||
| 155 | |||||
| 156 | Carp::confess "command setup requested on App::Cmd::Command subclass $into" | ||||
| 157 | if $into->isa('App::Cmd::Command'); | ||||
| 158 | |||||
| 159 | $self->_make_x_isa_y($into, $self->_command_base_class); | ||||
| 160 | |||||
| 161 | return 1; | ||||
| 162 | } | ||||
| 163 | |||||
| 164 | # spent 8µs within App::Cmd::Setup::_make_x_isa_y which was called:
# once (8µs+0s) by App::Cmd::Setup::_make_app_class at line 109 | ||||
| 165 | 1 | 600ns | my ($self, $x, $y) = @_; | ||
| 166 | |||||
| 167 | 2 | 164µs | 2 | 29µs | # spent 18µs (8+10) within App::Cmd::Setup::BEGIN@167 which was called:
# once (8µs+10µs) by PONAPI::CLI::BEGIN@5 at line 167 # spent 18µs making 1 call to App::Cmd::Setup::BEGIN@167
# spent 10µs making 1 call to strict::unimport |
| 168 | 1 | 10µs | push @{"$x\::ISA"}, $y; | ||
| 169 | } | ||||
| 170 | |||||
| 171 | sub _plugin_base_class { 'App::Cmd::Plugin' } | ||||
| 172 | sub _make_plugin_class { | ||||
| 173 | my ($self, $val, $data) = @_; | ||||
| 174 | my $into = $data->{into}; | ||||
| 175 | |||||
| 176 | Carp::confess "plugin setup requested on App::Cmd::Plugin subclass $into" | ||||
| 177 | if $into->isa('App::Cmd::Plugin'); | ||||
| 178 | |||||
| 179 | Carp::confess "plugin setup requires plugin configuration" unless $val; | ||||
| 180 | |||||
| 181 | $self->_make_x_isa_y($into, $self->_plugin_base_class); | ||||
| 182 | |||||
| 183 | # In this special case, exporting everything by default is the sensible thing | ||||
| 184 | # to do. -- rjbs, 2008-03-31 | ||||
| 185 | $val->{groups} = [ default => [ -all ] ] unless $val->{groups}; | ||||
| 186 | |||||
| 187 | my @exports; | ||||
| 188 | for my $pair (@{ Data::OptList::mkopt($val->{exports}) }) { | ||||
| 189 | push @exports, $pair->[0], ($pair->[1] || \'_faux_curried_method'); | ||||
| 190 | } | ||||
| 191 | |||||
| 192 | $val->{exports} = \@exports; | ||||
| 193 | |||||
| 194 | Sub::Exporter::setup_exporter({ | ||||
| 195 | %$val, | ||||
| 196 | into => $into, | ||||
| 197 | as => 'import_from_plugin', | ||||
| 198 | }); | ||||
| 199 | |||||
| 200 | return 1; | ||||
| 201 | } | ||||
| 202 | |||||
| 203 | 1 | 3µs | 1; | ||
| 204 | |||||
| 205 | __END__ |