]>
git.defcon.no Git - trk/blob - trk
f1cee049c035c27a34bc9601e6731bd6f71a818e
3 use Digest
::MD5
qw(md5_hex);
8 my $trk_dir = "$ENV{HOME}/.trk";
11 if ( -d
$ENV{TRK_DIR
} ) { $trk_dir = $ENV{TRK_DIR
} if -d
$ENV{TRK_DIR
}; }
12 else { printf("Environment variable TRK_DIR is not a directory\n"); exit(1); }
26 printf("It seems you require assistance\n");
30 printf("How to start\n") if $code == START
;
31 printf("How to time\n") if $code == TIMEFORMAT
;
39 my $id_length = shift;
40 $id_length = 32 if not defined $id_length;
44 for(my $i=0 ; $i<128;)
46 my $tc = chr(int(rand(127)));
47 if($tc =~ /[a-zA-Z0-9]/)
55 while ( length($w) < $id_length )
57 $w .= gen_puuid
( $id_length - length( $w ) );
60 $w = substr( $w, 0, $id_length );
64 # Input to parse_time is:
65 # * date -> date-string in the form YYYY-MM-DD
66 # * time -> time-string in the form HH:MM
67 # Return value is a unix timestamp, as returned by time()
70 my ( $Y, $M, $D ) = split ("-", shift );
71 my ( $h, $m ) = split(":", shift );
72 return timelocal
(0, $m, $h, $D, ($M-1), $Y);
78 return 0 if not $i =~ m/(\d\d\d\d-\d\d-\d\d) (\d\d:\d\d)/;
79 return parse_time
($1, $2);
85 return strftime
("%Y-%m-%d %H:%M", localtime($t));
88 sub parse_arguments
($)
93 my $start_time = time;
96 if (( $#ARGV >= 1) && ( $ARGV[1] eq "at" ))
98 # Start and Activity require a title to be present.
99 # All other (stop, main...) do not ^^.
100 if ( ($step == START
) || ($step == TASK
) )
102 # TODO: Allow no title!
103 # If no title is given, read ID of previously used track in stead :)
104 help
($step) unless $#ARGV > 3;
105 $title = join(" ", @ARGV[4..$#ARGV]);
107 help
(TIMEFORMAT
) unless ( $ARGV[2] =~ m/\d\d\d\d-\d\d-\d\d/ && $ARGV[3] =~ m/\d\d:\d\d/);
109 $start_time = parse_time
( $ARGV[2], $ARGV[3] );
111 elsif ( ($step == START
) || ($step == TASK
) || ($step == EDIT
))
114 $title = join(" ", @ARGV);
117 if ( not defined $title )
123 return ( $start_time, $title );
130 my $wrk_dir = $trk_dir;
131 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
133 return undef if ( ! -f
$wrk_dir . "/last" );
134 open ( CUR
, "<" . $wrk_dir . "/last" ) or die ("Unable to read last track file");
141 sub get_current_id
(;$)
144 my $wrk_dir = $trk_dir;
145 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
147 return undef if ( ! -f
$wrk_dir . "/current" );
148 open ( CUR
, "<" . $wrk_dir . "/current" ) or die ("Unable to read current track file");
155 sub set_current_id
($;$)
159 my $wrk_dir = $trk_dir;
160 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
162 return undef if ( -f
$wrk_dir . "/current" );
163 open ( CUR
, ">" . $wrk_dir . "/current" ) or die ("Unable to write current track file");
164 printf(CUR
"%s\n", $id );
167 open ( LAST
, ">" . $wrk_dir . "/last" ) or die ("Unable to write last track file");
168 printf(LAST
"%s\n", $id );
175 my $wrk_dir = $trk_dir;
176 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
181 foreach my $d ( <$wrk_dir/*> )
184 next if not -f
$d . "/info";
186 my $id = basename
($d);
187 my $title = get_track_name
( $id, $trk_id );
189 $tracks{$id} = $title unless not defined $title;
196 sub get_track_id
($;$)
201 # Get hash of track-id's and -names from get_tracks
202 my $tracks = get_tracks
($trk_id);
204 # Look up name in list
205 foreach my $id ( keys %$tracks )
208 return $id if ( $tracks->{$id} eq $title )
211 # If no match, return undef.
215 sub get_track_name
($;$)
219 my $wrk_dir = $trk_dir;
220 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
222 open(PRO
, "<" . $wrk_dir . "/" . $id . "/info" ) or die ("Unable to read track medatata file!");
226 next if not $_ =~ /^title:(.*)/;
233 sub create_track
($;$)
237 my $wrk_dir = $trk_dir;
238 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
245 } while ( -d
$wrk_dir . "/" . $id );
246 mkdir ( $wrk_dir . "/" . $id );
248 open(PRO
, ">" . $wrk_dir . "/" . $id . "/info" ) or die ("Unable to create track medatata file!");
249 printf(PRO
"title:%s\n", $title);
255 sub start_track
($$;$)
257 my $start_time = shift;
261 my $wrk_dir = $trk_dir;
262 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
264 my $current = get_current_id
($trk_id);
269 $current = get_last_id
( $trk_id );
273 $current = get_track_id
( $title, $trk_id );
276 printf("No track by that name! Creating a new one.\n");
277 $current = create_track
($title, $trk_id);
281 # Break off here if we haven't gotten an ID yet.
282 return undef if not $current;
284 set_current_id
($current, $trk_id);
286 # First iteration is VERY naive: simply add the start time to the bottom of the tracking file
287 # Will have to do more logic: if the start point is before one of the times already in the track,
288 # the file will have to be manipulated to get coherent tracking!
289 open (TRACK
, ">>" . $wrk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
290 printf(TRACK
"[%s]", time2str
($start_time));
299 sub close_track
($;$)
302 my $stop_time = shift;
304 my $wrk_dir = $trk_dir;
305 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
307 my $current = get_current_id
( $trk_id );
309 die ("Project exists, but tracking file does not!") if ( not -f
$wrk_dir . "/" . $current . "/tracking" );
311 # First iteration is VERY naive: simply add the stop time to the bottom line of the tracking file
312 # Will have to do more logic: if the start point is before one of the times already in the track,
313 # the file will have to be manipulated to get coherent tracking!
314 # In addtion to this: actually do some file sanity checking!
315 open (TRACK
, ">>" . $wrk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
316 printf(TRACK
" to [%s]\n", time2str
($stop_time));
319 unlink ( $wrk_dir . "/current" );
327 my $wrk_dir = $trk_dir;
328 $wrk_dir = $trk_dir . "/" . $trk_id if $trk_id;
332 my $name = get_track_name
( $current, $trk_id );
333 printf("# Report for '%s':\n\n", $name);
335 open (TRACK
, "<" . $wrk_dir . "/" . $current . "/tracking" ) or die ("Unable to open file, $!");
338 next if not $_ =~ m/\[(.*)\] to \[(.*)\]/;
341 my $t_start = str2time
( $start );
342 my $t_end = str2time
( $end );
343 my $delta = $t_end - $t_start;
346 my $hours = $t / 3600;
348 my $minutes = $t / 60;
350 printf(" %s to %s => %d hours %d minutes\n", $start, $end, $hours, $minutes);
358 my $hours = $t / 3600;
360 my $minutes = $t / 60;
362 printf("\nTotal: %d hours %d minutes\n", $hours, $minutes);
365 ############################################################
369 mkdir $trk_dir or die("Unable to create data directory");
377 my $command = $ARGV[0];
379 if ( ( $command eq "start") || ($command eq "on" ) )
386 my ( $start_time, $title ) = parse_arguments
(START
);
388 my $current = get_current_id
();
391 $current = start_track
( $start_time, $title );
395 printf("Something weird happened.\n");
401 printf("A project is being tracked: %s\n", get_track_name
( $current ) );
402 close_track
($start_time);
403 $current = start_track
( $start_time, $title );
406 printf("Started tracking of '%s' at %s\n\n", $title, scalar localtime $start_time);
408 elsif ( ( $command eq "stop") || ($command eq "off" ) )
416 my $stop_time = parse_arguments
(STOP
);
418 my $current = get_current_id
();
421 printf("No project is currently tracked. To stop, please start first\n");
424 my $title = get_track_name
( $current );
426 my $activity = get_current_id
($current);
429 printf("An active subtask is running: '%s'. Closing it.\n", get_track_name
( $activity, $current ));
430 close_track
($stop_time, $current);
432 close_track
($stop_time);
434 printf("Stopped tracking of '%s' at %s\n\n", $title, scalar localtime $stop_time);
436 elsif ( ( $command eq "activity") || ($command eq "task" ) )
443 my ( $start_time, $title ) = parse_arguments
(START
);
445 my $trk_id = get_current_id
();
448 printf("Starting a task/activity requires an active main track.\n");
454 my $current = get_current_id
( $trk_id );
457 $current = start_track
( $start_time, $title, $trk_id );
461 printf("Something weird happened.\n");
467 printf("A task/activity is being tracked: %s\n", get_track_name
( $current, $trk_id ) );
468 close_track
($start_time, $trk_id);
469 $current = start_track
( $start_time, $title, $trk_id );
472 printf("Started tracking of '%s' at %s\n\n", $title, scalar localtime $start_time);
478 elsif ( $command eq "main" )
487 my $stop_time = parse_arguments
(STOP
);
489 my $trk_id = get_current_id
();
492 printf("Stopping a task/activity requires an active main track.\n");
497 my $current = get_current_id
( $trk_id );
500 printf("No activity/task is currently tracked. To stop, please start first\n");
503 my $title = get_track_name
( $current, $trk_id );
504 close_track
($stop_time, $trk_id);
506 printf("Stopped tracking of '%s' at %s\n\n", $title, scalar localtime $stop_time);
509 elsif ( ( $command eq "projects" ) || ( $command eq "list" ) )
511 # Todo/future extensions:
512 # TODO: Sort list of names alphabetically
513 # TODO: Get total-hours for projects
515 my $tracks = get_tracks
();
516 printf("Currently tracked project names:\n\n");
517 my $current = get_current_id
();
519 #foreach my $id ( keys %$tracks )
520 foreach my $id ( sort { $tracks->{$a} cmp $tracks->{$b} || $a cmp $b } keys %$tracks )
522 printf(" %s %s\n", ($id eq $current ?
">" : " " ),$tracks->{$id} );
526 elsif ( $command eq "report" )
529 my ( undef, $title ) = parse_arguments
(START
);
535 $track = get_track_id
( $title );
539 $track = get_last_id
();
544 printf ("Unable to get info for that track\n");
549 my $activities = get_tracks
( $track );
550 if ( keys %$activities )
552 printf("# Reporting for sub-task/activities:\n\n");
554 foreach my $id ( sort { $activities->{$a} cmp $activities->{$b} || $a cmp $b } keys %$activities )
555 #foreach my $id ( keys %$activities )
557 report
( $id, $track );
558 printf("# --------------------------------------------------------------\n");
563 printf("# Reporting for main track/project/task\n");
565 printf("\n# ==============================================================\n\n");
568 print("# End of report\n");
572 elsif ( $command eq "edit" )
575 my ( undef, $title ) = parse_arguments
(EDIT
);
576 my $id = get_last_id
();
580 $id = get_track_id
($title);
583 printf("No project by that name. Try 'list'\n");
588 system( "/usr/bin/editor " . $trk_dir . "/" . $id . "/tracking" );