File Coverage

blib/lib/Devel/REPL/Plugin/Interrupt.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1 2     2   18238 use strict;
  2         4  
  2         82  
2 2     2   9 use warnings;
  2         3  
  2         143  
3             package Devel::REPL::Plugin::Interrupt;
4             # ABSTRACT: Traps SIGINT to kill long-running lines
5              
6             our $VERSION = '1.003028';
7              
8 2     2   10 use Devel::REPL::Plugin;
  2         4  
  2         18  
9 2     2   9354 use Sys::SigAction qw(set_sig_handler);
  2         10592  
  2         141  
10 2     2   15 use namespace::autoclean;
  2         3  
  2         18  
11              
12             around 'run' => sub {
13             my ($orig, $self) = (shift, shift);
14              
15             local $SIG{INT} = 'IGNORE';
16              
17             return $self->$orig(@_);
18             };
19              
20             around 'run_once' => sub {
21             my ($orig, $self) = (shift, shift);
22              
23             # We have to use Sys::SigAction: Perl 5.8+ has safe signal handling by
24             # default, and Term::ReadLine::Gnu restarts the interrupted system calls.
25             # The result is that the signal handler is not fired until you hit Enter.
26             my $sig_action = set_sig_handler INT => sub {
27             die "Interrupted.\n";
28             };
29              
30             return $self->$orig(@_);
31             };
32              
33             around 'read' => sub {
34             my ($orig, $self) = (shift, shift);
35              
36             # here SIGINT is caught and only kills the line being edited
37             while (1) {
38             my $line = eval { $self->$orig(@_) };
39             return $line unless $@;
40              
41             die unless $@ =~ /^Interrupted\./;
42              
43             # (Term::ReadLine::Gnu kills the line by default, but needs a LF -
44             # maybe I missed something?)
45             print "\n";
46             }
47             };
48              
49             1;
50              
51             __END__
52              
53             =pod
54              
55             =encoding UTF-8
56              
57             =head1 NAME
58              
59             Devel::REPL::Plugin::Interrupt - Traps SIGINT to kill long-running lines
60              
61             =head1 VERSION
62              
63             version 1.003028
64              
65             =head1 DESCRIPTION
66              
67             By default L<Devel::REPL> exits on SIGINT (usually Ctrl-C). If you load this
68             module, SIGINT will be trapped and used to kill long-running commands
69             (statements) and also to kill the line being edited (like eg. BASH do). (You
70             can still use Ctrl-D to exit.)
71              
72             =head1 SUPPORT
73              
74             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Devel-REPL>
75             (or L<bug-Devel-REPL@rt.cpan.org|mailto:bug-Devel-REPL@rt.cpan.org>).
76              
77             There is also an irc channel available for users of this distribution, at
78             L<C<#devel> on C<irc.perl.org>|irc://irc.perl.org/#devel-repl>.
79              
80             =head1 AUTHOR
81              
82             Shawn M Moore, C<< <sartak at gmail dot com> >>
83              
84             =head1 COPYRIGHT AND LICENCE
85              
86             This software is copyright (c) 2007 by Matt S Trout - mst (at) shadowcatsystems.co.uk (L<http://www.shadowcatsystems.co.uk/>).
87              
88             This is free software; you can redistribute it and/or modify it under
89             the same terms as the Perl 5 programming language system itself.
90              
91             =cut