Add documentation/copyright
[p5sagit/Devel-REPL.git] / lib / Devel / REPL / Plugin / MultiLine / PPI.pm
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;
53
54 __END__
55
56 =head1 NAME
57
58 Devel::REPL::Plugin::MultiLine::PPI - read lines until all blocks are closed
59
60 =head1 SYNOPSIS
61
62     #!/usr/bin/perl 
63
64     use lib './lib';
65     use Devel::REPL;
66
67     my $repl = Devel::REPL->new;
68     $repl->load_plugin('LexEnv');
69     $repl->load_plugin('History');
70     $repl->load_plugin('MultiLine::PPI');
71     $repl->run;
72
73 =head1 DESCRIPTION
74
75 Plugin that will collect lines until you have no unfinished structures. This
76 lets you write subroutines, C<if> statements, loops, etc. more naturally.
77
78 For example, without a MultiLine plugin,
79
80     $ my $x = 3;
81     3
82     $ if ($x == 3) {
83
84 will throw a compile error, because that C<if> statement is incomplete. With a
85 MultiLine plugin,
86
87     $ my $x = 3;
88     3
89     $ if ($x == 3) {
90
91     > print "OH NOES!"
92
93     > }
94     OH NOES
95     1
96
97 you may write the code across multiple lines, such as in C<irb> and C<python>.
98
99 This module uses L<PPI>. This plugin is named C<MultiLine::PPI> because someone
100 else may conceivably implement similar behavior some other less
101 dependency-heavy way.
102
103 =head1 SEE ALSO
104
105 C<Devel::REPL>
106
107 =head1 AUTHOR
108
109 Shawn M Moore, C<< <sartak at gmail dot com> >>
110
111 =head1 COPYRIGHT AND LICENSE
112
113 Copyright (C) 2007 by Shawn M Moore
114
115 This library is free software; you can redistribute it and/or modify
116 it under the same terms as Perl itself.
117
118 =cut