#!/usr/bin/perl -w
#
# no  --crb3 22may01/26oct05/02Aug06/18sep06
#
# supports quick easy scribbling of notes into
# MILdatecoded files.
#
##
# -----------------------------------------------------------------------
#                      LICENSE AND DISCLAIMER
#
# This program is copyright (C) 2001-2006 C. R. Bryan III
# <crb3@stormbringer.org> All Rights Reserved, and is made available under
# the terms of the GNU General Public License which is viewable at
# http://www.gnu.org/licenses/gpl.html. It comes with absolutely no warranty
# of functionality, serviceability, suitability or informativeness.
#
# -----------------------------------------------------------------------
##
#
$user="crb3" unless defined $user;              # your username here
$root2user=1 unless defined $root2user;         # root writes to $user's notes?
$wrapon=1 unless defined $wrapon;
$rmargin=65 unless defined $rmargin;
$autoindent=1 unless defined $autoindent;
$intabs=2 unless defined $intabs;
$space32=1 unless defined $space32;
#
# $dirpath is the directory where the dated notes go.
# I use a "public-branch/private branch" method where
# /home/user/user/ is chmod 700, since
# /home/user/public_html/ and /home/user/ are chmod 755
# to allow Apache to serve public_html files.
# "cork" is 'corkboard', where loose files get pinned up.
# "log" reflects the first use of this kind of script
#  to log times and actions for progress reports.
# modify the path to where you want your datecoded files kept.
#
$dirpath="/home/username/username/!cork/log" unless defined $dirpath;
$ftype="!no" unless defined $ftype;             # filetype for these files
#
# commandline invocation of preferred editor for editing this
# kind of file. filename will be tacked onto the end at invocation.
# I use WordStar-like editors. your preference WILL probably vary;
# alter to suit.
#
unless(defined($editor)){
  $editor="/usr/bin/jstar"
#       ." -rmargin 65"         # set wrap margin to 65 chars
        ." -force"              # always end file with \n
#       ." -tab 2"              # each <tab> is 2 spaces:
#       ." -spaces"             # real spaces, that is, and
#       ." -indentc 32"         # autoindent using real spaces.
        ." +999"                # open with cursor at file-bottom
  ;
  $editor .=" -wordwrap" if $wrapon;            # turn on wordwrap
  $editor .=" -autoindent" if $autoindent;      # turn on indent
  $editor .=" -tab $intabs";
  $editor .=" -spaces -indentc 32" if $space32;
  $editor .=" -rmargin $rmargin";
}
#
#
#
@mondys=(0,
         31,
         (28+31),
         (31+28+31),
         (30+31+28+31),
         (31+30+31+28+31),
         (30+31+30+31+28+31),
         (31+30+31+30+31+28+31),
         (31+31+30+31+30+31+28+31),
         (30+31+31+30+31+30+31+28+31),
         (31+30+31+31+30+31+30+31+28+31),
         (30+31+30+31+31+30+31+30+31+28+31),
         (31+30+31+30+31+31+30+31+30+31+28+31));

#@mons = qw/jan feb mar apr may jun jul aug sep oct nov dec/;

#
# start cat-building the explicit filename.
#
$isroot=0;
$usr=$ENV{'LOGNAME'};
if($usr eq 'root'){
  if($root2user){
    $usr=$user$isroot=1;
  }else{
    substr($dirpath,0,5)="";    # delete "/home", leaving /root/root
  }
}
$dirpath =~ s/username/$usr/g;  # swap in user
#
# notedir path is now built. this might be the user's first use
# of this script: make sure the notes dir is there.
#
unless(-d $dirpath){
  &mkparent($dirpath);
  mkdir($dirpath,0750);
}
#
# now cat-build a datecoded filename, as "!01jan70.!no",
# onto the path, unless the user specified something else.
# don't like that name-format? change it here.
#
$fnam="$dirpath/!";     # start building filename onto path
$now = $rightnow = "";  # establish date and datime vars
&get_datime;            # fill in those two
#
# caller might've typed a MILdate.
# disallow notenames differing only in case.
# caller might've typed in something completely
# different; allow it and don't mess up the case.
#  --crb3 22jan03
# or it might've been a date-offset (-e is 'next earlier
# date that's empty').
#  --crb3 26Oct05
# and -p is 'next earlier date that's NOT empty' ("prior").
#
if(defined($ARGV[0])){
  $typed = lc($spec=$ARGV[0]);
  if($typed =~ /^\d{2}[a-z]{3}\d{2,4}/){
    substr($typed,2,1) =~ tr/a-z/A-Z/;
    $spec=$typed;
  }elsif($typed =~ /^[\+\-]/){
    my ($mday,$month,$year)=(localtime)[3,4,5];
    $year += 1900;
    my $doy=date2doy($year,$month,$mday);
    if(index($typed,'-')==0){
      substr($typed,0,1)="";
      if($typed =~ /^\d+$/){
        $doy -= (0+$typed);
        while($doy <1){
          $year -=1;
          $doy += (is_leapyr($year) ? 366 : 365);
        }
        $spec=date2MIL(doy2date($year,$doy));

      }elsif($typed eq 'e'){            # find most recent empty date
        $doy--;
        if($doy <1){
          $year -=1;
          $doy += (is_leapyr($year) ? 366 : 365);
        }
        $spec=date2MIL(doy2date($year,$doy));
        while(-e "$dirpath/!$spec.$ftype" or -e "$dirpath/!$spec.$ftype.gz"){
          $doy--;
          if($doy <1){
            $year -=1;
            $doy += (is_leapyr($year) ? 366 : 365);
          }
          $spec=date2MIL(doy2date($year,$doy));
        }

      }elsif($typed eq 'p'){            # find most recent non-empty date
        $doy--;
        if($doy <1){
          $year -=1;
          $doy += (is_leapyr($year) ? 366 : 365);
        }
        $spec=date2MIL(doy2date($year,$doy));
        until(-e "$dirpath/!$spec.$ftype" or -e "$dirpath/!$spec.$ftype.gz"){
          $doy--;
          if($doy <1){
            $year -=1;
            $doy += (is_leapyr($year) ? 366 : 365);
          }
          $spec=date2MIL(doy2date($year,$doy));
        }
      }

    }elsif(index($typed,'+')==0){       # futureward by days
      substr($typed,0,1)="";
      $doy += (0+$typed);
      while($doy > ($yrdoy= (is_leapyr($year) ? 366 : 365)) ){
        $doy -$yrdoy;
        $year++;
      }
      $spec=date2MIL(doy2date($year,$doy));
    }
  }
}else{
  $spec=$now;
}
$fnam .= "$spec.$ftype";
#
# entry is stamped with current datime no matter what file it is.
#

