line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::bif::Editor; |
2
|
1
|
|
|
1
|
|
574
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
3
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
22
|
|
4
|
1
|
|
|
1
|
|
472
|
use Bif::Mo; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
5
|
1
|
|
|
1
|
|
4
|
use Carp (); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
14
|
|
6
|
1
|
|
|
1
|
|
840
|
use File::Which (); |
|
1
|
|
|
|
|
916
|
|
|
1
|
|
|
|
|
19
|
|
7
|
1
|
|
|
1
|
|
1194
|
use Path::Tiny (); |
|
1
|
|
|
|
|
12963
|
|
|
1
|
|
|
|
|
25
|
|
8
|
1
|
|
|
1
|
|
1040
|
use Proc::FastSpawn (); |
|
1
|
|
|
|
|
448
|
|
|
1
|
|
|
|
|
583
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our @CARP_NOT = (__PACKAGE__); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
has auto => ( |
13
|
|
|
|
|
|
|
is => 'ro', |
14
|
|
|
|
|
|
|
default => 1, |
15
|
|
|
|
|
|
|
); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
has txt => ( is => 'rw', ); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has encoding => ( |
20
|
|
|
|
|
|
|
is => 'ro', |
21
|
|
|
|
|
|
|
default => ':utf8', |
22
|
|
|
|
|
|
|
); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
has filename => ( |
25
|
|
|
|
|
|
|
is => 'rw', |
26
|
|
|
|
|
|
|
default => sub { Path::Tiny->tempfile }, |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
has editor => ( |
30
|
|
|
|
|
|
|
is => 'ro', |
31
|
|
|
|
|
|
|
default => \&_build_editor, |
32
|
|
|
|
|
|
|
); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
has pid => ( is => 'rw', ); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub _build_editor { |
37
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
38
|
|
|
|
|
|
|
|
39
|
0
|
0
|
|
|
|
0
|
if ( exists $ENV{EDITOR} ) { |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Explicit editor defined |
42
|
|
|
|
|
|
|
return File::Which::which( $ENV{EDITOR} ) |
43
|
0
|
|
0
|
|
|
0
|
|| Carp::croak("editor not found: $ENV{EDITOR}"); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Otherwise take the first from our own list |
47
|
0
|
|
|
|
|
0
|
foreach my $editor (qw/sensible-editor vim vi emacs nano/) { |
48
|
0
|
|
|
|
|
0
|
my $path = File::Which::which($editor); |
49
|
0
|
0
|
|
|
|
0
|
return $path if $path; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
0
|
Carp::croak("no suitable editor found"); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub BUILD { |
56
|
1
|
|
|
1
|
0
|
2
|
my $self = shift; |
57
|
1
|
50
|
|
|
|
7
|
$self->edit if $self->auto; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub edit { |
61
|
1
|
|
|
1
|
1
|
2
|
my $self = shift; |
62
|
1
|
50
|
33
|
|
|
5
|
return if $self->pid or !-t STDOUT; |
63
|
|
|
|
|
|
|
|
64
|
0
|
0
|
|
|
|
0
|
$self->filename->spew( { binmode => $self->encoding }, $self->txt ) |
65
|
|
|
|
|
|
|
if $self->txt; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
0
|
$self->pid( |
68
|
|
|
|
|
|
|
Proc::FastSpawn::spawn( |
69
|
|
|
|
|
|
|
$self->editor, [ $self->editor, $self->filename ] |
70
|
|
|
|
|
|
|
) |
71
|
|
|
|
|
|
|
); |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
|
|
|
0
|
return; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub wait_child { |
77
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
78
|
1
|
50
|
|
|
|
4
|
return unless $self->pid; |
79
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
0
|
waitpid( $self->pid, 0 ); |
81
|
0
|
|
|
|
|
0
|
$self->pid(undef); |
82
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
0
|
my $res = $?; |
84
|
0
|
|
|
|
|
0
|
my $err = $!; |
85
|
|
|
|
|
|
|
|
86
|
0
|
0
|
|
|
|
0
|
if ( $res == -1 ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
87
|
0
|
|
|
|
|
0
|
Carp::croak sprintf "%s failed to execute: %s", $self->editor, $err; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
elsif ( $res & 127 ) { |
90
|
0
|
0
|
|
|
|
0
|
Carp::croak sprintf( |
91
|
|
|
|
|
|
|
"%s died with signal %d, %s coredump", |
92
|
|
|
|
|
|
|
$self->editor, |
93
|
|
|
|
|
|
|
( $res & 127 ), |
94
|
|
|
|
|
|
|
( ( $res & 128 ) ? 'with' : 'without' ) |
95
|
|
|
|
|
|
|
); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
elsif ( my $code = $res >> 8 ) { |
98
|
0
|
|
|
|
|
0
|
Carp::croak sprintf( "%s exited with code %d", $self->editor, $code ); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub result { |
103
|
1
|
|
|
1
|
1
|
2
|
my $self = shift; |
104
|
1
|
50
|
|
|
|
8
|
return $self->txt unless -t STDOUT; |
105
|
0
|
|
|
|
|
0
|
$self->wait_child; |
106
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
0
|
return $self->filename->slurp( { binmode => $self->encoding } ); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub DESTROY { |
111
|
1
|
|
|
1
|
|
828
|
my $self = shift; |
112
|
1
|
|
|
|
|
4
|
$self->wait_child; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
1; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
__END__ |