add a few more type annotations
[scpubgit/DX.git] / lib / DX / ShellFrontend.pm
1 package DX::ShellFrontend;
2
3 use Types::Standard qw(Enum);
4 use IO::Handle;
5 use Caroline;
6 use DX::Class;
7
8 has session => (
9   is => 'ro', isa => ShellSession, required => 1,
10   handles => [ qw(is_complete_command_string eval_command_string) ]
11 );
12
13 has session_mode => (is => 'rwp', isa => Enum['shell','query'], required => 1);
14
15 has readline => (is => 'lazy', builder => sub { Caroline->new });
16
17 sub BUILD { STDOUT->autoflush(1) }
18
19 sub repl {
20   my ($self) = @_;
21   while (1) {
22     last unless $self->rep
23   }
24 }
25
26 sub rep {
27   my ($self) = @_;
28   return unless defined(my $command = $self->read_command);
29   my @result = $self->eval_command_string($command);
30   $self->process_result(@result);
31   return 1;
32 }
33
34 sub read_command {
35   my ($self) = @_;
36   my $base_prompt = $self->session_mode eq 'shell' ? '$ ' : '? ';
37   my $rl = $self->readline;
38   return unless defined(my $command = $rl->readline($base_prompt));
39   while (not $self->is_complete_command_string($command)) {
40     $command .= $rl->readline('> ');
41   }
42   $rl->history_add($command);
43   return $command;
44 }
45
46 sub process_result {
47   my ($self, @result) = @_;
48   foreach my $res (@result) {
49     my ($type, $payload) = @$res;
50     $self->${\($self->can("process_${type}_result")||die)}($payload);
51   }
52 }
53
54 sub process_mode_result {
55   my ($self, $mode) = @_;
56   $self->_set_session_mode($mode);
57 }
58
59 sub process_output_result {
60   my ($self, $output) = @_;
61   $output .= "\n" unless $output =~ /\n$/;
62   print $output;
63 }
64
65 1;