App-JobLog

 view release on metacpan or  search on metacpan

lib/App/JobLog/Command/add.pm  view on Meta::CPAN

    }
    my $log        = App::JobLog::Log->new;
    my ($last)     = $log->last_event;
    my $is_ongoing = $last && $last->is_open;
    $log->append_event(
        $tags ? ( tags => $tags ) : (),
        description => [ join ' ', @$args ],
        time        => now
    );
    if ( $is_ongoing && _different_day( $last->start, now ) ) {
        say 'Event spans midnight. Perhaps you failed to close the last event.';
    }
}

sub _different_day {
    my ( $d1, $d2 ) = @_;
    return !( $d1->year == $d2->year
        && $d1->month == $d2->month
        && $d1->day == $d2->day );
}

lib/App/JobLog/Command/configure.pm  view on Meta::CPAN

  WORKDAYS
);
use autouse 'App::JobLog::TimeGrammar' => qw(parse);
no if $] >= 5.018, warnings => "experimental::smartmatch";

sub execute {
    my ( $self, $opt, $args ) = @_;
    _list_params() if $opt->list;
    if ( defined $opt->precision ) {
        my $precision = precision( $opt->precision );
        say "precision set to $precision";
    }
    if ( defined $opt->start_pay_period ) {
        eval {
            my ($s) = parse( $opt->start_pay_period );
            my $d = start_pay_period($s);
            say 'beginning of pay period set to ' . $d->strftime('%F');
        };
        $self->usage_error(
            'could not understand date: ' . $opt->start_pay_period )
          if $@;
    }
    if ( defined $opt->length_pay_period ) {
        my $length_pp = pay_period_length( $opt->length_pay_period );
        say "length of pay period in days set to $length_pp";
    }
    if ( defined $opt->day_length ) {
        my $day_length = day_length( $opt->day_length );
        say "length of work day set to $day_length";
    }
    if ( defined $opt->workdays ) {
        my $days = uc $opt->workdays;
        my %days = map { $_ => 1 } split //, $days;
        my @days;
        for ( split //, DAYS ) {
            push @days, $_ if $days{$_};
        }
        $days = join '', @days;
        $days = workdays($days);
        say "workdays set to $days";
    }
    if ( defined $opt->sunday_begins_week ) {
        my $bool;
        for ( $opt->sunday_begins_week ) {
            when (/true/i)  { $bool = 1 }
            when (/false/i) { $bool = 0 }
            default { $bool = $opt->sunday_begins_week || 0 };
        }
        $bool = sunday_begins_week($bool);
        say "Sunday begins week is now " . ( $bool ? 'true' : 'false' );
    }
    if ( defined $opt->merge ) {
        my $m = lc $opt->merge;
        $m =~ s/^\s++|\s++$//g;
        $m =~ s/\s++/ /g;
        my $value = merge($m);
        say "merge level is now '$value'";
    }
    if ( defined $opt->editor ) {
        my $value = editor( $opt->editor );
        say "log editor is now $value";
    }
    if ( defined $opt->hidden_columns ) {
        my @cols = map { my $v = $_; lc $v } @{ $opt->hidden_columns };
        my %cols = map { $_ => 1 } @cols;
        my $value = join ' ', sort keys %cols;
        $value = hidden_columns($value);
        say "hidden columns: $value";
    }
    if ( defined $opt->time_zone ) {
        my $value = time_zone( $opt->time_zone );
        say "time zone is now $value";
    }
}

sub usage_desc { '%c ' . __PACKAGE__->name . ' %o' }

sub abstract { 'set or display various parameters' }

