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