#!/opt/local/bin/perl

#     Jimmy's code Development Environment
#     Jimmy's EDItor (JEDI)
#########################################################################
#  simple editor/IDE based on perl/Tk text widget
#  some mods to allow for vi style commands
#  still TBD though
#  COPYRIGHT:  Joachim Raeder, 2017
#              free for personal and academic use
#              commercial use requires a license
#  NO GUARANTEE WHATSOEVER FOR ANY SPECIFIC FUNCTIONALITY AND CORRECT
#  FUNCTION!
#########################################################################
use Tk;
#use Tk::TextVi;

$numbers=0; $cfile=''; $snap=''; $frc='.jedirc';

$w = MainWindow->new();
$sfnt=$w->fontCreate(-family=>'Monaco',-weight=>'bold',-size=> -16);
$bfnt=$w->fontCreate(-family=>'Courier',-weight=>'bold',-size=> -20);

$w->bind('<Control-Key-q>' => sub{ action('save');  exit; });
$w->bind('<Control-Key-e>' => sub{ action('saverun'); });

$f1 = $w->Frame()->pack( -side => 'right' );
$f2 = $w->Frame()->pack( -side => 'left' );

$t = $f1->Scrolled("Text", -scrollbars => 'osw', -background => 'moccasin', -font =>$bfnt, -wrap => 'none')->pack;
$t->configure( -height => 96, -width => 132); $t->configure( -font => $bfnt );

@PH=(qw/-expand 1 -side top -fill x/);

#....... various actions
@FF=('-font',$bfnt,'-bg','#FFaaaa');  
  $f01bx=$f2->Button(@FF,-text=>"QUIT (NO SAVE!)", -command => sub{ exit; })->pack(@PH);
@FF=('-font',$bfnt,'-bg','#9FEDAB');  
  $f01b1=$f2->Button(@FF,-text=>"OPEN from menu",        -command => sub{ action('open'); action('savesnap'); })->pack(@PH);
  $f01b2=$f2->Button(@FF,-text=>"SAVE",                  -command => sub{ action('save'); })->pack(@PH);
  $f01b4=$f2->Button(@FF,-text=>"SAVE SNAPSHOT",         -command => sub{ action('savesnap'); })->pack(@PH);
  $f01b5=$f2->Button(@FF,-text=>"SAVE/QUIT",             -command => sub{ action('save'); exit; })->pack(@PH);
  $f01b6=$f2->Button(@FF,-text=>"SAVE/RUN ",             -command => sub{ action('saverun') })->pack(@PH);
  $f01b7=$f2->Button(@FF,-text=>"SAVE/CLEAR",            -command => sub{ action('saveclr') })->pack(@PH);
  $f01b8=$f2->Button(@FF,-text=>"SAVE NEW  ",            -command => sub{ action('savenew') })->pack(@PH);
  $f01b9=$f2->Button(@FF,-text=>"kdiff3 to last snap",   -command => sub{ action('kdiff3l') })->pack(@PH);

#...... config stuff
@FF=('-font',$bfnt,'-bg','#bbbbff'); 
  $f01c01=$f2->Button(@FF,-text=>"toggle numbers", -command => sub{ @a=tget(); $numbers=($numbers+1)%2; tclean(); tload(@a);  })->pack(@PH);

#...... scrolled list of last files
$flist=$f2->Scrolled('Listbox',-width=>36,-height=>36,-background => 'moccasin', -font =>$bfnt);
   $flist->pack(-side=>'top', -expand=>1, -fill=>'both');
   fillbox('FILE'); $flist->bind('<Double-1>', => sub{ action('flist_click'); }) ;
$hlist=$f2->Scrolled('Listbox',-width=>36,-height=>24,-background => 'moccasin', -font =>$sfnt);
   $hlist->pack(-side=>'top', -expand=>1, -fill=>'both'); hlist_fill();

#...... if filename given load it
$f=shift(@ARGV); if($f ne ''){ if(-e "$f"){ @a=suck($f); tload(@a); $cfile=$f; addrc('FILE',$f); action('savesnap'); } }

$t->SetCursor('1.0'); $t->focus();
MainLoop;