sub options {
    return (
        [

lib/App/JobLog/Command/done.pm  view on Meta::CPAN

sub execute {
    my ( $self, $opt, $args ) = @_;
    $self->simple_command_check($args);

    my $log = App::JobLog::Log->new;
    my ($last) = $log->last_event;
    if ( $last && $last->is_open ) {
        $log->append_event( done => 1 );
    }
    else {
        say 'No currently open event in log.';
    }
}

sub usage_desc { '%c ' . __PACKAGE__->name }

sub abstract { 'mark current task as done' }

1;

__END__

lib/App/JobLog/Command/edit.pm  view on Meta::CPAN

            my $md5  = Digest::MD5->new;
            my $md51 = $md5->addfile($fh)->hexdigest;
            system "$editor $log";
            $fh = FileHandle->new($log);
            my $md52 = $md5->reset->addfile($fh)->hexdigest;

            if ( $md51 ne $md52 ) {
                $fh = FileHandle->new( "$log.bak", 'w' );
                copy( $fn, $fh );
                $fh->close;
                say "saved backup log in $log.bak";
                my $errors = App::JobLog::Log->new->validate;
                _error_report($errors);
            }
            else {
                unlink $fn;
            }
        }
        else {
            say 'nothing in log to edit';
        }
    }
    else {
        $self->usage_error('no editor specified') unless $opt->close;
    }
}

sub usage_desc {
    '%c ' . __PACKAGE__->name . ' [--validate] [-c <date and time>]';
}

lib/App/JobLog/Command/edit.pm  view on Meta::CPAN

              'add a "DONE" line to the log at the specified moment'
        ],
        [ 'validate|v' => 'check log for errors, commenting out any found' ],
    );
}

sub _error_report {
    my $errors = shift;

    if ($errors) {
        say "errors found: $errors";
        say 'Error messages have been inserted into the log. Please edit.';
    }
    else {
        say 'log is valid';
    }
}

sub validate {
    my ( $self, $opt, $args ) = @_;

    if ( $opt->close ) {
        $self->usage_error('no time expression provided') unless @$args;
    }
}

lib/App/JobLog/Command/last.pm  view on Meta::CPAN

      last if $test->($e);
   }

   if ($e) {
      my $start = $e->start->strftime('%F at %H:%M:%S %p');
      my $end = $e->is_open ? 'now' : $e->end->strftime('%F at %H:%M:%S %p');
      $opt->{merge} = 'no_merge';
      App::JobLog::Command::summary->execute( $opt, ["$start - $end"] );
   }
   else {
      say $count ? 'no matching event' : 'empty log';
   }
}

sub usage_desc { '%c ' . __PACKAGE__->name }

sub abstract { 'describe the last task recorded' }

sub options {
   return (
      [

lib/App/JobLog/Command/parse.pm  view on Meta::CPAN

use App::JobLog -command;
use autouse 'App::JobLog::TimeGrammar' => qw(parse);

use Modern::Perl;

sub execute {
    my ( $self, $opt, $args ) = @_;
    my $expression = join ' ', @$args;
    eval {
        my ( $s, $e, $is_interval ) = parse $expression;
        say <<END;
        
received:          $expression
start time:        $s
end time:          $e
received interval: @{[$is_interval ? 'true' : 'false']}
END
    };
    $self->usage_error($@) if $@;
}

lib/App/JobLog/Command/tags.pm  view on Meta::CPAN

            $events = App::JobLog::Log->new->$method;
        }
    };
    $self->usage_error($@) if $@;
    my %tags;
    for my $e (@$events) {
        $tags{$_} = 1 for @{ $e->tags };
    }
    if (%tags) {
        print "\n";
        say $_ for sort keys %tags;
        print "\n";
    }
    else {
        say 'no tags in log';
    }
}

sub usage_desc { '%c ' . __PACKAGE__->name . ' %o [date or date range]' }

sub abstract {
    'list tags employed in log or some subrange thereof';
}

sub full_description {

lib/App/JobLog/Command/vacation.pm  view on Meta::CPAN

    $vacation->close;
}

sub _show {
    my ($vacation) = @_;
    my $lines = $vacation->show;
    if (@$lines) {
        print $_ for @$lines;
    }
    else {
        say 'no vacation times recorded';
    }
}

