File Coverage

blib/lib/Bot/Training.pm
Criterion Covered Total %
statement 28 88 31.8
branch 0 22 0.0
condition 0 5 0.0
subroutine 10 16 62.5
pod n/a
total 38 131 29.0


line stmt bran cond sub pod time code
1             package Bot::Training;
2             BEGIN {
3 1     1   17446 $Bot::Training::VERSION = '0.04';
4             }
5              
6 1     1   38 use 5.010;
  1         4  
  1         43  
7 1     1   1077 use autodie qw(open close);
  1         33662  
  1         6  
8 1     1   1718 use Any::Moose;
  1         127260  
  1         9  
9             use Module::Pluggable (
10 1         12 search_path => [ 'Bot::Training' ],
11             except => [ 'Bot::Training::Plugin' ],
12 1     1   3152 );
  1         22223  
13 1     1   101 use List::Util qw< first >;
  1         3  
  1         183  
14 1     1   2251 use namespace::clean -except => [ qw< meta plugins > ];
  1         45196  
  1         12  
15              
16             with any_moose('X::Getopt::Dashes');
17              
18             has help => (
19             traits => [ qw/ Getopt / ],
20             cmd_aliases => 'h',
21             cmd_flag => 'help',
22             isa => 'Bool',
23             is => 'ro',
24             default => 0,
25             documentation => 'This help message',
26             );
27              
28             has _go_version => (
29             traits => [ qw/ Getopt / ],
30             cmd_aliases => 'v',
31             cmd_flag => 'version',
32             documentation => 'Print version and exit',
33             isa => 'Bool',
34             is => 'ro',
35             );
36              
37             has _go_list => (
38             traits => [ qw/ Getopt / ],
39             cmd_aliases => 'l',
40             cmd_flag => 'list',
41             documentation => 'List the known Bot::Training files. Install Task::Bot::Training to get them all',
42             isa => 'Bool',
43             is => 'ro',
44             );
45              
46             has _go_file => (
47             traits => [ qw/ Getopt / ],
48             cmd_aliases => 'f',
49             cmd_flag => 'file',
50             documentation => 'The file to retrieve. Matched case-insensitively against Bot::Training plugins',
51             isa => 'Str',
52             is => 'ro',
53             );
54              
55             sub _new_class {
56 0     0     my ($self, $class) = @_;
57              
58 0           my $pkg;
59 0 0         if ($class =~ m[^\+(?<custom_plugin>.+)$]) {
60 1     1   2914 $pkg = $+{custom_plugin};
  1         1386  
  1         708  
  0            
61             } else {
62             # Be fuzzy about includes, e.g. Training::Test, Test or test is OK
63 0     0     $pkg = first { / : $class /ix }
64 0           sort { length $a <=> length $b }
  0            
65             $self->plugins;
66              
67 0 0         unless ($pkg) {
68 0           local $" = ', ';
69 0           my @plugins = $self->plugins;
70 0           die "Couldn't find a class name matching '$class' in plugins '@plugins'";
71             }
72             }
73              
74 0 0         if (Any::Moose::moose_is_preferred()) {
75 0           require Class::MOP;
76 0           eval { Class::MOP::load_class($pkg) };
  0            
77             } else {
78 0           eval qq[require $pkg];
79             }
80 0 0         die $@ if $@;
81              
82 0           return $pkg->new;
83             }
84              
85             sub file {
86 0     0     my ($self, $fuzzy) = @_;
87              
88 0           return $self->_new_class($fuzzy);
89              
90             }
91              
92             sub run {
93 0     0     my ($self) = @_;
94              
95 0 0         if ($self->_go_version) {
96             # Munging strictness because we don't have a version from a
97             # Git checkout. Dist::Zilla provides it.
98 1     1   10 no strict 'vars';
  1         2  
  1         1040  
99 0   0       my $version = $VERSION // 'dev-git';
100              
101 0           say "bot-training $version";
102 0           return;
103             }
104              
105 0 0         if ($self->_go_list) {
106 0           my @plugins = $self->plugins;
107 0 0         if (@plugins) {
108 0           say for @plugins;
109             } else {
110 0           say "No plugins loaded. Install Task::Bot::Training";
111 0           return 1;
112             }
113             }
114            
115 0 0         if ($self->_go_file) {
116 0           my $trn = $self->file( $self->_go_file );;
117 0           open my $fh, "<", $trn->file;
118 0           print while <$fh>;
119 0           close $fh;
120             }
121              
122             }
123              
124             # --i--do-not-exist
125 0     0     sub _getopt_spec_exception { goto &_getopt_full_usage }
126              
127             # --help
128             sub _getopt_full_usage {
129 0     0     my ($self, $usage, $plain_str) = @_;
130              
131             # If called from _getopt_spec_exception we get "Unknown option: foo"
132 0 0         my $warning = ref $usage eq 'ARRAY' ? $usage->[0] : undef;
133              
134 0           my ($use, $options) = do {
135             # $plain_str under _getopt_spec_exception
136 0   0       my $out = $plain_str // $usage->text;
137              
138             # The default getopt order sucks, use reverse sort order
139 0           chomp(my @out = split /^/, $out);
140 0           my $opt = join "\n", sort { $b cmp $a } @out[1 .. $#out];
  0            
141 0           ($out[0], $opt);
142             };
143 0           my $synopsis = do {
144 0           require Pod::Usage;
145 0           my $out;
146 0           open my $fh, '>', \$out;
147              
148 1     1   103 no warnings 'once';
  1         2  
  1         516  
149              
150 0           my $hailo = File::Spec->catfile($Hailo::Command::HERE_MOMMY, 'hailo');
151             # Try not to fail on Win32 or other odd systems which might have hailo.pl not hailo
152 0 0         $hailo = ((glob("$hailo*"))[0]) unless -f $hailo;
153 0           Pod::Usage::pod2usage(
154             -input => $hailo,
155             -sections => 'SYNOPSIS',
156             -output => $fh,
157             -exitval => 'noexit',
158             );
159 0           close $fh;
160              
161 0           $out =~ s/\n+$//s;
162 0           $out =~ s/^Usage:/examples:/;
163              
164 0           $out;
165             };
166              
167             # Unknown option provided
168 0 0         print $warning if $warning;
169              
170 0           print <<"USAGE";
171             $use
172             $options
173             USAGE
174              
175 0           say "\n", $synopsis;
176              
177 0           exit 1;
178             }
179              
180             __PACKAGE__->meta->make_immutable;
181              
182             =encoding utf8
183              
184             =head1 NAME
185              
186             Bot::Training - Plain text training material for bots like L<Hailo> and L<AI::MegaHAL>
187              
188             =head1 SYNOPSIS
189              
190             use Bot::Training;
191             use File::Slurp qw< slurp >;
192              
193             my $bt = Bot::Training->new;
194              
195             # Plugins I know about. Install Task::Bot::Training for more:
196             my @plugins = $bt->plugins
197              
198             # Get the plugin object of a .trn file (which is just a plain text
199             # file). These all work just as well:
200             my $hal = $bt->file('megahal');
201             my $hal = $bt->file('MegaHAL');
202             my $hal = $bt->file('Bot::Training::MegaHAL');
203              
204             # Get all lines in the file with File::Slurp:
205             my @test = split /\n/, slurp($hal->file);
206              
207             =head1 DESCRIPTION
208              
209             Markov bots like L<Hailo> and L<AI::MegaHAL> are fun. But to get them
210             working you either need to train them on existing training material or
211             make your own.
212              
213             This module provides a pluggable way to install already existing
214             training files via the CPAN. It also comes with a command-line
215             interface called C<bot-training>.
216              
217             =head1 AUTHOR
218              
219             E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org>
220              
221             =head1 LICENSE AND COPYRIGHT
222              
223             Copyright 2010 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org>
224              
225             This program is free software, you can redistribute it and/or modify
226             it under the same terms as Perl itself.
227              
228             =cut