File Coverage

blib/lib/Pry.pm
Criterion Covered Total %
statement 13 44 29.5
branch 1 12 8.3
condition n/a
subroutine 5 10 50.0
pod 5 5 100.0
total 24 71 33.8


line stmt bran cond sub pod time code
1 1     1   15263 use 5.008001;
  1         3  
  1         32  
2 1     1   4 use strict;
  1         1  
  1         31  
3 1     1   4 use warnings;
  1         4  
  1         61  
4              
5             package Pry;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.003001';
9              
10 1     1   418 use Exporter::Shiny our @EXPORT = qw(pry);
  1         3145  
  1         5  
11              
12             # cargo-culted Win32 stuff... untested!
13             #
14             BEGIN {
15 1 50   1   822 if ($^O eq 'MSWin32') {
16 0           require Term::ANSIColor;
17 0           require Win32::Console::ANSI;
18 0           Win32::Console::ANSI->import;
19             }
20             };
21              
22             our ($Lexicals, $Trace, $Already);
23              
24             # a refinement for the Reply class
25             #
26             my $_say = sub {
27             require Term::ANSIColor;
28             shift;
29             my ($text, $colour) = (@_, "cyan");
30             print Term::ANSIColor::colored($text, "bold $colour"), "\n";
31             };
32              
33             our $Dumper = 'Data::Dumper';
34              
35             my $_display_vars = sub {
36             my $invocant = shift;
37             my $_dumper = $Dumper eq 'Data::Dump'
38             ? do { require Data::Dump; \&Data::Dump::dump }
39             : do { require Data::Dumper; \&Data::Dumper::Dumper };
40            
41             local $Data::Dumper::Deparse = 1;
42             local $Data::Dumper::Terse = 1;
43            
44             for my $var (@_)
45             {
46             my $val = ($var =~ /\A\$/) ? ${$Lexicals->{$var}} : $Lexicals->{$var};
47             my $dump = $_dumper->($val);
48             chomp($dump);
49             $dump =~ s/(\A\[)/\(/ and $dump =~ s/(\]\z)/\)/ if $var =~ /\A\@/;
50             $dump =~ s/(\A\{)/\(/ and $dump =~ s/(\}\z)/\)/ if $var =~ /\A\%/;
51             $invocant->$_say("$var = $dump;", "yellow");
52             }
53             };
54              
55             # shim to pass lexicals to Reply
56             #
57             {
58             package #hide
59             Pry::_Lexicals;
60             our @ISA = qw( Reply::Plugin );
61 0     0 1   sub lexical_environment { $Lexicals }
62             $INC{'Pry/_Lexicals.pm'} = __FILE__;
63             }
64              
65             # the guts
66             #
67             sub pry (;@)
68             {
69 0     0 1   my ($caller, $file, $line) = caller;
70            
71 0 0         if ( $Already )
72             {
73 0           Reply->$_say(
74             "Pry is not re-entrant; not prying again at $file line $line",
75             "magenta",
76             );
77 0           return;
78             }
79 0           local $Already = 1;
80            
81 0           require Devel::StackTrace;
82 0           require Reply;
83 0           require PadWalker;
84            
85 0           $Lexicals = +{
86 0           %{ PadWalker::peek_our(1) },
87 0           %{ PadWalker::peek_my(1) },
88             };
89 0           $Trace = Devel::StackTrace->new(
90             ignore_package => __PACKAGE__,
91             message => "Prying",
92             );
93            
94 0           my $repl = Reply->new(
95             config => ".replyrc",
96             plugins => [ "/Pry/_Lexicals" ],
97             );
98 0           $repl->step("package $caller");
99            
100 0           $repl->$_say("Prying at $file line $line", "magenta");
101 0 0         $repl->$_display_vars(@_) if @_;
102 0           $repl->$_say("Current package: '$caller'");
103 0           $repl->$_say("Lexicals in scope: @{[ sort keys %$Lexicals ]}");
  0            
104 0           $repl->$_say("Ctrl+D to finish prying.", "magenta");
105 0           $repl->run;
106 0           $repl->$_say("Finished prying!", "magenta");
107            
108 0           my @return = map($Lexicals->{$_}, @_);
109 0 0         wantarray ? @return : \@return;
110             }
111              
112             # utils
113             #
114 0 0   0 1   sub Lexicals () { $Lexicals if $] }
115 0 0   0 1   sub Trace () { $Trace if $] }
116 0     0 1   sub Dump (@) { __PACKAGE__->$_display_vars(@_) }
117              
118             1;
119              
120             __END__
121              
122             =pod
123              
124             =begin trustme
125              
126             =item pry
127              
128             =end trustme
129              
130             =encoding utf-8
131              
132             =head1 NAME
133              
134             Pry - intrude on your code
135              
136             =head1 SYNOPSIS
137              
138             use Pry;
139            
140             ...;
141             pry;
142             ...;
143              
144             =head1 DESCRIPTION
145              
146             Kind of a bit like a debugger, kind of a bit like a REPL.
147              
148             This module gives you a function called C<pry> that you can drop into
149             your code anywhere. When Perl executes that line of code, it will stop
150             and drop you into a REPL. You can use the REPL to inspect any lexical
151             variables (and even alter them), call functions and methods, and so on.
152              
153             All the clever stuff is in the REPL. Rather than writing yet another
154             Perl REPL, Pry uses L<Reply>, which is an awesome yet fairly small REPL
155             with support for plugins that can do some really useful stuff, such as
156             auto-complete of function and variable names.
157              
158             Once you've finished using the REPL, just hit Ctrl+D and your code will
159             resume execution.
160              
161             =head2 Functions
162              
163             =over
164              
165             =item C<< pry() >>
166              
167             Starts the Pry REPL.
168              
169             =item C<< pry(@varnames) >>
170              
171             Dumps selected variables before starting the Pry REPL.
172              
173             Note a list of variable I<names> is expected; not I<values>. For
174             example:
175              
176             my $x = 42;
177             my @y = (666, 999);
178             pry('$x', '@y');
179              
180             =back
181              
182             =head3 Utility Functions
183              
184             The following functions are provided for your convenience. They cannot
185             be exported, so you should access them, from the REPL, using their
186             fully-qualified name.
187              
188             =over
189              
190             =item C<< Pry::Lexicals >>
191              
192             Returns a hashref of your lexical variables.
193              
194             =item C<< Pry::Trace >>
195              
196             Returns the stack trace as a L<Devel::StackTrace> object.
197              
198             =item C<< Pry::Dump(@variable_names) >>
199              
200             Dumps variables (which must exist somewhere in the C<< Pry::Lexicals >>
201             hashref).
202              
203             =back
204              
205             =head2 Package Variable
206              
207             =over
208              
209             =item C<< $Pry::Dumper >>
210              
211             Decides the backend dumper implementation used by C<< Pry::Dump() >>.
212             Valid values are "Data::Dump" and "Data::Dumper".
213              
214             =back
215              
216             =head1 CONFIGURATION
217              
218             Pry's REPL can be configured in the same way as L<Reply>.
219              
220             =head1 CAVEATS
221              
222             I imagine this probably breaks pretty badly in a multi-threaded or
223             multi-process scenario.
224              
225             =head1 BUGS
226              
227             Please report any bugs to
228             L<http://rt.cpan.org/Dist/Display.html?Queue=Pry>.
229              
230             =head1 SEE ALSO
231              
232             L<http://en.wikipedia.org/wiki/Read–eval–print_loop>,
233             L<Reply>.
234              
235             =head1 AUTHOR
236              
237             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
238              
239             =head1 COPYRIGHT AND LICENCE
240              
241             This software is copyright (c) 2014 by Toby Inkster.
242              
243             This is free software; you can redistribute it and/or modify it under
244             the same terms as the Perl 5 programming language system itself.
245              
246             =head1 DISCLAIMER OF WARRANTIES
247              
248             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
249             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
250             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
251