Commit | Line | Data |
9cdb543b |
1 | package Devel::REPL::Plugin::MultiLine::PPI; |
2 | |
3 | use Moose::Role; |
4 | use PPI; |
5 | use namespace::clean -except => [ 'meta' ]; |
6 | |
7 | has 'continuation_prompt' => ( |
8 | is => 'rw', required => 1, lazy => 1, |
9 | default => sub { '> ' } |
10 | ); |
11 | |
12 | around 'read' => sub { |
13 | my $orig = shift; |
14 | my ($self, @args) = @_; |
15 | my $line = $self->$orig(@args); |
16 | |
17 | if (defined $line) { |
18 | while (needs_continuation($line)) { |
19 | my $orig_prompt = $self->prompt; |
20 | $self->prompt($self->continuation_prompt); |
21 | |
22 | my $append = $self->read(@args); |
23 | $line .= $append if defined($append); |
24 | |
25 | $self->prompt($orig_prompt); |
26 | |
27 | # ^D means "shut up and eval already" |
28 | return $line if !defined($append); |
29 | } |
30 | } |
31 | return $line; |
32 | }; |
33 | |
34 | sub needs_continuation |
35 | { |
36 | my $line = shift; |
37 | my $document = PPI::Document->new(\$line); |
38 | return 0 if !defined($document); |
39 | |
40 | # this could use more logic, such as returning 1 on s/foo/ba<Enter> |
41 | my $unfinished_structure = sub |
42 | { |
43 | my ($document, $element) = @_; |
44 | return 0 unless $element->isa('PPI::Structure'); |
45 | return 1 unless $element->start && $element->finish; |
46 | return 0; |
47 | }; |
48 | |
49 | return $document->find_any($unfinished_structure); |
50 | } |
51 | |
52 | 1; |