Index: plod
===================================================================
RCS file: /c/rcs/plod/plod,v
retrieving revision 1.1.1.1
retrieving revision 1.8
diff -r1.1.1.1 -r1.8
47a48,49
> # PLODJRC	file to store job timing information in.
> # TIMESPENT	default amount of time to assigne to -j entries
49c51,54
< # STAMP		time/date stamp printed at the top of each entry
---
> # GENSTAMP	perl code that generates STAMP. See STAMPREGEX.
> # STAMPREGEX	regular expression to parse STAMP. Timing and date
> #               selection depend on it. See GENSTAMP.
> # STAMP		time/date stamp printed at the top of each entry (depricated)
70a76,77
> $PLODJRC = "$HOME/.plodjob";
> $TIMESPENT = 15;
72c79,80
< $STAMP = sprintf("%02d/%02d/%04d, %02d:%02d --", $MM, $DD, $YY+1900, $hh, $mm);
---
> $GENSTAMP = '$STAMP = sprintf("%02d/%02d/%04d, %02d:%02d -- %s %s", $MM, $DD, $YY+1900, $hh, $mm, $jobname, $duration);';
> $STAMPREGEX = '^([0-9]+)/([0-9]+)/([0-9]+), .* --(\s*([A-z_0-9:-]+)\s+([0-9]+))?';
75a84
> $TIMEFMT = 'm';
76a86
> require 'timelocal.pl';
242,244c252,262
<    local($bogus) = @_;
<    return(&mistake) if ($bogus);
<    &calledit($EDITOR);
---
>    local($args) = @_;
>    local($anEditor, $bogus);
>    ($anEditor, $bogus) = &shellwords($args);
>    return(
>      warn("*** Only one argument (edit program) expected for this escape.\n"))
>      if ($bogus);
>    if ($anEditor) {
>        &calledit($anEditor);
>    } else {
>        &calledit($EDITOR);
>    }
450a469,470
> $PLODJRC = $ENV{'PLODJRC'} if ($ENV{'PLODJRC'});
> $TIMESPENT = $ENV{'TIMESPENT'} if ($ENV{'TIMESPENT'});
459a480,481
> $GENSTAMP = $ENV{'GENSTAMP'} if (defined($ENV{'GENSTAMP'}));
> $STAMPREGEX = $ENV{'STAMPREGEX'} if (defined($ENV{'STAMPREGEX'}));
469a492,497
> $EndDateT = 9999999999;
> # beginning of the epoch
> $StartDateT = 0;
> # the default $deltaduration is 0.
> $deltaduration = 0;
> $jobcode = "";
485c513
<       &usage() if ($grep || $cat || $edit || $page);
---
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
493c521
<       &usage() if ($grep || $cat || $edit || $page);
---
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
499c527
<       &usage() if ($grep || $cat || $edit || $page);
---
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
505c533
<       &usage() if ($grep || $cat || $edit || $page);
---
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
508a537,618
>    } 
>    elsif ($curr eq '-T') {
>        &usage if ($grep || $cat || $edit || $page || $card || $jobcode);
>        $card = $curr;
>        $file = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>        $key = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>    }
>    elsif ($curr eq '-F') {
>        $Specific_error = "-F can only be used with -T\n", &usage
> 	   if ($grep || $cat || $edit || $page || $jobcode);
>        $TIMEFMT = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>        $formatok = 0;
>      CHECKFMT: {
> 	 $formatok = 1, last CHECKFMT if $TIMEFMT eq "h:m";
> 	 $formatok = 1, last CHECKFMT if $TIMEFMT eq "h";
> 	 $formatok = 1, last CHECKFMT if $TIMEFMT eq "m";
>      }
>        $Specific_error = "Invalid format to -F should be 'h', 'm' or 'h:m'",
>        &usage, if !$formatok;
>    }
>    elsif ($curr eq '-S') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       &GetJobInfo();
>       print "No job in progress.\n" if ! $Jobname;
>       print "Job $Jobname suspended.\n" if $Jobname && ($JobStart == 0);
>       print "Job $Jobname in progress for $Duration minutes.\n"
> 	  if $Jobname && $JobStart;
>       PLODNormExit();
>   }
>    elsif ($curr eq '-b') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       $jobcode = $curr;
>       $jobname = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>       $jobname = '?' if ! $jobname;
>   }
>    elsif ($curr eq '-B') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       $jobcode = $curr;
>       $Specific_error = "-B switch requires that environment variable PLODJOB be set. It is not set.",
>           &usage if ! $ENV{'PLODJOB'};
>       $jobname = $ENV{'PLODJOB'};
>   }
>    elsif ($curr eq '-e') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       $jobcode = $curr;
>   }
>    elsif ($curr eq '-j') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       $jobcode = $curr;
>       $jobname = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>       $jobname = '?' if ! $jobname;
>   }
>    elsif ($curr eq '-J') {
>       &usage() if ($grep || $cat || $edit || $page || $card || $jobcode);
>       $jobcode = $curr;
>   }
>    elsif ($curr eq '-t') {
>        &usage() if ($grep || $cat || $edit || $page );
>        $duration = shift @ARGV unless ($ARGV[0] =~ /^-[A-z]w$/);
>        $Specific_error = "Number of minutes is not a number: $duration",
>        &usage() if $duration !~ m/^[-+]?[0-9]+$/;
>        # define $deltaduration if number start with + or -.
>        $deltaduration = $duration, undef($duration) if ($duration =~ m/^[-+]/);
>    }
>    elsif ($curr eq '-d') {  # Start Date
>        &usage() if ($cat || $edit || $page || $jobcode);
>        $StartDate = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>        if (! (($m, $d, $y) = ($StartDate =~ m:^([0-9]+)/([0-9]+)/([0-9]+)$:))) {
> 	   $Specific_error = "Unknown date format $StartDate";
> 	   &usage();
>        }
>        $StartDateT = &timelocal(0,0,0,$d,$m-1,$y);
> 	   
>    }
>    elsif ($curr eq '-D') { # End Date
>        &usage() if ($cat || $edit || $page || $jobcode);
>        $EndDate = shift @ARGV unless ($ARGV[0] =~ /^-\w$/);
>        if (! (($m, $d, $y) = ($EndDate =~ m:^([0-9]+)/([0-9]+)/([0-9]+)$:))) {
> 	   $Specific_error = "Unknown date format $EndDate";
> 	   &usage();
>        }
>        $EndDateT = &timelocal(59,59,23,$d,$m-1,$y);
512c622
< &usage() if (@ARGV && ($grep || $cat || $edit || $page));
---
> &usage() if (@ARGV && ($grep || $cat || $edit || $page || $card));
513a624,625
> $Specific_error = "Start date $StartDate occurs after end date $EndDate.",
>        &usage() if ($StartDateT > $EndDateT);
521c633,634
<    eval { do "$PLODRC"; };
---
>    # changed to require because cygwin perl 5 has do silently fail.
>    eval { require "$PLODRC"; };
524a638,768
> # handle job timing code here. Look for errors.  %Job is defined in
> # .plodrc, so we have to do this after the .plodrc is read.
> $PLODJRC = "$HOME/$PLODJRC" unless ($PLODJRC =~ /^\.?\.?\//);
> if ($jobcode) {
>     $Specific_error = "-d and -D are used for -T and -G or -g mode only.";
>     &usage() if ($StartDate || $EndDate);
>     # suspend the current job.
>     if ( $jobcode eq '-J' ) {
> 	# defines $JobStart $Duration, $Jobname << note capitals
> 	# are from the PLODJRC file and not from the command line.
> 	&GetJobInfo();
> 	&PLODBadExit("No job defined.\n") if $Jobname eq "";
> 	# if $jobStart is 0, then they started the job on 1/1/1970 8-), or 
> 	# it was suspended.
> 	if ($JobStart == 0) { # toggle job timing back on.
> 	    # creates an entry in jobfile jobname=jobstart
> 	    # where jobstart is time(). Last arg is number of minutes offset.
> 	    &MakeJobEntry($Jobname, time(), 0);
> 	    $duration=0;
> 	    $jobname = $Jobname;
> 	    print "Resuming job $Jobname\n";
> 	}
> 	else { # toggle job timing off
> 	    # creates an entry in jobfile jobname=0
> 	    # where jobstart is time().
> 	    &MakeJobEntry($Jobname, 0, 0);
> 	    print "Suspending job $Jobname\n";
> 	    $jobname = $Jobname;
> 	    $duration = $Duration + $deltaduration if ! defined($duration);
> 	    $duration = 0 if $duration < 0;
> 	}
>     }
>     elsif ( $jobcode eq '-j' ) {
> 	if ($jobname eq '?') { # print jobnames and exit
> 	    $i=0;
> 	    print "List of defined jobs:\n";
>             if ($JobListOrder) { # 1 alphabetic row, 0 alphabetic column
> 		foreach $j (sort keys %Jobs) {
> 		    printf "%-18s ", $j;
> 		    $i++;
> 		    print "\n" if ! ($i%4);
> 		}
> 	    } else {
> 		@Jobs = sort keys %Jobs;
> 		$rows = int(scalar(@Jobs) / 4) + 1;
> 		for ($i=0 ; $i< $rows; $i=$i+1) {
> 		    printf "%-18s %-18s %-18s %-18s\n", $Jobs[$i],
> 		    $Jobs[$i + $rows], $Jobs[$i + (2* $rows)],
> 		    $Jobs[$i + (3*$rows)];
> 		}
> 	    }
> 	    print "\n\nUse plod -H or plod -h to get usage information.\n";
> 	    &PLODNormExit();
> 	}
> 	$Jobs{$jobname} = $jobname 
> 	    if $jobname =~ m/^TR:[0-9]+$/ && !defined($Jobs{$jobname});
> 	$Specific_error = "Unknown job. $jobname is not defined in %Jobs array.", &usage if ! defined($Jobs{$jobname});
> 	$jobname = $Jobs{$jobname};
>         $Specific_error = "Duration must be an absolute number with -j.";
>         &usage if ($deltaduration);
> 	$duration = $TIMESPENT if ! defined($duration);
> 	# add $duration seconds to the PLODJRC entry.
> 	&GetJobInfo();
> 	if ( $JobStart != 0 ) {
> 	    &MakeJobEntry($Jobname, $JobStart, $duration);
> 	}
>     }
>     elsif ($jobcode eq '-B') {
> 	$Jobs{$jobname} = $jobname 
> 	    if $jobname =~ m/^TR:[0-9]+$/ && !defined($Jobs{$jobname});
> 	$Specific_error = "Unknown job. $jobname (from PLODJOB environment variable) is not defined in %Jobs array.",
> 	&usage if ! defined($Jobs{$jobname});
> 	&PLODBadExit("Option -t only allowed with -j, -J and -e.")
> 	    if defined($duration);
> 	$jobname = $Jobs{$jobname};
> 	&GetJobInfo();
> 	$Specific_error = "$Jobname already started. Must end job (-e) before beginning a new job", &usage() if $Jobname ne "";
> 	&MakeJobEntry($jobname, time(), 0);
> 	$duration = 0;
>     }
>     elsif ($jobcode eq '-b') {
> 	if ($jobname eq '?') { # print jobnames and exit
> 	    $i=0;
> 	    print "List of defined jobs:\n";
> 	    foreach $j (sort keys %Jobs) {
> 		printf "%-18s ", $j;
> 		$i++;
> 		print "\n" if ! ($i%4);
> 	    }
> 	    print "\n\nUse plod -H or plod -h to get usage information.\n";
> 	    &PLODNormExit();
> 	}
> 	$Jobs{$jobname} = $jobname 
> 	    if $jobname =~ m/^TR:[0-9]+$/ && !defined($Jobs{$jobname});
> 	$Specific_error = "Unknown job. $jobname is not defined in %Jobs array.",
> 	&usage if ! defined($Jobs{$jobname});
> 	&PLODBadExit("Option -t only allowed with -j, -J and -e.")
> 	    if defined($duration);
> 	$jobname = $Jobs{$jobname};
> 	&GetJobInfo();
> 	$Specific_error = "$Jobname already started. Must end job (-e) before beginning a new job", &usage() if $Jobname ne "";
> 	&MakeJobEntry($jobname, time(), 0);
> 	$duration = 0;
>     }
>     elsif ($jobcode eq '-e') {
> 	&GetJobInfo();
> 	&PLODBadExit("No job is in progress. Use -j or -b to establish job.\n") if $Jobname eq "";
> 	$jobname = $Jobname;
> 	$duration = $Duration + $deltaduration if !defined ($duration);
> 	$duration = 0 if $duration < 0;
> 	&MakeJobEntry("",0,0);
>     }
>     else { PLODBadExit("Fatal Internal Error: unknown jobcode $jobcode") };
> }
> elsif (! ( $grep || $cat || $edit || $page || $card) ) {
>     # we are in recording mode.
>     $Specific_error = "-d and -D are used for -T and -G or -g mode only.";
>     &usage() if ($StartDate || $EndDate);
> 
>     # define $jobname
>     &GetJobInfo();
>     $jobname = $Jobname if $JobStart != 0;
>     &PLODBadExit("Option -t only allowed with -j, -J and -e.")
> 	if defined($duration);
>     $duration = "";
> }
> 
> # to get the proper values for duration and jobname, we have to set
> # $STAMP here.
> eval $GENSTAMP if !defined($STAMP);
> 
597a842,845
> elsif ($card) {
>     &cardsum($file, $key);
>     &PLODNormExit();
> }
783c1031
<    local(@entry, $print);
---
>    local(@entry, $print, $crlf, $sepseen, $DatePass);
801a1050,1051
>    $crlf = 0;
>    $sepseen = 0;
802a1053,1064
>       s/\r//, $crlf =1 if m/\r\n$/;
>       if ( $sepseen ){
> 	  # this should be the STAMP entry
> 	  if (m/$STAMPREGEX/) {
> 	      $noteTimeT = timelocal(0,0,0,$2,($1 -1) ,$3);
> 	      if ($EndDateT >= $noteTimeT && $StartDateT <= $noteTimeT) {
> 		  $DatePass = 1;
> 	      }
> 	  }
> 	  $sepseen = 0;
>       }
> 	  
805c1067,1068
<          $print = 0; undef @entry;
---
> 	 $sepseen = 1; $DatePass = 0;
> 	 $print = 0; undef @entry;
806a1070
>       s/\n/\r\n/, $crlf = 0 if $crlf;
809c1073
<       $print = ($print || /$pattern/o);
---
>       $print = ($print || /$pattern/o) && $DatePass;
905,907c1169,1198
<    warn "Usage: $prog [one line log entry]\tor\n";
<    warn "       $prog -C|-E|-V|-P [file [key]]\tor\n";
<    die  "       $prog -g|-G pattern [file [key]]\n";
---
>    warn "\n  $Specific_error\n\n" if  $Specific_error;
>    warn "Usage: $prog [-s] [-f plodrc] <-b jobname | -B |\n";
>    warn "             -j jobname [ -t timespent] | -J [-t timespent] |\n";
>    warn "             -e [-t timespent]> [one line log entry]\tor\n";
>    warn "       $prog [-s] [-f plodrc] <-C|-E|-V|-P|-S> [logfile [key]]\tor\n";
>    warn "       $prog [-s] [-f plodrc] [-d date] [-D date] <-g|-G pattern> \n";
>    warn "             [logfile [key]]\n";
>    warn "       $prog [-s] [-f plodrc] [-d date] [-D date] [-F format] -T\n";
>    if ( $ShortUsage ) {
>        die "             [logfile [key]]\n";
>    }
>    else {
>        warn "             [logfile [key]]\n";
>        warn "where: -f - use alternate plodrc file\n";
>        warn "       -s - prompt for encryption key\n";
>        warn "       -b - begin work on new current job\n";
>        warn "       -B - begin work on new current job. Environment\n";
>        warn "            variable $PLODJOB defines job name\n";
>        warn "       -J - suspend/resume work on current job\n";
>        warn "       -j - record some work on job interrupting current job. Modifies\n";
>        warn "            timing on current job unless current job is suspended\n"; 
>        warn "       -e - end work on current job.\n";
>        warn "       -S - report current status of job.\n";
> 
>        warn "       -g|-G - return entry that matches pattern. -g case insensitive\n";
>        warn "       -d/-D - only select entries after/before this date.\n";
>        warn "       -T - report total amount of time for all jobs (Timecard)\n";
>        warn "       -F - format of time on timecard. 'h' hours, 'h:m' or 'm'\n";
>        die "       -C|E|V|P - invoke cat, \$EDITOR, \$VISUAL or \$PAGER on logfile.\n";
>    }
925c1216,1219
<    }
---
>   } else {
>       unlink($BACKUP) if ($BACKUP);
>   }
> 
928a1223,1224
>    # restore the old jobname settings.
>    &MakeJobEntry($Jobname, $JobStart, 0);
992a1289,1380
> }
> 
> sub GetJobInfo {
>     # no arguments
>     local($line, $JUNK);
>     &MakeJobEntry("", 0, 0) if ! -f $PLODJRC;
>     open(JOBFILE, "< $PLODJRC") || &PLODBadExit("Can't read $PLODJRC\n");
>     $line = <JOBFILE>;
>     close(JOBFILE);
>     $JUNK = "";
>     ($Jobname, $JobStart, $JUNK) = split(/=/, $line);
>     chop($JobStart);
>     chop($JobStart) if $JobStart =~ m/\r/;
>     &PLODBadExit("Unexpected field in $PLODJRC. Contents $JUNK\n") if $JUNK ne "";
>     $Duration = int((time() - $JobStart)/60) if $JobStart;
>     $Duration = 0 if $JobStart < 0;
> }
> 
> sub MakeJobEntry {
>     local($name, $start, $offset) = @_;
>     local($newstart);
>     $newstart = $start + ($offset*60);
>     $newstart = 0 if $newstart < 0;
>     open(JOBFILE, "> $PLODJRC") || 
> 	&PLODBadExit("Can't write to $PLODJRC $!\n"); 
>     print JOBFILE "$name=$newstart\n";
>     close(JOBFILE);
> }
> 
> sub cardsum {
>    local($file, $key) = @_;
>    local(%JobSum, $crlf, $sepseen);
>    
>    $key = $key || $KEYVAL;
>    $file = $file || $LOGFILE;
>    $file = "$LOGDIR/$file" unless ($file =~ /^\.?\.?\//);
>    if ($CRYPTCMD) {
>       unless (&decrypt($key, $file, $TMPFILE)) {
>          unlink($TMPFILE);
>          warn "*** Unable to decrypt $file.\n";
>          return;
>       }
>       $file = $TMPFILE;
>    }
>    unless (open(INP, "< $file")) {
>       warn "*** Can't open $file for reading.\n";
>       return;
>    }
>    $crlf = 0;
>    $sepseen = 0;
>    while (<INP>) {
>       s/\r//, $crlf =1 if m/\r\n$/;
>       if ( $sepseen ){
> 	  # this should be the STAMP entry
> 	  if (m/$STAMPREGEX/) {
> 	      $noteTimeT = timelocal(0,0,0,$2,$1 -1,$3);
> 	      if ($EndDateT >= $noteTimeT && $StartDateT <= $noteTimeT) {
> 		  $Job = $5; $Time = $6;
> 		  if ( $Job ) {
> 		      $JobSum{$Job} += $Time;
> 		      $JobSum{$1} += $Time if $Job =~ /^([^:]*:)([^:]*)$/;
> 		      $JobSum{'zTOTAL ='} += $Time;
> 		  }
> 	      }
> 	  }
> 	  $sepseen = 0;
>       }
> 	  
>       if (/^$SEPARATOR$/o) {
>          $sepseen = 1;
>       }
>    }
>    close(INP);
>    unlink($TMPFILE) if ($CRYPTCMD);
>    if ( $TIMEFMT eq "h" ) {
>        foreach $key (sort(keys(%JobSum))) {
> 	   $h = $JobSum{$key}/60;
> 	   printf("%-25s %6.2f\n", $key, $h);
>        }
>    }
>    elsif ( $TIMEFMT eq "h:m" ) {
>        foreach $key (sort(keys(%JobSum))) {
> 	   $h = int($JobSum{$key}/60);
> 	   $m = int(60 * (($JobSum{$key}/60) - $h));
> 	   printf "%-25s %4d:%02d\n", $key, $h, $m;
>        }
>    }
>    else { # minutes
>        foreach $key (sort(keys(%JobSum))) {
> 	   printf "%-25s %5d\n", $key, $JobSum{$key};
>        }
>    }
Index: plod.man
===================================================================
RCS file: /c/rcs/plod/plod.man,v
retrieving revision 1.1.1.1
retrieving revision 1.7
diff -r1.1.1.1 -r1.7
17c17,22
< \ [\ -s\ ]\ [\ -f \fIfile\fR\ ]\ [\ \fIone line message\fR\ ]
---
> \ [\ -s\ ]\ [\ -f \fIfile\fR\ ]\ <-b \fIjobname\fR | -B |
> .br
> \ \ \ \ \ \ \ -j \fIjob\fR [ -t \fItimespent\fR ] | -J [ -t
> \fItimespent\fR ] |
> .br
> \ \ \ \ \ \ \ -e [ -t \fItimespent\fR ]> [\ \fIone line message\fR\ ]
21c26,27
< \fB-C\fR|\fB-E\fR|\fB-P\fR|\fB-V\fR\ [\ \fIlogfile\fR\ [\ \fIkey\fR\ ]]
---
> \fB-C\fR|\fB-E\fR|\fB-P\fR|\fB-V\fR\|\fB-S\fR [\ \fIlogfile\fR\
> [\ \fIkey\fR\ ]]
24a31,33
> [ -d \fIstartdate\fR ]
> .br
> \ \ \ \ \ \ [ -D \fIenddate\fR ]
25a35,42
> .br
> .B plod
> \ [\ -s\ ]\ [\ -f \fIfile\fR\ ]
> [ -d \fIstartdate\fR ]
> .br
> \ \ \ \ \ \ [ -D \fIenddate\fR ]
> \fB-T\fR [\ \fIlogfile\fR\ [\ \fIkey\fR\ ]]
> 
43a61,66
> The first mode also permits you to store time information with your
> log entries automatically. These job commands start timing a job,
> suspend or resume timing a job (to go to lunch), record temporarily
> diversions from a job (to answer a question or take a phone call) and
> end timing a job (see \fBTIMING COMMANDS\fR below).
> 
55c78
< but, unlike \fBgrep\fR(1), \fBPLOD\fR displays the entire log entry 
---
> but, unlike \fBgrep\fR(1), \fBPLOD\fR displays the entire log entry
60a84,92
> The \fB-d\fR and \fB-D\fR options let you
> filter the result of the grep by date. The \fIstartdate\fR and
> \fIenddate\fR arguments accept dates in the form 'mm/dd/yyyy'.
> 
> The fourth mode creates a timecard that tells you how much time was
> spent on an individual job. Again the \fB-d\fR and \fB-D\fR options
> allows you to restrict the dates that get entered into the
> timecard. The \fB-F\fR option determines the format for the time. For
> more information see \fBTIMING COMMANDS\fR below.
79a112,118
> .Ip "\fBGENSTAMP\fR" 4
> This variable is perl code that when run defines the
> Time/Date/Job/Timespent stamp entered into every log entry.  Set this
> to null if you do not wish to datestamp your logs.  Setting it to null
> will disable all of the timing commands as well. The default format is
> \fIMM/DD/YY, HH:MM -- Job Timespent\fR.
> .Sp
81,82c120,127
< The time/date stamp entered into every log entry.  Set this to null if you
< do not wish to datestamp your logs.  Default is \fIMM/DD/YY, HH:MM --\fR.
---
> The time/date stamp entered into every log entry.  This is not defined
> by default as it overrides the \fBGENSTAMP\fR variable. Overriding the
> GENSTAMP variable will cause problems with the job timing commands.
> .Sp
> .Ip "\fBSTAMPREGEX\fR" 4
> The regular expression that is used to parse the entry's
> \fBSTAMP\fR. This is used by the \fB-D\fR and \fB-d\fR options as well
> as the \fB-T\fR option.
142a188,198
> .Ip "\fBPLODJRC\fR" 4
> The name of the file holding the current job name and timing
> information.  \fBHOME\fR will be prepended to this value of
> \fBPLODRC\fR is not an absolute path.  Default is \fI.plodjob\fR.
> .Sp
> .Ip "\fBTIMESPENT\fR" 4
> The default amount of time that will be recorded for a job enrty done
> using the \fB-j\fR option. It can be overridden with the \fB-t\fR
> \fItimespent\fR option. The \fItimespent\fR argument should be the
> number of minutes spent on the job. The default is 15 minutes.
> .Sp
160a217,387
> .SH TIMING COMMANDS
> The timing commands are used to manipulate timing information for
> jobs. The jobs are defined by setting elements of the %Jobs array. For
> example adding the line:
> 
> .RS
> .nf
>   $Jobs{'software_install'} = 'software_install';
> .fi
> .RE
> 
> to your .plodrc would alloy you to time the job called
> "software_install". Note that "software_install" occurs on both sides
> of the = sign. This is important because the item on the righthand side
> of the equals sign is what shows up as the job name in the logs. This
> makes it easy to have short aliases for longer names. For example the entry:
> 
> .RS
> .nf
>   $Jobs{'si'} = 'software_install';
> .fi
> .RE
> 
> in your .plodrc makes the alias "si" mean the same thing as
> "software_install". This is to prevent you from accidently mistyping a
> job name every job you want to use must have an entry in the Jobs
> array.  Actually this is a bit of a lie. Entries of the form
> "TR:<numbers>" are always accepted. This bit of hackery is present to
> allow you to record your time on trouble tickets without having to
> enter each trouble ticket in the Jobs array. If you define:
> 
> .RS
> .nf
>   $Jobs{'TR_10241'} = 'TR:DiskSpace';
>   $Jobs{'TR_10249'} = 'TR:DiskSpace';
>   $Jobs{'TR_10274'} = 'TR:DiskSpace';
> .fi
> .RE
> 
> then any work done on the tickets listed on the left hand side will be
> mapped to the TR:Diskspace job in the log. It is suggested that you
> set up your trouble ticketing system to define the environment
> variable PLODJOB in the form TR:<number> where number is the job that
> you are working on solving. Note that the : has a special meaning when
> generating timecards. It will be described below.
> 
> We have seen how to set up the jobs, so how do the multitude of
> options work?  The \fB-B\fR or \fB-b\fR options start the clock
> running, timing the number of minutes spent on the job. The \fB-B\fR
> option gets its job name from the environment variable \fBPLODJOB\fR
> while you must specify the job name on the command line with the
> \fB-b\fR option. You can provide a one line message or enter an
> interactive message.
> 
> From this point on, every message that you enter (until you use the \fB-e\fR
> or \fB-J\fR options) will be tagged with the job name. This makes it easy to
> use the \fB-G\fR or \fB-G\fR options to find all messages on a job.
> 
> Now let's say you have been working all morning on the job and you
> want to get lunch. If you were to just leave, the clock would still be
> running when you get back and have counted the time you were at lunch
> as time spent on the job. The \fB-J\fR option is a toggle. If a job is
> active, it suspends it. If the job is suspended it resumes timing
> it. The \fB-J\fR option lets you enter a one line or multi-line
> message. Only the message with the \fB-J\fR option will be tagged with
> the job name. If you run plod without any job options while a job is
> suspended, the entry will not be tagged with job information. You must
> unsuspend the job using the \fB-J\fR option to enable the job tag on
> messages. Now lets say that you have finished with the job for the
> time being and you are going to work on another job. Use the \fB-e\fR
> option to close out the job and permit another job to be started with
> the \fB-b\fR or \fB-B\fR options.
> 
> Now let's say that you are working on a job and a phone call comes in
> that you need to handle. You could use \fB-e\fR to end the job and
> then \fB-b\fR to start a new job, then \fB-e\fR to end the new job and
> \fB-b\fR to restart the one you are working on. However that is a
> hassle. That's where the \fB-j\fR option comes in. Using "\fB-j\fR
> \fIjobname\fR" creates a plod entry for jobname without the hassle of
> \fB-b\fR and \fB-e\fR. Using the "\fB-t\fR \fItimespent\fR" option
> with it allows you to set the number of minutes you spent on the
> job. The environment and perl variable \fBTIMESPENT\fI
> (\fB$TIMESPENT\fR), which is set to 15 by default, determines the
> default amount of time if you do not use the "\fB-t\fR
> \fItimespent\fR" option. Now one other little trick happens. The
> amount of time spent on the "\fB-j\fR \fIjobname\fR" option is
> automatically subtracted from the current job specified by the
> \fB-B\fR or \fB-b\fR flag if the the job is active (i.e. not suspended
> by the \fB-J\fR option).
> 
> The \fB-t\fR option can also change time when used with \fB-J\fR and
> \fB-e\fR.  If the \fItimespent\fR argument starts with a \fB+\fR or
> \fB-\fR sign, then that number of minutes is added to or subtracted
> from the time spent on the job. This allows you to adjust the time
> spent if you went out to lunch and forgot to use \fB-J\fR to suspend
> the clock. Just use \fB-J -t -60\fR to reduce the reported time by 60
> minutes (don't forget to unsuspend the job and restart the timer). If
> you don't remember the current job status, use the \fB-S\fR option. To
> summarize the options:
> .RS
> .Ip "\fB-b\fR \fIjobname\fR"
> begin work on new current job. If called as: \fB-b
> \\?\fR or just \fB-b\fR the defined jobs are listed.
> .Sp
> .Ip \fB-B\fR
> begin work on new current job. Environment variable $PLODJOB
> defines job name
> .Sp
> .Ip \fB-J\fR
> suspend/resume work on current job
> .Sp
> .Ip "\fB-j\fR \fIjobname\fR"
> record some work on job interrupting current job. Modifies timing
> on current job unless current job is suspended. If called as: \fB-j
> \\?\fR or just \fB-j\fR the defined jobs are listed sorted
> alphabetically in 4 columns. If you set \fB$JobListOrder\fR to 1, the
> jobs will be sorted alphabetically by rows.
> .Sp
> .Ip \fB-e\fR
> end work on current job
> .Sp
> .Ip \fB-S\fR
> report current status of job
> .Sp
> .RE
> 
> Now that we have this timing info what can we do with it? Well I am
> glad you asked. The \fB-T\fR option generates a timecard listing jobs
> on the left hand side and cumulative time on the right. The format of
> the time is controlled by the \fB-F\fR option. It can be set to:
> "\fIh\fR" for hours and decimal hours, "\fIh:m\fR" for hours and
> minutes or "\fIm\fR" for minutes.  The \fB-d\fR and \fB-D\fR options take
> dates in the form '\fImm/dd/yyyy\fR' and only select the entries that fall
> after the \fB-d\fR date and before the \fB-D\fR date.
> 
> Jobs that have a ':' in them are treated as a category and
> subcategory. Sums are computed for both of them. As an example:
> 
> .RS
> .nf
> Programming:                 3:50
> Programming:c                0:10
> Programming:perl             3:40
> TR:                          0:30
> TR:23                        0:10
> TR:32                        0:20
> zTOTAL =                     4:20
> .fi
> .RE
> 
> the total for all TR's was 30 minutes and all programming projects was
> 3:50. The \fB-T\fR option also computes a total for all jobs. It is
> listed as '\fIzTOTAL =\fR' at the bottom.
> 
> In brief:
> 
> .RS
> .Ip \fB-T\fR
> report amount of time for all jobs (Timecard)
> .Sp
> .Ip "\fB-F\fR \fIformat\fR"
> format for time. 'h' hours, 'm' minutes, 'h:m' hours and minutes.
> .Sp
> .Ip "\fB-d\fR \fImm/dd/yyyy\fR"
> only return entries after this date.
> .Sp
> .Ip "\fB-D\fR \fImm/dd/yyyy\fR"
> only return entries before this date.
> .Sp
> .RE
> 
171,172c398,400
< .Ip ~e 8
< Edit the current buffer with \fB$EDITOR\fR.
---
> .Ip "~e [editor]" 8
> Edit the current buffer with \fBeditor\fR or \fB$EDITOR\fR if \fBeditor\fR
> not specifed.
185c413
< Similar to ~E except that \fB$EDITOR\fR is used.
---
> Similar to ~V except that \fB$EDITOR\fR is used.
245a474,480
> Among the variables tha can be customize is \fI$ShortUsage\fR. This
> reduces the Usage message to a specific error and a command line
> summary. It eliminates the explanation text when \fI$ShortUsage\fR is
> set to 1. Another variable that must be set is the \fI%Jobs\fR array
> as described in \fBTIMING COMMANDS\fR if you want to use the timing
> commands to track your work.
> 
425a661
> 
