File Coverage

blib/lib/App/bif/Editor.pm
Criterion Covered Total %
statement 31 51 60.7
branch 4 22 18.1
condition 1 6 16.6
subroutine 12 13 92.3
pod 3 4 75.0
total 51 96 53.1


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__