File Coverage

blib/lib/Hailo/UI/ReadLine.pm
Criterion Covered Total %
statement 25 70 35.7
branch 2 16 12.5
condition 0 6 0.0
subroutine 9 12 75.0
pod 0 2 0.0
total 36 106 33.9


line stmt bran cond sub pod time code
1             package Hailo::UI::ReadLine;
2             our $AUTHORITY = 'cpan:AVAR';
3             $Hailo::UI::ReadLine::VERSION = '0.75';
4 2     2   99002 use v5.10.0;
  2         16  
5 2     2   523 use Moose;
  2         464733  
  2         16  
6 2     2   15122 use MooseX::StrictConstructor;
  2         31870  
  2         13  
7 2     2   14860 use Encode 'decode';
  2         20577  
  2         147  
8 2     2   478 use Hailo;
  2         36792  
  2         75  
9 2     2   1201 use Term::ReadLine;
  2         5289  
  2         75  
10 2     2   932 use Data::Dump 'dump';
  2         10158  
  2         205  
11 2     2   17 use namespace::clean -except => 'meta';
  2         4  
  2         35  
12              
13             with qw(Hailo::Role::Arguments
14             Hailo::Role::UI);
15              
16             sub BUILD {
17 2 100   2 0 15 $ENV{PERL_RL} = 'Perl o=0' unless $ENV{PERL_RL};
18 2         55 return;
19             }
20              
21             sub run {
22 0     0 0   my ($self, $hailo) = @_;
23 0           my $name = 'Hailo';
24 0           my $term = Term::ReadLine->new($name);
25 0           my $command = qr[
26             ^
27             # A dot-prefix like in SQLite
28             \.
29             # We only have Hailo methods matching this
30             (?<method> [a-z_]+ )
31             # Optional arguments. These'll be passed to eval() before being
32             # passed to the method
33             \s*
34             (?: (?<arguments>.+) )?
35             $]x;
36              
37 0           print $self->_intro;
38              
39 0           while (defined (my $line = $term->readline($name . '> '))) {
40 0           $line = decode('utf8', $line);
41              
42 0 0         if ($line =~ /$command/p) {
43 0 0         if ($+{method} eq 'help') {
    0          
44 0           print $self->_help($hailo);
45             } elsif ($+{method} =~ /^(?: quit | exit )$/xs) {
46 0   0       say $hailo->reply("Dave, this conversation can serve no purpose anymore. Goodbye.") // "Bye!";
47 0           exit 0;
48             }
49 0           my $meth = $+{method};
50 0 0         my @args = defined $+{arguments} ? eval $+{arguments} : ();
51              
52             eval {
53 0           say dump $hailo->$meth(@args);
54 0           1;
55 0 0         } or do {
56 0   0       chomp(my $err = $@ || "Zombie Error");
57 0           say STDERR "Failed on <<${^MATCH}>>: <<$err>>";
58             }
59             } else {
60 0           my $answer = $hailo->learn_reply($line);
61 0   0       say $answer // "I don't know enough to answer you yet.";
62             }
63             }
64 0           print "\n";
65              
66 0           return;
67             }
68              
69             sub _intro {
70 0     0     my ($self) = @_;
71 0           my $intro = <<"INTRO";
72             Welcome to the Hailo interactive shell
73             Enter ".help" to show the built-in commands.
74             Input that's not a command will be passed to Hailo to learn, and it'll
75             reply back.
76             INTRO
77 0           return $intro;
78             }
79              
80             sub _help {
81 0     0     my ($self, $hailo) = @_;
82              
83 0           my $include = qr/ ^ _go /xs;
84 0           my $exclude = qr/
85             _
86             (?:
87             version
88             | order
89             | progress
90             | random_reply
91             | examples
92             | autosave
93             | brain
94             | class
95             )
96             $/xs;
97              
98 0           my @attr;
99 0           for my $attr ($hailo->meta->get_all_attributes) {
100             # Only get attributes that are valid command-line options
101 0 0         next unless $attr->name =~ $include;
102              
103             # We don't support changing these in mid-stream
104 0 0         next if $attr->name =~ $exclude;
105              
106             push @attr => {
107 0           name => do {
108 0           my $tmp = $attr->cmd_flag;
109 0           $tmp =~ tr/-/_/;
110 0           $tmp;
111             },
112             documentation => $attr->documentation,
113             };
114             }
115              
116 0           push @attr => {
117             name => 'quit',
118             documentation => "Exit this chat session",
119             };
120              
121 0           my $help = <<"HELP";
122             These are the commands we know about:
123              
124             HELP
125              
126 0           my @sorted = sort { $a->{name} cmp $b->{name} } @attr;
  0            
127 0           for my $cmd (@sorted) {
128 0           $help .= sprintf " %-14s%s\n", '.'.$cmd->{name}, $cmd->{documentation};
129             }
130              
131 0           $help .= <<"HELP";
132              
133             The commands are just method calls on a Hailo object. Any arguments to
134             them will be passed through eval() used as method arguments. E.g.:
135              
136             .train "/tmp/megahal.trn"
137             Trained from 350 lines in 0.54 seconds; 654.04 lines/s
138             ()
139              
140             Return values are printed with Data::Dump:
141              
142             .stats
143             (1311, 2997, 3580, 3563)
144              
145             Any input not starting with "." will be passed through Hailo's
146             learn_reply method:
147              
148             Hailo> Help, mommy!
149             Really? I can't. It's an ethical thing.
150              
151             HELP
152              
153 0           return $help;
154             }
155              
156             __PACKAGE__->meta->make_immutable;
157              
158             =encoding utf8
159              
160             =head1 NAME
161              
162             Hailo::UI::ReadLine - A UI for L<Hailo|Hailo> using L<Term::ReadLine|Term::ReadLine>
163              
164             =head1 SYNOPSIS
165              
166             This module is called internally by L<Hailo|Hailo>, it takes no options.
167              
168             A ReadLine interface will be presented when calling L<hailo> on the
169             command-line with only a C<--brain> argument:
170              
171             hailo --brain hailo.sqlite
172              
173             =head1 DESCRIPTION
174              
175             Presents a ReadLine interface using L<Term::ReadLine>, the
176             L<Term::ReadLine::Gnu> frontend will be used.
177              
178             =head1 AUTHOR
179              
180             E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org>
181              
182             =head1 LICENSE AND COPYRIGHT
183              
184             Copyright 2010 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason.
185              
186             This program is free software, you can redistribute it and/or modify
187             it under the same terms as Perl itself.
188              
189             =cut