X-Git-Url: https://git.defcon.no/?a=blobdiff_plain;ds=sidebyside;f=trk;h=6629a7c0c9ee4cf6199e9f38de384dd7b784a0ca;hb=HEAD;hp=8940a49c20c4ea5f3db6cb2e230b6826463b5fee;hpb=9b25de5fdef80e56d5f83c66f23d56d98c498ce3;p=trk diff --git a/trk b/trk index 8940a49..6629a7c 100755 --- a/trk +++ b/trk @@ -1,4 +1,25 @@ #!/usr/bin/perl +# +# Copyright © Jon Langseth +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + use Time::Local; use Digest::MD5 qw(md5_hex); use File::Basename; @@ -6,6 +27,11 @@ use POSIX; use strict; my $trk_dir = "$ENV{HOME}/.trk"; +if ( $ENV{TRK_DIR} ) +{ + if ( -d $ENV{TRK_DIR} ) { $trk_dir = $ENV{TRK_DIR} if -d $ENV{TRK_DIR}; } + else { printf("Environment variable TRK_DIR is not a directory\n"); exit(1); } +} use constant { START => 1, @@ -18,13 +44,18 @@ use constant { sub help { my $code = shift; - printf("It seems you require assistance\n"); - if ( $code ) - { - printf("How to start\n") if $code == START; - printf("How to time\n") if $code == TIMEFORMAT; - } + printf("Error in invocation. Syntax summary:\n\n"); + printf(" %s {start|on} [at yyyy-mm-dd hh:mm] \n", $0); + printf(" %s {stop|off} [at yyyy-mm-dd hh:mm] \n", $0); + printf(" %s {activity|task} [at yyyy-mm-dd hh:mm] \n", $0); + printf(" %s main [at yyyy-mm-dd hh:mm]\n", $0); + printf(" %s {projects|list} [verbose]\n", $0); + printf(" %s report [{terse|standard|verbose|details}] []\n", $0); + printf(" %s edit \n", $0); + printf(" %s status\n", $0); + printf("\nSee README.txt for more information\n"); + exit(-1); } @@ -70,7 +101,6 @@ sub parse_time ($$) sub str2time ($) { my $i = shift; - printf("%s\n", $i); return 0 if not $i =~ m/(\d\d\d\d-\d\d-\d\d) (\d\d:\d\d)/; return parse_time($1, $2); } @@ -81,6 +111,16 @@ sub time2str ($) return strftime("%Y-%m-%d %H:%M", localtime($t)); } +sub delta2str ($) +{ + my $delta = shift; + my $t = $delta; + my $hours = $t / 3600; + $t = $delta % 3600; + my $minutes = $t / 60; + return sprintf("%d hours %d minutes", $hours, $minutes); +} + sub parse_arguments ($) { @@ -198,7 +238,7 @@ sub get_track_id ($;$) my $tracks = get_tracks($trk_id); # Look up name in list - foreach my $id ( keys $tracks ) + foreach my $id ( keys %$tracks ) { # Return ID for name return $id if ( $tracks->{$id} eq $title ) @@ -315,6 +355,78 @@ sub close_track ($;$) unlink ( $wrk_dir . "/current" ); } + +sub report ($$;$) +{ + my $current = shift; + my $silent = shift; + my $trk_id = shift; + my $wrk_dir = $trk_dir; + $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id; + + my $total = 0; + + my $name = get_track_name( $current, $trk_id ); + printf("# Report for '%s':\n\n", $name) unless $silent; + + my $check = get_current_id( $trk_id ); + + open (TRACK, "<" . $wrk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!"); + while ( ) + { + next if not $_ =~ m/\[(.*)\] to \[(.*)\]/; + my $start = $1; + my $end = $2; + my $t_start = str2time( $start ); + my $t_end = str2time( $end ); + my $delta = $t_end - $t_start; + + if ( not $silent ) + { + printf(" %s to %s => %s\n", $start, $end, delta2str($delta) ); + } + $total += $delta; + + + } + close ( TRACK ); + + if ( $check eq $current ) + { + my $t; + if ( $t = current_starttime( $trk_id ) ) + { + my $delta = time - $t; + printf(" %s to NOW (active) => %s\n", time2str( $t ), delta2str( $delta ) ) if not $silent; + $total += $delta; + } + } + + return $total; + +} + +sub current_starttime (;$) +{ + my $trk_id = shift; + my $wrk_dir = $trk_dir; + $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id; + + my $line = undef; + + my $current = get_current_id( $trk_id ); + return 0 if not $current; + + open (TRACK, "<" . $wrk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!"); + while ( ) + { + $line = $_; + } + close ( TRACK ); + return 0 if not $line =~ m/^\[(\d\d\d\d-\d\d-\d\d \d\d:\d\d)\]$/; + return str2time($1); +} + ############################################################ if ( ! -d $trk_dir ) @@ -459,6 +571,7 @@ elsif ( $command eq "main" ) printf("Stopped tracking of '%s' at %s\n\n", $title, scalar localtime $stop_time); } } +#### Mark elsif ( ( $command eq "projects" ) || ( $command eq "list" ) ) { # Todo/future extensions: @@ -469,12 +582,170 @@ elsif ( ( $command eq "projects" ) || ( $command eq "list" ) ) printf("Currently tracked project names:\n\n"); my $current = get_current_id(); - foreach my $id ( keys $tracks ) + #foreach my $id ( keys %$tracks ) + foreach my $id ( sort { $tracks->{$a} cmp $tracks->{$b} || $a cmp $b } keys %$tracks ) { - printf(" %s %s\n", ($id eq $current ? ">" : " " ),$tracks->{$id} ); + + if (( $#ARGV >= 1) && ( $ARGV[1] eq "verbose" )) + { + printf(" %s %s %s\n", ($id eq $current ? ">" : " " ), $id , $tracks->{$id}); + } + else + { + printf(" %s %s\n", ($id eq $current ? ">" : " " ),$tracks->{$id} ); + } } print("\n"); } +#### Mark +elsif ( ( $command eq "activities" ) || ( $command eq "tasks" ) ) +{ + # Todo/future extensions: + # TODO: Sort list of names alphabetically + # TODO: Get total-hours for projects + # TODO: + + + my $trk_id = get_current_id(); + if ( not $trk_id ) + { + printf("Starting a task/activity requires an active main track.\n"); + exit(1); + } + + my $verbose = (( $#ARGV >= 1) && ( $ARGV[1] eq "verbose" )); + + my $tracks = get_tracks( $trk_id ); + printf("Current track is '%s'\n", get_track_name( $trk_id )); + printf("Track ID for for current track is %s\n", $trk_id) if $verbose; + printf("Currently tracked activities/tasks for track '%s':\n\n", get_track_name( $trk_id )); + my $current = get_current_id( $trk_id ); + + #foreach my $id ( keys %$tracks ) + foreach my $id ( sort { $tracks->{$a} cmp $tracks->{$b} || $a cmp $b } keys %$tracks ) + { + + if ( $verbose ) + { + printf(" %s %s %s\n", ($id eq $current ? ">" : " " ), $id , $tracks->{$id}); + } + else + { + printf(" %s %s\n", ($id eq $current ? ">" : " " ),$tracks->{$id} ); + } + } + print("\n"); +} +elsif ( $command eq "report" ) +{ + + my $format = "standard"; + my $output = 0; + + if (( $#ARGV >= 1) && + ( ( $ARGV[1] eq "standard" ) + || ( $ARGV[1] eq "terse" ) + || ( $ARGV[1] eq "verbose" ) + || ( $ARGV[1] eq "details" ) ) ) + { + $format = $ARGV[1]; + shift @ARGV; + } + + $output = 0 if $format eq "terse"; + $output = 1 if $format eq "standard"; + $output = 2 if $format eq "verbose"; + $output = 3 if $format eq "details"; + + my ( undef, $title ) = parse_arguments(START); + + printf("Report format: %s\nTitle: %s\n", $format, $title); + + my $track = undef; + + if ( $title ) + { + $track = get_track_id( $title ); + } + else + { + $track = get_last_id(); + } + + if ( not $track ) + { + printf ("Unable to get info for that track\n"); + exit(1); + } + + my $total = 0; + my $subtotals = 0; + + my $activities = get_tracks( $track ); + if ( keys %$activities ) + { + printf("# Reporting for sub-task/activities:\n\n") if $output >= 2; + + foreach my $id ( sort { $activities->{$a} cmp $activities->{$b} || $a cmp $b } keys %$activities ) + #foreach my $id ( keys %$activities ) + { + $subtotals += report( $id, ( $output >= 2 ? 0 : 1 ), $track ); + printf("# --------------------------------------------------------------\n\n") if $output >= 2; + } + } + + printf("# Reporting for main track/project/task\n") if $output >= 2; + $total += report($track, ( ( $output >= 1 ? 0 : 1 ) ) ); + printf("\n# ==============================================================\n\n") if $output >= 2; + print("\n") if $output >= 1; + + + printf("Total: %s\n", delta2str($total) ); + + if ( $output >= 2 ) + { + printf("Time logged on tasks: %s\n", delta2str($subtotals) ); + } + + print("# End of report\n") if $output >= 1; + +} +elsif ( $command eq "status" ) +{ + + my $trk_id = get_current_id(); + if ( not $trk_id ) + { + printf("Not currently tracking anything.\n"); + $trk_id = get_last_id(); + if ( $trk_id ) + { + printf("Last track was: %s\n", get_track_name( $trk_id ) ); + } + exit(1); + } + printf("Currently tracking: %s\n", get_track_name( $trk_id ) ); + my $t = current_starttime(); + printf("Tracking started at %s\n", scalar localtime $t); + printf("Time elapsed since start of session: %s\n", delta2str(time - $t) ); + + my $activity = get_current_id( $trk_id ); + if ( $activity ) + { + printf("\nCurrent sub-task/activity is: %s\n", get_track_name( $activity, $trk_id ) ); + my $t = current_starttime($trk_id); + printf("Activity started at %s\n", scalar localtime $t); + printf("Time elapsed since start of activity: %s\n", delta2str(time - $t) ); + } + else + { + $activity = get_last_id( $trk_id ); + if ( $activity ) + { + printf("\nLast track was: %s\n", get_track_name( $activity, $trk_id ) ); + } + } +} elsif ( $command eq "edit" ) {