App-tt
view release on metacpan or search on metacpan
$self->{config}{lc($1)} = $2;
}
}
$self->{defaults} ||= {
editor => $ENV{EDITOR} || 'nano',
export_columns => $ENV{TT_COLUMNS} || 'date,project,hours,rounded,tags,description',
hours_per_month => $ENV{TT_HOURS_PER_MONTH} || 0,
min_time => $ENV{TT_MIN_TIME} || 300,
round_up_at => $ENV{TT_ROUND_UP_AT} || 30,
};
}
return $self->{config}{$key} // $self->{defaults}{$key} // die "Missing option '$key'.\n";
}
sub _edit_with_editor {
my ($self, $trc_file) = @_;
my $prev = $trc_file ? 0 : 1;
my $event = $prev ? $self->_get_previous_event : $self->_load($trc_file);
$trc_file = $event->{path} //= 'Not found';
die "Could not find file to edit. ($event->{path})\n" unless $event->{start};
my $fh = File::Temp->new;
printf $fh "# %s\n", $event->{path};
for my $k (qw(project tags description start stop user)) {
$event->{$k} = join ', ', @{$event->{$k} || []} if $k eq 'tags';
$event->{$k} = $event->{$k}->datetime if $k eq 'start' or $k eq 'stop' and $event->{$k};
printf $fh "%-12s %s\n", "$k:", $event->{$k} // '';
}
close $fh;
$self->_print("Edit $event->{path}");
system $self->config('editor') => "$fh";
for (split /\n/, App::tt::file->new("$fh")->slurp) {
my ($k, $v) = /^(\w+)\s*:\s*(.+)/ or next;
$v = [grep {length} split /[\s,]+/, $v] if $k eq 'tags';
$v = $self->_time(str => $v) if $k eq 'start';
$v = $self->_time(str => $v, ref => $event->{start}) if $k eq 'stop';
$event->{$k} = $v;
}
return $! unless $self->_save($event);
$self->home->child('previous')->spurt($event->{path}) if $prev;
unlink $trc_file or die "rm $trc_file: $!" unless $trc_file eq $event->{path};
return 0;
}
sub _fill_event {
my ($self, $event) = @_;
my $project = $self->project;
$project ||= App::tt::file->new->basename if -d '.git';
$project ||= $self->config('project');
$event->{__CLASS__} ||= 'App::TimeTracker::Data::Task';
$event->{project} ||= $project;
$event->{seconds} ||= 0;
$event->{user} ||= scalar(getpwuid $<);
$event->{tags} ||= [$self->_tags];
$event->{description} ||= $self->description // '';
return $event;
}
sub _print {
my ($self, $data, @args) = @_;
if (ref $data eq 'ARRAY') {
my $th = $data->[0][-1] eq '{X}' ? 1 : 0;
my @margin = $PTY ? ('') : ();
my ($width, @lines, @spec);
for my $row (@$data) {
push @lines, $row and next unless ref $row eq 'ARRAY';
my $w = 0;
for my $col (0 .. $#$row) {
($row->[$col] //= '') =~ y/\r\n//d;
my $len = length $row->[$col];
$spec[$col] = $len if $len >= ($spec[$col] // 0);
$w += $spec[$col] + 2;
}
$width = $w if $w >= ($width // 0);
}
$width -= 2;
my @fm = (map({"\%-${_}s"} @spec[0 .. $#spec - 1]), '%s');
$data = join '', map {
ref $_
? sprintf join(' ', @margin, @fm[0 .. $#$_]) . "\n", @$_
: ' ' . ($_ x $width) . "\n";
} @$data;
}
my $fh = $self->{stdout} ||= \*STDOUT;
if ($data =~ s/^(\d*)(>|!)\s//) {
$fh = $self->{stderr} ||= \*STDERR if $1 eq '2' || $2 eq '!';
$data = "\n$data\n";
$data =~ s!\n!\n !g if $PTY;
}
return print {$fh} "$data\n" if @_ == 2;
return printf {$fh} "$data\n", @args;
}
sub _fill_log_days {
my ($self, $last, $now) = @_;
my $interval = int(($now - $last)->days);
map {
my $t = $last + $_ * 86400;
+{seconds => 0, start => $t, tags => [$t->day]}
} 1 .. $interval;
}
sub _get_previous_event {
my $self = shift;
# $ROOT/previous contains path to last .trc file
( run in 1.460 second using v1.01-cache-2.11-cpan-39bf76dae61 )