sub usage_desc { '%c ' . __PACKAGE__->name . ' %o [<description>]' }

sub abstract { 'list or define days off' }

sub options {
    return (
        [ 'list|l', 'show all vacation times recorded', ],

lib/App/JobLog/Command/when.pm  view on Meta::CPAN

            print <<END;

WARNING! The last event in the log has been open since before 12:00 am today!

END
        }
    }
    my $remaining = 0;
    $remaining += $_->time_remaining for @$days;
    if ( $remaining == 0 ) {
        say "\nyou are just now done";
    }
    else {
        my $then = now->add( seconds => $remaining );
        my $format;
        if ( $then->year == now->year ) {
            my $delta = abs $then->delta_days(now)->in_units('days');
            if ( $delta > 7 ) {
                $format = SAME_YEAR_FORMAT;
            }
            elsif ( $then->month == now->month && $then->day == now->day ) {

lib/App/JobLog/Command/when.pm  view on Meta::CPAN

            }
            else {
                $format = SAME_WEEK_FORMAT;
            }
        }
        else {
            $format = FULL_FORMAT;
        }
        if ( $then < now ) {
            $then = ( $days->[-1]->last_event->end // now )->add( seconds => $remaining );
            say "\nyou were finished at " . $then->strftime($format);
        }
        else {
            say "\nyou will be finished at " . $then->strftime($format);
        }
        print "\n";
    }
}

sub usage_desc { '%c ' . __PACKAGE__->name . ' %o <date or date range>' }

sub abstract {
    'report when work is done for the day';
}

lib/App/JobLog/Log/Day.pm  view on Meta::CPAN

        push @lines, [ $s->time_fmt ] if $show_times;
        push @lines, [ duration( $s->duration ) ] if $show_durations;
        push @lines, wrap( $s->tag_string, $tag_width ) if $show_tags;
        push @lines, $screen_width == -1
          ? [ $s->description ]
          : wrap( $s->description, $description_width )
          if $show_descriptions;
        my $count = _pad_lines( \@lines );

        for my $i ( 0 .. $count ) {
            say sprintf $format, _gather( \@lines, $i );
        }
    }
    print "\n"
      if $show_times
          || $show_durations
          || $show_tags
          || $show_descriptions
          || $show_date;
}

lib/App/JobLog/Log/Format.pm  view on Meta::CPAN

                printf $format, 'UNTAGGED', duration( $times->{untagged} )
                  if $times->{untagged};
                for my $key ( sort keys %{ $times->{tags} } ) {
                    my $d = $times->{tags}{$key};
                    printf $format, $key, duration($d);
                }
            }
        }
    }
    else {
        say 'No events in interval specified.';
    }
}

# generate printf format for synopses
# returns format and wrap widths for tags and descriptions
sub _define_format {
    my ( $synopses, $hash, $screen_width ) = @_;

    #determine maximum width of each column
    my $widths;

lib/App/JobLog/TimeGrammar.pm  view on Meta::CPAN

  use DateTime;
  use App::JobLog::Time qw(tz);
  use App::JobLog::TimeGrammar qw(parse);
  
  # for demonstration purposes we modify "today"
  $App::JobLog::Time::today =
    DateTime->new( year => 2011, month => 2, day => 17, time_zone => tz );

  for my $phrase ( 'Monday until the end of the week', 'Tuesday at 9:00 p.m.' ) {
      my ( $start, $end, $endpoints ) = parse($phrase);
      say $phrase;
      say "$start - $end; both endpoints specified? "
        . ( $endpoints ? 'yes' : 'no' );
  }

produces

  Monday until the end of the week
  2011-02-14T00:00:00 - 2011-02-20T23:59:59; both endpoints specified? yes
  Tuesday at 9:00 p.m.
  2011-02-08T21:00:00 - 2011-02-15T23:59:59; both endpoints specified? no



( run in 3.476 seconds using v1.01-cache-2.11-cpan-d7a12ab2c7f )