$gzipit=0;                      # handling older gzipped notes:
if(-e "$fnam.gz"){              #  ungzip, edit, re-gzip.
  system("gunzip $fnam.gz");    # user is at console to handle
  $gzipit=1;                    #  overwrite questions.
}
$isit = (-e $fnam ? 1 : 0);     # no trinary returns, please.
open(NFIL,">>$fnam"or die "Can't open notefile $fnam\n";
print NFIL ";$rightnow\n\n";    # datestamp new entry or amendment
if(defined($formand !$isit){
    print NFIL $form;           # a given file gets form stuff once.
}
close(NFIL);
system("$editor $fnam");        # NOW scribble in it.

if($gzipit){
  system("gzip $fnam");
  $fnam .= ".gz";               # for chown
}

#
# if root wrote it, give it to usr so you can
# modify it once you're out of root.
#
system("chown $usr:$usr $fnam"if $isroot;
1;


#---------------

#
# mkparent.
# given an explicit path, create any missing directory
# components of that path. uses recursion, so don't
# abuse it by feeding it (sym)links unless you like
# scouring your process table.
#
sub mkparent {
  my $tdir = shift(@_);

  return if $tdir eq "" or !defined($tdir);
  $tdir =~ s/\/[^\/ ]+?$//;
  unless(-d $tdir){
    &mkparent($tdir);
  }
  mkdir($tdir,0750);
}

#
# get_datime.
# fills in two globals: now (date) and rightnow (datime).
#
sub get_datime{
  ($sec,$min,$hour,$mday,$mon,$yr,,,,) = localtime();

#  $yr %= 100;
#  $amon = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$mon];

  $rightnow = ($hour<10?"0":"")."$hour:".($min<10?"0":"")."$min:".($sec<10?"0":"")."$sec ";

#  $now = ($mday<10?"0":"")."$mday$amon".($yr<10?"0":"")."$yr";
  $now = date2MIL($yr,$mon,$mday);

  $rightnow .= $now;
}

#
# date2MIL.
# convert numeric year, month, day to MILdate.
#
sub date2MIL {
  ($yr,$mon,$mday)=(@_);
  $amon = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec))[$mon];
  $yr %= 100;
  my $now=($mday<10?"0":"")."$mday$amon".($yr<10?"0":"")."$yr";
  return($now);
}

#
# date2doy.
# given three integers for day, month and fullyear, where 01jan is 1,1,
# return the date's day-of-the-year count, where 01jan is 1.
#
sub date2doy {
  my($yr,$mo,$dy)=(@_);
  my($doy);

  $mo--;                                # back to 0-based
  $doy=$mondys[$mo]+$dy;                # index into lengths-table
  $doy++ if(is_leapyr($yrand $mo>1);  # adjust for leapyear
  return($doy);
}


#
# doy2date.
# given year and day-of-year count, return yr,mo,dy.
#
sub doy2date {          # (yr,dy)
  my $yr=0;
  my $doy=0;
  $yr += shift(@_);     # coerce incoming args to numeric
  $doy += shift(@_);
  my($mo,$dy);
  my $skip=0;

  if(is_leapyr($yr)){   # leapyear adjustments
    if($doy == $mondys[2]+1){           #
      $mo=2$dy=29;
      $skip=1;
    }elsif($doy > $mondys[2]){          # ly adjust
      $doy--;
    }
  }
  unless($skip){
    for($mo=0;$mo<12;$mo++){
      last if $doy <= $mondys[$mo+1];
    }
    $dy=$doy-$mondys[$mo];
    $mo++;
  }
  return($yr,$mo,$dy);
}

#
# is_leapyr.
# take year number, return leapyear? true : false.
#
sub is_leapyr {
  my $y=abs(shift(@_));
  return(0if( ($y%4or ( !($y%100and ($y%400) ) );
  return(1);
}

Grab the
tarball
here

 
See an
example
caller
script
here
 
Syntax highlighting using Syntax::Highlight::Engine::Kate