use Time::Local;
use Digest::MD5 qw(md5_hex);
use File::Basename;
+use POSIX;
my $trk_dir = "$ENV{HOME}/.trk";
START => 1,
TIMEFORMAT => 2,
STOP => 3,
+ EDIT => 4,
};
sub help
exit(-1);
}
-# Input to parse_time is:
-# * date -> date-string in the form YYYY-MM-DD
-# * time -> time-string in the form HH:MM
-# Return value is a unix timestamp, as returned by time()
-sub parse_time ($$)
-{
- my ( $Y, $M, $D ) = split ("-", shift );
- my ( $h, $m ) = split(":", shift );
- return timelocal(0, $m, $h, $D, ($M-1), $Y);
-}
sub gen_puuid (;$)
{
return $w;
}
+# Input to parse_time is:
+# * date -> date-string in the form YYYY-MM-DD
+# * time -> time-string in the form HH:MM
+# Return value is a unix timestamp, as returned by time()
+sub parse_time ($$)
+{
+ my ( $Y, $M, $D ) = split ("-", shift );
+ my ( $h, $m ) = split(":", shift );
+ return timelocal(0, $m, $h, $D, ($M-1), $Y);
+}
+
+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);
+}
+
+sub time2str ($)
+{
+ my $t = shift;
+ return strftime("%Y-%m-%d %H:%M", localtime($t));
+}
+
sub parse_arguments ($)
{
if ( ($step == START) || ($step == TASK) )
{
# TODO: Allow no title!
- # If no title is given, read ID of previously used project in stead :)
+ # If no title is given, read ID of previously used track in stead :)
help($step) unless $#ARGV > 3;
$title = join(" ", @ARGV[4..$#ARGV]);
}
$start_time = parse_time( $ARGV[2], $ARGV[3] );
}
- elsif ( ($step == START) || ($step == TASK) )
+ elsif ( ($step == START) || ($step == TASK) || ($step == EDIT))
{
shift(@ARGV);
$title = join(" ", @ARGV);
}
}
-sub get_current_project
+sub get_last_id
+{
+ return undef if ( ! -f $trk_dir . "/last" );
+ open ( CUR, "<" . $trk_dir . "/last" ) or die ("Unable to read last track file");
+ my $id = <CUR>;
+ chomp($id);
+ close(CUR);
+ return $id;
+}
+
+sub get_current_id
{
return undef if ( ! -f $trk_dir . "/current" );
- open ( CUR, "<" . $trk_dir . "/current" ) or die ("Unable to read current project file");
+ open ( CUR, "<" . $trk_dir . "/current" ) or die ("Unable to read current track file");
my $id = <CUR>;
chomp($id);
close(CUR);
return $id;
}
-sub set_current_project ($)
+sub set_current_id ($)
{
my $id = shift;
return undef if ( -f $trk_dir . "/current" );
- open ( CUR, ">" . $trk_dir . "/current" ) or die ("Unable to write current project file");
+ open ( CUR, ">" . $trk_dir . "/current" ) or die ("Unable to write current track file");
printf(CUR "%s\n", $id );
close(CUR);
- open ( LAST, ">" . $trk_dir . "/last" ) or die ("Unable to write last project file");
+ open ( LAST, ">" . $trk_dir . "/last" ) or die ("Unable to write last track file");
printf(LAST "%s\n", $id );
close(LAST);
}
-sub current_task
+sub get_tracks
{
- my $project = get_current_project();
- return undef if not $project;
-
- open ( CUR, "<" . $trk_dir . "/current" ) or die ("Unable to read current project file");
- <CUR>;
- my $id = <CUR>;
- chomp($id);
- close(CUR);
- return $id;
-
-}
-
-sub get_projects
-{
- my %projects;
+ my %tracks;
foreach my $d ( <$trk_dir/*> )
{
next if not -f $d . "/info";
my $id = basename($d);
- my $title = get_project_name( $id );
+ my $title = get_track_name( $id );
- $projects{$id} = $title unless not defined $title;
+ $tracks{$id} = $title unless not defined $title;
}
- return \%projects;
+ return \%tracks;
}
-sub get_project_id ($)
+sub get_track_id ($)
{
my $title = shift;
- # Get hash of project-id's and -names from get_projects
- my $projects = get_projects();
+ # Get hash of track-id's and -names from get_tracks
+ my $tracks = get_tracks();
# Look up name in list
- foreach my $id ( keys $projects )
+ foreach my $id ( keys $tracks )
{
# Return ID for name
- return $id if ( $projects->{$id} eq $title )
+ return $id if ( $tracks->{$id} eq $title )
}
# If no match, return undef.
return undef;
}
-sub get_project_name ($)
+sub get_track_name ($)
{
my $id = shift;
- open(PRO, "<" . $trk_dir . "/" . $id . "/info" ) or die ("Unable to read project medatata file!");
+ open(PRO, "<" . $trk_dir . "/" . $id . "/info" ) or die ("Unable to read track medatata file!");
my $title = undef;
while (<PRO>)
{
return $title;
}
-sub create_project ($)
+sub create_track ($)
{
my $title = shift;
} while ( -d $trk_dir . "/" . $id );
mkdir ( $trk_dir . "/" . $id );
- open(PRO, ">" . $trk_dir . "/" . $id . "/info" ) or die ("Unable to create project medatata file!");
- printf(PRO "title:%s", $title);
+ open(PRO, ">" . $trk_dir . "/" . $id . "/info" ) or die ("Unable to create track medatata file!");
+ printf(PRO "title:%s\n", $title);
close(PRO);
return $id;
}
+sub start_track ($$)
+{
+ my $start_time = shift;
+ my $title = shift;
+
+
+ my $current = get_current_id();
+ if ( not $current )
+ {
+ if ( not $title )
+ {
+ $current = get_last( );
+ }
+ else
+ {
+ $current = get_track_id( $title );
+ if ( not $current )
+ {
+ printf("No track by that name! Creating a new one.\n");
+ $current = create_track($title);
+ }
+ }
+
+ # Break off here if we haven't gotten an ID yet.
+ return undef if not $current;
+
+ set_current_id($current);
+
+ # First iteration is VERY naive: simply add the start time to the bottom of the tracking file
+ # Will have to do more logic: if the start point is before one of the times already in the track,
+ # the file will have to be manipulated to get coherent tracking!
+ open (TRACK, ">>" . $trk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
+ printf(TRACK "[%s]", time2str($start_time));
+ close (TRACK);
+
+ return $current;
+ }
+
+ return undef;
+}
+
+sub close_track ($)
+{
+
+ my $stop_time = shift;
+
+ my $current = get_current_id();
+
+ die ("Project exists, but tracking file does not!") if ( not -f $trk_dir . "/" . $current . "/tracking" );
+
+ # First iteration is VERY naive: simply add the stop time to the bottom line of the tracking file
+ # Will have to do more logic: if the start point is before one of the times already in the track,
+ # the file will have to be manipulated to get coherent tracking!
+ # In addtion to this: actually do some file sanity checking!
+ open (TRACK, ">>" . $trk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
+ printf(TRACK " to [%s]\n", time2str($stop_time));
+ close (TRACK);
+
+ unlink ( $trk_dir . "/current" );
+}
+
############################################################
if ( ! -d $trk_dir )
my ( $start_time, $title ) = parse_arguments(START);
- my $current = get_current_project();
+ my $current = get_current_id();
if ( not $current )
{
- $current = get_project_id( $title );
+ $current = start_track( $start_time, $title );
+
if ( not $current )
{
- printf("No project by that name! Creating a new one.\n");
- $current = create_project($title);
- }
- else
- {
- printf("Continuing tracking for existing project.\n");
+ printf("Something weird happened.\n");
+ exit(1);
}
- set_current_project($current);
}
else
{
- printf("A project is being tracked: %s\n", get_project_name( $current ) );
- printf("Stop current tracking before starting a new one\n");
- exit(0);
+ printf("A project is being tracked: %s\n", get_track_name( $current ) );
+ close_track($start_time);
+ $current = start_track( $start_time, $title );
}
- # First iteration is VERY naive: simply add the start time to the bottom of the tracking file
- # Will have to do more logic: if the start point is before one of the times already in the track,
- # the file will have to be manipulated to get coherent tracking!
- open (TRACK, ">>" . $trk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
- printf(TRACK "[%s]", $start_time);
- close (TRACK);
-
printf("Started tracking of '%s' at %s\n\n", $title, scalar localtime $start_time);
}
elsif ( ( $command eq "stop") || ($command eq "off" ) )
my $stop_time = parse_arguments(STOP);
- my $current = get_current_project();
+ my $current = get_current_id();
if ( not $current )
{
printf("No project is currently tracked. To stop, please start first\n");
exit(0);
}
- my $title = get_project_name( $current );
+ my $title = get_track_name( $current );
- die ("Project exists, but tracking file does not!") if ( not -f $trk_dir . "/" . $current . "/tracking" );
+ close_track($stop_time);
- # First iteration is VERY naive: simply add the stop time to the bottom line of the tracking file
- # Will have to do more logic: if the start point is before one of the times already in the track,
- # the file will have to be manipulated to get coherent tracking!
- # In addtion to this: actually do some file sanity checking!
- open (TRACK, ">>" . $trk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
- printf(TRACK " to [%s]\n", $stop_time);
- close (TRACK);
+ printf("Stopped tracking of '%s' at %s\n\n", $title, scalar localtime $stop_time);
+}
+elsif ( ( $command eq "projects" ) || ( $command eq "list" ) )
+{
+ # Todo/future extensions:
+ # TODO: Sort list of names alphabetically
+ # TODO: Get total-hours for projects
+ # TODO:
+ my $tracks = get_tracks();
+ printf("Currently tracked project names:\n\n");
+ my $current = get_current_id();
+
+ foreach my $id ( keys $tracks )
+ {
+ printf(" %s %s\n", ($id eq $current ? ">" : " " ),$tracks->{$id} );
+ }
+ print("\n");
+}
+elsif ( $command eq "edit" )
+{
- unlink ( $trk_dir . "/current" );
+ my ( undef, $title ) = parse_arguments(EDIT);
+ my $id = get_last_id();
- printf("Stopped tracking of '%s' at %s\n\n", $title, scalar localtime $stop_time);
+ if ( $title )
+ {
+ $id = get_track_id($title);
+ if ( not $id )
+ {
+ printf("No project by that name. Try 'list'\n");
+ exit(0);
+ }
+ }
+
+ system( "/usr/bin/editor " . $trk_dir . "/" . $id . "/tracking" );
}
else
{