#-------------------------------------------------------
sub action{ local($a)=@_; local(@a,$x);
#-------------------------------------------------------

  if($a eq 'flist_click'){ ($sel)=$flist->curselection();
      if($sel eq ''){ print STDERR "no selection for this click!\n"; return; }
      else{ $f=$flist->get($sel); print STDERR "got flist selection |$f|\n"; newfile($f); addrc('FILE',$f); }}

  if($a eq 'open'){ $f=$w->getOpenFile( -font => $bfnt ); print STDERR "got file: |$cfile|\n";
      if($f eq ''){ return;} newfile($f);addrc('FILE',$f);  }

  if($a eq 'savesnap'){ $f=basename($cfile); $DA=`date "+%Y-%m-%dT%H%M%S"`; chop($DA);  $snap=".00-$f-$DA";
    @a=tget(); $x=join("\n",@a); dumpf($x,$snap); print STDERR "savesnap: |$snap|\n"; return; }

  if($a eq 'savenew'){ $cfile=$w->getSaveFile( -font => $bfnt ); print STDERR "got file: |$cfile|\n";
    @a=tget(); $x=join("\n",@a); dumpf($x,$cfile);addrc('FILE',$cfile);  return; }

  if($a eq 'save'){ if($cfile eq ''){ err("no current file"); return; }
    @a=tget(); $x=join("\n",@a); dumpf($x,$cfile); return; }

  if($a eq 'saverun'){ if($cfile eq ''){ err("no current file"); return; }
    @a=tget(); $x=join("\n",@a); dumpf($x,$cfile); ssy("chmod 755 $cfile; $cfile"); return; }

  if($a eq 'saveclr'){ if($cfile eq ''){ err("no current file"); return; }
    @a=tget(); $x=join("\n",@a); dumpf($x,$cfile); tclean(); $cfile=""; return; }

  if($a eq 'savequit'){ if($cfile eq ''){ err("no current file"); return; }
    @a=tget(); $x=join("\n",@a); dumpf($x,$cfile); exit; }

  if($a eq 'kdiff3l'){ @a=tget(); $x=join("\n",@a); dumpf($x,'tmp.kd3'); ssy("kdiff3 $snap tmp.kd3"); return; }

}
#-------------------------------------------------------
sub newfile{ local($fn)=@_; local(@a,$x,$snap);
#-------------------------------------------------------
    #....  save current file if exists
    if($cfile ne ''){ @a=tget(); $x=join("\n",@a); dumpf($x,$cfile); }   #...... save existing file
    tclean(); $cfile=$fn; @a=suck($fn); tload(@a);    #.... load selected file and save snapshot right away
    $fn=basename($cfile); $DA=`date "+%Y-%m-%dT%H%M%S"`; chop($DA);  $snap=".00-$fn-$DA";
    @a=tget(); $x=join("\n",@a); dumpf($x,$snap); 
    print STDERR "newfile saved snap: |$snap|\n";   }
#-------------------------------------------------------
sub tclean{ $t->delete('1.0','end'); }
#-------------------------------------------------------
#-------------------------------------------------------
sub tget{  local(@a,$x);
#-------------------------------------------------------
  $x=$t->get('1.0','end'); @a=(); foreach(split('\n',$x)){ if($numbers>0){ $_=substr($_,9); }
      #  print STDERR "tget: |$_|\n";
      push(@a,$_); } return(@a); }
#-------------------------------------------------------
sub tload{  local($k,$x);
#-------------------------------------------------------
  $k=0; foreach(@_){ if($numbers>0){ $k++; $x=sprintf("%8d %s",$k,$_);  } else{ $x=$_; }
      $t->insert('end',"$x\n"); } }
#-------------------------------------------------------
sub fillbox{  local($type)=@_; local($f);
#-------------------------------------------------------
  $flist->delete(0.0,'end'); @a=suck($frc); push(@a,'FILE .jedirc');
  foreach(@a){if(/$type\s+(\S+)/){$f=$1;$flist->insert('end',$f); }}}
#-------------------------------------------------------
sub addrc{ local($type,$w)=@_;  local(@a,$x,$y,$z);  $z='';
#-------------------------------------------------------
  @a=suck($frc); foreach(@a){ ($x,$y)=split();
      if(($x eq $type)&&($y eq $w)){ print STDERR "addrc elim $type $y\n"; } else{ $z="$z$_\n"; }} #..... eliminate dups
  $z="$type $w\n$z"; dumpf($z,$frc); fillbox($type); } #..... add on top

sub hlist_fill{ local($t);
    $t="Control-q anywhere --> save and quit
        Control-e anywhere --> save and execute
        Control-x in text  --> cut marked and save to buffer
        Control-c in text  --> save marked to buffer
        Control-v in text  --> paste buffer at cursor
        Dble-1 file --> save and load that file
        Most actions cause a save to '.00-FILE-DATE
";  foreach(split('\n',$t)){ s/^\s+//; $hlist->insert('end',"$_"); } }

sub err{ local($x)=@_; print STDERR "ERROR:  $x\n"; }
sub ssy{ local($c)=@_; print STDERR "ssy:|$c|\n"; system($c); return; }
sub min{ local($a,$b)=@_;local($c); $c=$a; if($b<$a){$c=$b;} return($c); }
sub max{ local($a,$b)=@_;local($c); $c=$a; if($b>$a){$c=$b;} return($c); }
sub abs{ local($a)=@_;local($c); $c=$a; if($a<0){$c=-$a;} return($c); }
sub log10{local($a)=@_;$y10=1.0/(log(10.0));$a=$y10*log(max($a,1.0e-15)); return($a); }
sub log2{local($a)=@_;$y10=1.0/(log(2.0));$a=$y10*log(max($a,1.0e-15)); return($a); }
sub basename{ local($k)=@_; local(@a)=split('\/',$k); return($a[$#a]); }
sub suck{local($f)=@_; local($t,@t);$t=`cat $f`;@t=split('\n',$t); print STDERR "suck: |$f| |$#t|\n"; return(@t); }
sub dumpf{ local($c,$f)=@_; open(DF,">$f"); print DF $c; close(DF); }

