File Coverage

blib/lib/Hailo/UI/ReadLine.pm
Criterion Covered Total %
statement 10 10 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 14 100.0


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