File Coverage

blib/lib/File/Edit.pm
Criterion Covered Total %
statement 40 70 57.1
branch 7 20 35.0
condition 0 3 0.0
subroutine 9 13 69.2
pod 4 5 80.0
total 60 111 54.0


line stmt bran cond sub pod time code
1             package File::Edit;
2 2     2   129219 use Mojo::Base -base;
  2         335044  
  2         14  
3 2     2   2102 use Path::Tiny qw/path/;
  2         17915  
  2         138  
4 2     2   17 use Carp;
  2         3  
  2         2148  
5             our $VERSION = '0.0.4';
6              
7             has 'file';
8             has 'found'; # Line numbers of found lines. ArrayRef.
9             has '_lines'; # Text in the form of lines. ArrayRef.
10             has '_line_re'; # Regex for _find_one
11              
12             sub new {
13 8 50   8 1 4616 @_ > 1
14             ? $_[0]->SUPER::new({ file => path($_[1]),
15             _lines => [path($_[1])->lines],
16             found => [] })
17             : $_[0]->SUPER::new
18             }
19             sub text {
20 1     1 1 10 my ($self, $text) = @_;
21              
22 1         6 $text =~ s/\n/\nx-x/g;
23 1         8 $self->{_lines} = [split('x-x',$text)];
24              
25 1         3 return $self;
26             }
27             sub replace {
28 1     1 1 17 my ($o, $orig, $repstr) = @_;
29              
30             # Replaces one line
31 1         3 $o->_find_one($orig)
32             ->_replace_found($repstr);
33              
34 1         2 return $o;
35             }
36             sub get_block {
37 0     0 0 0 my ($o, %opt) = @_;
38              
39             return $o->_find_block($opt{from},$opt{to})
40 0         0 ->_found_lines;
41             }
42             sub save {
43 0     0 1 0 my ($o, $file) = @_;
44              
45 0 0       0 if ($file) {
46 0         0 path($file)->spew(join('',@{$o->_lines}));
  0         0  
47             } else {
48 0         0 $o->file->spew(join('',@{$o->_lines}));
  0         0  
49             }
50              
51 0         0 return $o;
52             }
53              
54             sub _find_block {
55 0     0   0 my ($o, $begin_re, $end_re) = @_;
56 0         0 my $in_block = 0; # True if line is in block
57 0         0 my $line_begin = -1; # First line num of found block. -1 if not found
58 0         0 my $line_end = -1; # Last line num of found block. -1 if not found
59              
60 0         0 foreach my $n (0 .. $#{$o->_lines}) {
  0         0  
61 0 0       0 if (!$in_block) {
62 0 0       0 if ($o->_lines->[$n] =~ $begin_re) {
63 0         0 $line_begin = $n;
64 0         0 $in_block = 1;
65             }
66             } else {
67 0 0       0 if ($o->_lines->[$n] =~ $end_re) {
68 0         0 $line_end = $n;
69 0         0 $in_block = 0;
70 0         0 last;
71             }
72             }
73             }
74              
75             # Error if block not found
76 0 0 0     0 croak "Block not found." if $line_begin == -1 or $line_end == -1;
77              
78 0         0 $o->found([$line_begin, $line_end]);
79              
80 0         0 return $o;
81             }
82             sub _found_lines {
83 0     0   0 my ($o) = @_;
84              
85 0         0 return [@{$o->_lines}[$o->found->[0] .. $o->found->[1]]];
  0         0  
86             }
87              
88             sub _find_one {
89 6     6   86 my ($o, $line_re) = @_;
90 6         7 my $n = 0;
91              
92             # Init search result
93 6         14 $o->found([]);
94 6 50       38 $line_re = ref $line_re eq 'Regexp' ? $line_re : _qre($line_re);
95 6         17 $o->_line_re($line_re);
96              
97 6         28 foreach my $l (@{$o->_lines}) {
  6         8  
98 12 100       54 push @{$o->found}, $n if $l =~ $line_re;
  5         10  
99 12         24 $n++;
100             }
101              
102             # Error if more than one line found
103 0         0 croak "Multiple lines found: ".join(', ',@{$o->found})
104 6 50       8 if scalar(@{$o->found}) > 1;
  6         10  
105              
106             # Error if more than one line found
107             croak "Line not found."
108 6 100       19 if scalar(@{$o->found}) == 0;
  6         8  
109              
110 5         26 return $o;
111             }
112             sub _replace_found {
113             # Replaces all lines found (line numbers in $o->found)
114 2     2   41 my ($o, $repstr) = @_;
115              
116 2         5 my $line_re = $o->_line_re; # s// does not work with $o-> notation
117              
118 2         7 foreach my $n (@{$o->found}) {
  2         3  
119 2         9 $o->_lines->[$n] =~ s/$line_re/$repstr/;
120             }
121              
122 2         21 return $o;
123             }
124             sub _qre { ## ($string) :> regex
125 6     6   11 my $quoted = quotemeta(shift);
126 6         53 return qr/$quoted/;
127             }
128              
129              
130             =head1 NAME
131              
132             File::Edit - A naive, probably buggy, file editor.
133              
134             =head1 VERSION
135              
136             Version 0.0.4
137              
138             =cut
139             =head1 SYNOPSIS
140              
141             use File::Edit;
142              
143             # Replace string in file
144             File::Edit->new('build.gradle')
145             ->replace('minSdkVersion 16', 'minSdkVersion 21')
146             ->save()
147             ;
148              
149             # Edit text, save to file
150             File::Edit->new()
151             ->text(" minSdkVersion 16\n targetSdkVersion 29")
152             ->replace('minSdkVersion 16', 'minSdkVersion 21')
153             ->save('build.gradle')
154             ;
155              
156             =head1 EXPORT
157              
158             A list of functions that can be exported. You can delete this section
159             if you don't export anything, such as for a purely object-oriented module.
160              
161             =head1 METHODS
162              
163             =head2 new
164              
165             my $fe = File::Edit->new("some_file.txt");
166              
167             Reads in a file for editing.
168              
169             =head2 text
170              
171             my $fe = File::Edit->new()->text(some_text);
172              
173             Reads in some text for editing.
174              
175             =head2 replace
176              
177             $fe->replace($old, $new);
178              
179             Replace the $old portion of a single line with $new.
180              
181             =head2 save
182              
183             my $fe = File::Edit->new("some_file.txt");
184             $fe->save(); # Saves to "some_file.txt"
185             $fe->save("other.txt") # Saves to "other.txt"
186              
187             =head1 AUTHOR
188              
189             Hoe Kit CHEW, C<< >>
190              
191             =head1 BUGS
192              
193             Please report any bugs or feature requests to C, or through
194             the web interface at L. I will be notified, and then you'll
195             automatically be notified of progress on your bug as I make changes.
196              
197              
198              
199              
200             =head1 SUPPORT
201              
202             You can find documentation for this module with the perldoc command.
203              
204             perldoc File::Edit
205              
206              
207             You can also look for information at:
208              
209             =over 4
210              
211             =item * RT: CPAN's request tracker (report bugs here)
212              
213             L
214              
215             =item * CPAN Ratings
216              
217             L
218              
219             =item * Search CPAN
220              
221             L
222              
223             =back
224              
225              
226             =head1 LICENSE AND COPYRIGHT
227              
228             This software is Copyright (c) 2021 by Hoe Kit CHEW.
229              
230             This is free software, licensed under:
231              
232             The Artistic License 2.0 (GPL Compatible)
233              
234              
235             =cut
236              
237             1; # End of File::Edit