File Coverage

blib/lib/Term/EditorEdit/Edit.pm
Criterion Covered Total %
statement 78 121 64.4
branch 20 66 30.3
condition n/a
subroutine 12 18 66.6
pod 1 8 12.5
total 111 213 52.1


line stmt bran cond sub pod time code
1             package Term::EditorEdit::Edit;
2              
3 2     2   11 use strict;
  2         3  
  2         57  
4 2     2   11 use warnings;
  2         4  
  2         57  
5              
6 2     2   9 use Any::Moose;
  2         2  
  2         20  
7 2     2   2989 use Text::Clip;
  2         8590  
  2         70  
8 2     2   1862 use Try::Tiny;
  2         3561  
  2         138  
9 2     2   1997 use IO::File;
  2         2439  
  2         3852  
10              
11             our $EDITOR = 'Term::EditorEdit';
12             our $RETRY = "__Term_EditorEdit_retry__\n";
13             our $Test_edit;
14              
15             #has editor => qw/ is ro required 1 weak_ref 1 /;
16             has process => qw/ is ro isa Maybe[CodeRef] /;
17             has separator => qw/ is rw /;
18             has file => qw/ is ro required 1 /;
19              
20             has document => qw/ is rw isa Str required 1 /;
21             has $_ => reader => $_, writer => "_$_", isa => 'Str' for qw/ initial_document /;
22              
23             has preamble => qw/ is rw isa Maybe[Str] /;
24             has $_ => reader => $_, writer => "_$_", isa => 'Maybe[Str]' for qw/ initial_preamble /;
25              
26             has content => qw/ is rw isa Str /;
27             has $_ => reader => $_, writer => "_$_", isa => 'Str' for qw/ initial_content /;
28              
29             sub BUILD {
30 2     2 1 296 my $self = shift;
31              
32 2         10 my $document = $self->document;
33 2         13 $self->_initial_document( $document );
34              
35 2         10 my ( $preamble, $content ) = $self->split( $document );
36              
37 2         16 $self->preamble( $preamble );
38 2         11 $self->_initial_preamble( $preamble );
39              
40 2         12 $self->content( $content );
41 2         13 $self->_initial_content( $content );
42             }
43              
44             sub edit {
45 1     1 0 2 my $self = shift;
46              
47 1         3 my $file = $self->file;
48 1         2 my $tmp;
49 1 50       6 if ( blessed $file ) {
50 1 50       11 if ( $file->isa( 'IO::Handle' ) ) {
    0          
51 1         2 $tmp = $file;
52             }
53             elsif ( $file->isa( 'Path::Class::File' ) ) {
54 0 0       0 $tmp = $file->open( 'w' ) or die "Unable to open $file: $!";
55             }
56             else {
57 0         0 die "Invalid file: $file";
58             }
59             }
60             else {
61 0 0       0 $file = '' unless defined $file;
62 0 0       0 if ( ref $file ) {
    0          
63 0         0 die "Invalid file: $file";
64             }
65             elsif ( length $file ) {
66 0 0       0 $tmp = IO::File->new( $file, 'w' ) or die "Unable to open $file: $!";
67             }
68             else {
69 0         0 die "Missing file";
70             }
71             }
72 1         10 $tmp->autoflush( 1 );
73            
74 1         84 while ( 1 ) {
75 1 50       13 $tmp->seek( 0, 0 ) or die "Unable to seek on tmp ($tmp): $!";
76 1 50       21 $tmp->truncate( 0 ) or die "Unable to truncate on tmp ($tmp): $!";
77 1         54 $tmp->print( $self->join( $self->preamble, $self->content ) );
78              
79 1 50       63 if ( $Test_edit ) {
80 1         4 $Test_edit->( $tmp );
81             }
82             else {
83             try {
84 0     0   0 $EDITOR->edit_file( $tmp->filename );
85             }
86             catch {
87 0     0   0 my $error = $_[0];
88 0         0 warn "$error";
89 0         0 warn "*** There was an error editing ", $tmp->filename, "\n";
90 0         0 while ( 1 ) {
91 0         0 print STDERR "Do you want to (c)ontinue, (a)bort, or (s)ave? ";
92 0         0 my $input = ;
93 0         0 chomp $input;
94 0 0       0 die $error unless defined $input;
95 0 0       0 if ( 0 ) { }
    0          
    0          
96 0         0 elsif ( $input eq 'c' ) {
97 0         0 last;
98             }
99             elsif ( $input eq 'a' ) {
100 0         0 die $error;
101             }
102             elsif ( $input eq 's' ) {
103 0         0 my $save;
104 0 0       0 unless ( $save = File::Temp->new( dir => '.', template => 'TermEditorEdit.XXXXXX', unlink => 0 ) ) {
105 0 0       0 warn "Unable to create temporary file: $!" and next;
106             }
107 0         0 my $tmp_filename = $tmp->filename;
108 0         0 my $tmpr;
109 0 0       0 unless ( $tmpr = IO::File->new( $tmp_filename, 'r' ) ) {
110 0 0       0 warn "Unable to open ($tmp_filename): $!" and next;
111             }
112 0         0 $save->print( join '', <$tmpr> );
113 0         0 $save->close;
114 0         0 warn "Saved to: ", $save->filename, " ", ( -s $save->filename ), "\n";
115             }
116             else {
117 0         0 warn "I don't understand ($input)\n";
118             }
119             }
120              
121 0         0 };
122             }
123              
124 1         237 my $document;
125             {
126 1         3 my $filename = $tmp->filename;
  1         4  
127 1 50       9 my $tmpr = IO::File->new( $filename, 'r' ) or die "Unable to open ($filename): $!";
128 1         94 $document = join '', <$tmpr>;
129 1         5 $tmpr->close;
130 1         13 undef $tmpr;
131             }
132              
133 1         9 $self->document( $document );
134 1         3 my ( $preamble, $content ) = $self->split( $document );
135 1         4 $self->preamble( $preamble );
136 1         4 $self->content( $content );
137              
138 1 50       5 if ( my $process = $self->process ) {
139 0         0 my ( @result, $retry );
140             try {
141 0     0   0 @result = $process->( $self );
142             }
143             catch {
144 0 0   0   0 die $_ unless $_ eq $RETRY;
145 0         0 $retry = 1;
146 0         0 };
147              
148 0 0       0 next if $retry;
149              
150 0 0       0 return $result[0] if defined $result[0];
151             }
152              
153 1         15 return $content;
154             }
155            
156             }
157              
158             sub first_line_blank {
159 0     0 0 0 my $self = shift;
160 0         0 return $self->document =~ m/\A\s*$/m;
161             }
162 0     0 0 0 sub line0_blank { return $_[0]->first_line_blank }
163              
164             sub preamble_from_initial {
165 1     1 0 2 my $self = shift;
166 1         3 my @preamble;
167 1         6 for my $part ( "$_[0]", $self->initial_preamble ) {
168 2 50       6 next unless defined $part;
169 2         3 chomp $part;
170 2         4 push @preamble, $part;
171             }
172 1 50       11 $self->preamble( join "\n", @preamble, '' ) if @preamble;
173             }
174              
175             sub retry {
176 1     1 0 70 my $self = shift;
177 1         9 die $RETRY;
178             }
179              
180             sub split {
181 4     4 0 7 my $self = shift;
182 4         7 my $document = shift;
183              
184 4 100       25 return ( undef, $document ) unless my $separator = $self->separator;
185              
186 1 50       6 die "Invalid separator ($separator)" if ref $separator;
187              
188 1 50       18 if ( my $mark = Text::Clip->new( data => $document )->find( qr/^\s*$separator\s*$/m ) ) {
189 1         352 return ( $mark->preceding, $mark->remaining );
190             }
191              
192 0         0 return ( undef, $document );
193             }
194              
195             sub join {
196 5     5 0 1121 my $self = shift;
197 5         10 my $preamble = shift;
198 5         7 my $content = shift;
199              
200 5 100       27 return $content unless defined $preamble;
201 3         6 chomp $preamble;
202              
203 3         9 my $separator = $self->separator;
204 3 100       9 unless ( defined $separator ) {
205 1 50       21 return $content unless length $preamble;
206 1         7 return join "\n", $preamble, $content;
207             }
208 2 100       10 return join "\n", $separator, $content unless length $preamble;
209 1         7 return join "\n", $preamble, $separator, $content;
210             }
211              
212             1;