I no longer use this plugin in my bundle
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / MultiLine / PPI.pm
CommitLineData
1716b200 1use strict;
2use warnings;
9cdb543b 3package Devel::REPL::Plugin::MultiLine::PPI;
4
54beb05d 5our $VERSION = '1.003027';
6
6a5409bc 7use Devel::REPL::Plugin;
9cdb543b 8use PPI;
aa8b7647 9use namespace::autoclean;
9cdb543b 10
11has 'continuation_prompt' => (
b595a818 12 is => 'rw',
13 lazy => 1,
9cdb543b 14 default => sub { '> ' }
15);
16
b21e7551 17has 'line_depth' => (
b595a818 18 is => 'rw',
19 lazy => 1,
b21e7551 20 default => sub { 0 }
21);
22
9cdb543b 23around 'read' => sub {
24 my $orig = shift;
25 my ($self, @args) = @_;
26 my $line = $self->$orig(@args);
27
28 if (defined $line) {
0cbfa921 29 return $self->continue_reading_if_necessary($line, @args);
30 } else {
31 return $line;
32 }
33};
34
35sub continue_reading_if_necessary {
36 my ( $self, $line, @args ) = @_;
37
38 while ($self->line_needs_continuation($line)) {
39 my $orig_prompt = $self->prompt;
40 $self->prompt($self->continuation_prompt);
9cdb543b 41
0cbfa921 42 $self->line_depth($self->line_depth + 1);
43 my $append = $self->read(@args);
44 $self->line_depth($self->line_depth - 1);
b21e7551 45
998f8107 46 $line .= "\n$append" if defined($append);
9cdb543b 47
0cbfa921 48 $self->prompt($orig_prompt);
9cdb543b 49
0cbfa921 50 # ^D means "shut up and eval already"
51 return $line if !defined($append);
9cdb543b 52 }
0cbfa921 53
9cdb543b 54 return $line;
0cbfa921 55}
9cdb543b 56
49946f5c 57sub line_needs_continuation
9cdb543b 58{
49946f5c 59 my $repl = shift;
9cdb543b 60 my $line = shift;
2fd5e077 61
62 # add this so we can test whether the document ends in PPI::Statement::Null
63 $line .= "\n;;";
64
9cdb543b 65 my $document = PPI::Document->new(\$line);
d954e450 66 return 0 if !defined($document);
9cdb543b 67
2fd5e077 68 # adding ";" to a complete document adds a PPI::Statement::Null. we added a ;;
69 # so if it doesn't end in null then there's probably something that's
70 # incomplete
d954e450 71 return 0 if $document->child(-1)->isa('PPI::Statement::Null');
2fd5e077 72
9cdb543b 73 # this could use more logic, such as returning 1 on s/foo/ba<Enter>
74 my $unfinished_structure = sub
75 {
76 my ($document, $element) = @_;
77 return 0 unless $element->isa('PPI::Structure');
2fd5e077 78 return 1 unless $element->finish;
9cdb543b 79 return 0;
80 };
81
82 return $document->find_any($unfinished_structure);
83}
84
851;
d9ba19d2 86
87__END__
88
89=head1 NAME
90
91Devel::REPL::Plugin::MultiLine::PPI - read lines until all blocks are closed
92
93=head1 SYNOPSIS
94
d9ba19d2 95 use Devel::REPL;
96
97 my $repl = Devel::REPL->new;
98 $repl->load_plugin('LexEnv');
99 $repl->load_plugin('History');
100 $repl->load_plugin('MultiLine::PPI');
101 $repl->run;
102
103=head1 DESCRIPTION
104
105Plugin that will collect lines until you have no unfinished structures. This
106lets you write subroutines, C<if> statements, loops, etc. more naturally.
107
108For example, without a MultiLine plugin,
109
110 $ my $x = 3;
111 3
112 $ if ($x == 3) {
113
114will throw a compile error, because that C<if> statement is incomplete. With a
115MultiLine plugin,
116
117 $ my $x = 3;
118 3
119 $ if ($x == 3) {
120
121 > print "OH NOES!"
122
123 > }
124 OH NOES
125 1
126
127you may write the code across multiple lines, such as in C<irb> and C<python>.
128
129This module uses L<PPI>. This plugin is named C<MultiLine::PPI> because someone
130else may conceivably implement similar behavior some other less
131dependency-heavy way.
132
133=head1 SEE ALSO
134
135C<Devel::REPL>
136
137=head1 AUTHOR
138
139Shawn M Moore, C<< <sartak at gmail dot com> >>
140
141=head1 COPYRIGHT AND LICENSE
142
143Copyright (C) 2007 by Shawn M Moore
144
145This library is free software; you can redistribute it and/or modify
146it under the same terms as Perl itself.
147
148=cut