File Coverage

blib/lib/File/Tudo.pm
Criterion Covered Total %
statement 73 77 94.8
branch 11 16 68.7
condition 10 19 52.6
subroutine 13 14 92.8
pod 7 7 100.0
total 114 133 85.7


line stmt bran cond sub pod time code
1             package File::Tudo;
2 2     2   353658 use 5.016;
  2         10  
3             our $VERSION = '0.02';
4 2     2   15 use strict;
  2         4  
  2         75  
5 2     2   32 use warnings;
  2         5  
  2         194  
6              
7 2     2   15 use Exporter 'import';
  2         4  
  2         160  
8             our @EXPORT_OK = qw(default_todo tudo);
9              
10 2     2   17 use Carp;
  2         3  
  2         221  
11 2     2   13 use File::Spec;
  2         3  
  2         69  
12              
13 2     2   1505 use File::HomeDir;
  2         17414  
  2         2114  
14              
15             sub default_todo {
16 0   0 0 1 0 $ENV{TODO_FILE} // File::Spec->catfile(File::HomeDir->my_home, 'TODO');
17             }
18              
19             sub new {
20              
21 3     3 1 325470 my $class = shift;
22 3   33     12 my $path = shift // default_todo;
23 3   100     13 my $param = shift // {};
24              
25 3   100     17 my $read = $param->{read} // 1;
26              
27 3         14 my $self = {
28             Path => $path,
29             Todo => [],
30             };
31              
32 3         9 bless $self, $class;
33              
34 3 100 100     77 if ($read and -s $self->{Path}) {
35 1         7 $self->read($self->{Path});
36             }
37              
38 3         14 return $self;
39              
40             }
41              
42             sub path {
43              
44 2     2 1 607 my $self = shift;
45 2         5 my $path = shift;
46              
47 2 50       10 unless (defined $path) {
48 2         17 return $self->{Path};
49             }
50              
51 0         0 $self->{Path} = $path;
52              
53             }
54              
55             sub todo {
56              
57 12     12 1 29 my $self = shift;
58 12         20 my $todo = shift;
59              
60 12 100       35 unless (defined $todo) {
61 9         58 return $self->{Todo};
62             }
63              
64 3 50       10 unless (ref $todo eq 'ARRAY') {
65 0         0 croak "todo() expects an array reference as argument";
66             }
67              
68 3         11 $self->{Todo} = $todo;
69              
70             }
71              
72             sub read {
73              
74 2     2 1 5 my $self = shift;
75 2         10 my $path = shift;
76              
77 2         4 my @todo;
78 2         5 my $str = '';
79              
80 2 50       137 open my $fh, '<', $path
81             or croak "Failed to open $path for reading: $!";
82              
83 2         96 while (my $l = readline $fh) {
84              
85 23         35 chomp $l;
86              
87 23 100       63 if ($l eq '--') {
88 9         12 chomp $str;
89 9         21 push @todo, $str;
90 9         40 $str = '';
91             } else {
92 14         43 $str .= $l . "\n";
93             }
94              
95             }
96              
97 2         31 close $fh;
98              
99 2         24 $self->{Todo} = \@todo;
100              
101             }
102              
103             sub write {
104              
105 3     3 1 6 my $self = shift;
106 3   33     18 my $path = shift // $self->{Path};
107              
108 3 50       565 open my $fh, '>', $path
109             or croak "Failed to open $path for writing: $!";
110              
111 3         12 for my $i (0 .. $#{$self->{Todo}}) {
  3         18  
112              
113 8         23 my $todo = $self->{Todo}->[$i];
114              
115 8 50       56 if ($todo =~ /(^|\n)--($|\n)/) {
116 0         0 croak "todo[$i] cannot contain a '--' line";
117             }
118              
119 8         16 say { $fh } $todo;
  8         49  
120 8         15 say { $fh } '--';
  8         17  
121              
122             }
123              
124 3         335 return 1;
125              
126             }
127              
128             sub tudo {
129              
130 2     2 1 1109 my $str = shift;
131 2   33     8 my $path = shift // default_todo;
132              
133 2         19 my $tudo = File::Tudo->new($path);
134              
135 2         4 my @new = @{$tudo->todo};
  2         7  
136              
137 2         6 push @new, $str;
138              
139 2         13 $tudo->todo(\@new);
140              
141 2         6 $tudo->write;
142              
143             }
144              
145             1;
146              
147             =head1 NAME
148              
149             File::Tudo - Tudo TODO file interface
150              
151             =head1 SYNOPSIS
152              
153             use File::Tudo qw(tudo);
154              
155             # Simple convenience wrapper, useful for quick scripts
156             tudo("Fix that one issue");
157              
158             # OO interface
159             my $tudo = File::Tudo.new('/path/to/TODO');
160             $tudo->todo([ 'New TODO list' ]);
161             $tudo->write;
162              
163             =head1 DESCRIPTION
164              
165             File::Tudo is a Perl module for reading/writing simple TODO files. It is a port
166             of a Raku (Perl 6) module of the same name.
167              
168             =head2 Subroutines
169              
170             The following subroutines can be imported.
171              
172             =head3 tudo($str, [ $path ])
173              
174             C is a simple convenience wrapper for File::Tudo that appends an
175             additional entry to the end of your TODO file. This can make it useful for
176             reporting TODOs from your Perl scripts.
177              
178             my @updates = get_package_updates(@pkgs);
179              
180             tudo("There are updates that need taken care of!") if @updates;
181              
182             C<$str> is the string you would like to add as an entry to your TODO file.
183              
184             C<$path> is an optional argument that lets you specify the path to your TODO
185             file. If C<$path> is not given, defaults to the return value of
186             C.
187              
188             =head3 default_todo()
189              
190             C returns the default path for your TODO file. It will either be
191             the path specified by the C environment variable if set, or
192             C<~/TODO> otherwise.
193              
194             =head2 Object-Oriented Interface
195              
196             =head3 Methods
197              
198             =head4 new([ $path, [ $params ] ])
199              
200             Returns a blessed File::Tudo object.
201              
202             C<$path> is the path to the TODO file. If not specified, defaults to the
203             return value of C.
204              
205             C<$params> is a hash ref of various parameters.
206              
207             =over 4
208              
209             =item read
210              
211             Boolean determining whether C will initialize its C array from the
212             TODO entries found in the C<$path>, or ignore them and initialize C with
213             an empty array.
214              
215             Defaults to true.
216              
217             =back
218              
219             =head4 path([ $path ])
220              
221             Setter/getter method for the object's path attribute. The path will be the path
222             that C will write to by default. Is intially set by the C<$path>
223             supplied in C.
224              
225             =head4 todo([ $todo ])
226              
227             Setter/getter method for the object's C attribute. C is an array
228             ref of TODOs.
229              
230             =head4 read($path)
231              
232             Reads a list of TODOs from C<$path>, overwriting the current array in C.
233              
234             =head4 write([ $path ])
235              
236             Write list of TODOs in C to C<$path>, if specified, or the path in the
237             C attribute otherwise.
238              
239             =head1 ENVIRONMENT
240              
241             =over 4
242              
243             =item TODO_FILE
244              
245             Default path to TODO file.
246              
247             =back
248              
249             =head1 AUTHOR
250              
251             Written by Samuel Young, Esamyoung12788@gmail.comE.
252              
253             =head1 BUGS
254              
255             Don't be ridiculous...
256              
257             Report bugs on my Codeberg, L.
258              
259             =head1 COPYRIGHT
260              
261             Copyright 2025, Samuel Young
262              
263             This program is free software; you can redistribute it and/or modify it
264             under the terms of the Artistic License 2.0.
265              
266             =head1 SEE ALSO
267              
268             L
269              
270             =cut