Turn MultiLine::PPI's needs_continuation into a method line_needs_continuation
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / MultiLine / PPI.pm
CommitLineData
9cdb543b 1package Devel::REPL::Plugin::MultiLine::PPI;
2
3use Moose::Role;
4use PPI;
5use namespace::clean -except => [ 'meta' ];
6
7has 'continuation_prompt' => (
8 is => 'rw', required => 1, lazy => 1,
9 default => sub { '> ' }
10);
11
b21e7551 12has 'line_depth' => (
13 is => 'rw', required => 1, lazy => 1,
14 default => sub { 0 }
15);
16
9cdb543b 17around 'read' => sub {
18 my $orig = shift;
19 my ($self, @args) = @_;
20 my $line = $self->$orig(@args);
21
22 if (defined $line) {
49946f5c 23 while ($self->line_needs_continuation($line)) {
9cdb543b 24 my $orig_prompt = $self->prompt;
25 $self->prompt($self->continuation_prompt);
26
b21e7551 27 $self->line_depth($self->line_depth + 1);
9cdb543b 28 my $append = $self->read(@args);
b21e7551 29 $self->line_depth($self->line_depth - 1);
30
9cdb543b 31 $line .= $append if defined($append);
32
33 $self->prompt($orig_prompt);
34
35 # ^D means "shut up and eval already"
36 return $line if !defined($append);
37 }
38 }
39 return $line;
40};
41
49946f5c 42sub line_needs_continuation
9cdb543b 43{
49946f5c 44 my $repl = shift;
9cdb543b 45 my $line = shift;
46 my $document = PPI::Document->new(\$line);
47 return 0 if !defined($document);
48
49 # this could use more logic, such as returning 1 on s/foo/ba<Enter>
50 my $unfinished_structure = sub
51 {
52 my ($document, $element) = @_;
53 return 0 unless $element->isa('PPI::Structure');
54 return 1 unless $element->start && $element->finish;
55 return 0;
56 };
57
58 return $document->find_any($unfinished_structure);
59}
60
611;
d9ba19d2 62
63__END__
64
65=head1 NAME
66
67Devel::REPL::Plugin::MultiLine::PPI - read lines until all blocks are closed
68
69=head1 SYNOPSIS
70
71 #!/usr/bin/perl
72
73 use lib './lib';
74 use Devel::REPL;
75
76 my $repl = Devel::REPL->new;
77 $repl->load_plugin('LexEnv');
78 $repl->load_plugin('History');
79 $repl->load_plugin('MultiLine::PPI');
80 $repl->run;
81
82=head1 DESCRIPTION
83
84Plugin that will collect lines until you have no unfinished structures. This
85lets you write subroutines, C<if> statements, loops, etc. more naturally.
86
87For example, without a MultiLine plugin,
88
89 $ my $x = 3;
90 3
91 $ if ($x == 3) {
92
93will throw a compile error, because that C<if> statement is incomplete. With a
94MultiLine plugin,
95
96 $ my $x = 3;
97 3
98 $ if ($x == 3) {
99
100 > print "OH NOES!"
101
102 > }
103 OH NOES
104 1
105
106you may write the code across multiple lines, such as in C<irb> and C<python>.
107
108This module uses L<PPI>. This plugin is named C<MultiLine::PPI> because someone
109else may conceivably implement similar behavior some other less
110dependency-heavy way.
111
112=head1 SEE ALSO
113
114C<Devel::REPL>
115
116=head1 AUTHOR
117
118Shawn M Moore, C<< <sartak at gmail dot com> >>
119
120=head1 COPYRIGHT AND LICENSE
121
122Copyright (C) 2007 by Shawn M Moore
123
124This library is free software; you can redistribute it and/or modify
125it under the same terms as Perl itself.
126
127=cut