File Coverage

blib/lib/App/JobLog/Command/edit.pm
Criterion Covered Total %
statement 27 81 33.3
branch 0 28 0.0
condition 0 3 0.0
subroutine 9 16 56.2
pod 3 6 50.0
total 39 134 29.1


line stmt bran cond sub pod time code
1             package App::JobLog::Command::edit;
2             $App::JobLog::Command::edit::VERSION = '1.040';
3             # ABSTRACT: edit the log
4              
5 2     2   1618 use App::JobLog -command;
  2         5  
  2         15  
6 2     2   723 use Modern::Perl;
  2         3  
  2         12  
7 2         12 use Class::Autouse qw{
8             App::JobLog::Log
9             App::JobLog::Log::Line
10             Digest::MD5
11             FileHandle
12 2     2   311 };
  2         5  
13 2     2   158 use autouse 'File::Temp' => qw(tempfile);
  2         3  
  2         11  
14 2     2   444 use autouse 'File::Copy' => qw(copy);
  2         2  
  2         8  
15 2     2   343 use autouse 'App::JobLog::Config' => qw(editor log);
  2         9  
  2         12  
16 2     2   297 use autouse 'Getopt::Long::Descriptive' => qw(prog_name);
  2         4  
  2         9  
17 2     2   121 use autouse 'App::JobLog::TimeGrammar' => qw(parse);
  2         5  
  2         7  
18 2     2   111 use autouse 'App::JobLog::Time' => qw(now);
  2         3  
  2         7  
19              
20             sub execute {
21 0     0 1   my ( $self, $opt, $args ) = @_;
22 0 0 0       if ( $opt->close || $opt->validate ) {
    0          
23 0           eval {
24 0           my $log = App::JobLog::Log->new;
25 0 0         if ( $opt->close ) {
26 0           my $time = join ' ', @$args;
27 0           my ($s) = parse($time);
28 0 0         $self->usage_error(
29             'you may only insert closing times prior to present')
30             unless $s < now;
31 0           my ( $e, $i ) = $log->find_previous($s);
32 0 0         $self->usage_error('log does not contain appropriate event')
33             unless $e;
34 0 0         $self->usage_error('no open event at this time')
35             unless $e->is_open;
36 0           $log->insert( $i + 1,
37             App::JobLog::Log::Line->new( time => $s, done => 1 ) );
38             }
39 0 0         if ( $opt->validate ) {
40 0           my $errors = $log->validate;
41 0           _error_report($errors);
42             }
43             };
44 0 0         $self->usage_error($@) if $@;
45             }
46             elsif ( my $editor = editor ) {
47 0 0         if ( my $log = log ) {
48 0           my ( $fh, $fn ) = tempfile;
49 0           binmode $fh;
50 0           copy( $log, $fh );
51 0           $fh->close;
52 0           $fh = FileHandle->new($log);
53 0           my $md5 = Digest::MD5->new;
54 0           my $md51 = $md5->addfile($fh)->hexdigest;
55 0           system "$editor $log";
56 0           $fh = FileHandle->new($log);
57 0           my $md52 = $md5->reset->addfile($fh)->hexdigest;
58              
59 0 0         if ( $md51 ne $md52 ) {
60 0           $fh = FileHandle->new( "$log.bak", 'w' );
61 0           copy( $fn, $fh );
62 0           $fh->close;
63 0           say "saved backup log in $log.bak";
64 0           my $errors = App::JobLog::Log->new->validate;
65 0           _error_report($errors);
66             }
67             else {
68 0           unlink $fn;
69             }
70             }
71             else {
72 0           say 'nothing in log to edit';
73             }
74             }
75             else {
76 0 0         $self->usage_error('no editor specified') unless $opt->close;
77             }
78             }
79              
80             sub usage_desc {
81 0     0 1   '%c ' . __PACKAGE__->name . ' [--validate] [-c ]';
82             }
83              
84 0     0 1   sub abstract { 'open a text editor to edit the log' }
85              
86             sub full_description {
87 0     0 0   <
88             Close an open task or open a text editor to edit the log.
89              
90             Closing an open task is the only edit you'll commonly have to make (it's
91             easy to forget to close the last task of the day). Fortunately, it is the easiest
92             edit to perform. You simply type
93              
94 0           @{[prog_name]} @{[__PACKAGE__->name]} --close yesterday at 8:00 pm
  0            
95              
96 0           for example and @{[prog_name]} will insert the appropriate line if it can do so.
97             If it can't because there is no open task at the time specified, it will emit a warning
98             instead.
99              
100 0           The date and time parsing is handled by the same code used by the @{[App::JobLog::Command::summary->name]} command,
101             so what works for one works for the other. One generally does not specify hours and such
102 0           for summaries, but @{[prog_name]} will understand most common natural language time expressions.
103              
104             If you need to do more extensive editing of the log this command will open a text editor
105             for you and confirm the validity of the log after you save, commenting out
106             ill-formed lines and printing a warning. This command requires the you
107             to have set editor configuration parameter to specify a text.
108             The text editor must be invokable like so,
109              
110            
111            
112             That is, you must be able to specify the file to edit as an argument. If the editor
113             requires any additional arguments or options you must provide those via the
114             environment variable.
115             END
116             }
117              
118             sub options {
119             return (
120             [
121 0     0 0   'close|close-task|c' =>
122             'add a "DONE" line to the log at the specified moment'
123             ],
124             [ 'validate|v' => 'check log for errors, commenting out any found' ],
125             );
126             }
127              
128             sub _error_report {
129 0     0     my $errors = shift;
130              
131 0 0         if ($errors) {
132 0           say "errors found: $errors";
133 0           say 'Error messages have been inserted into the log. Please edit.';
134             }
135             else {
136 0           say 'log is valid';
137             }
138             }
139              
140             sub validate {
141 0     0 0   my ( $self, $opt, $args ) = @_;
142              
143 0 0         if ( $opt->close ) {
144 0 0         $self->usage_error('no time expression provided') unless @$args;
145             }
146             }
147              
148             1;
149              
150             __END__