#!/usr/bin/perl
# The Missing Textutils, Ondrej Bojar, obo@cuni.cz
# http://www.cuni.cz/~obo/textutils
#
# 'tt' pads tab-delimited file with spaces so that it looks nicely.
#
# Please read the source code for more options.
#
# $Id: tt,v 1.10 2006/12/04 04:44:01 bojar Exp $
#

use strict;
use Getopt::Long;

$| = 1;

my $numbers_right = 0;
my $utf8 = 0;
my $dett = 0;
my $centercols = "";
my $rightcols = "";
my $leftcols = "";
my $align = undef;
my $dotfill = 0;
my $rmtab = 0;
my $fullspan = 0;  # perform tabbing over the whole input, not paragraphwise
GetOptions(
  "dett" => \$dett,
  "utf8" => \$utf8,
  "numbers-right" => \$numbers_right,
  "align-right=s" => \$rightcols,
  "dotfill" => \$dotfill,
  "rmtab" => \$rmtab, # use 1 space instead of tab
  "align-left=s" => \$leftcols,
  "align-center=s" => \$centercols,
  "align=s" => \$align,  # lcr_r    _ ... use align-left or numbers-right
  "fullspan", \$fullspan
  );

if ($utf8) {
  binmode(STDIN, ":utf8");
  binmode(STDOUT, ":utf8");
  binmode(STDERR, ":utf8");
}

my $outfieldsep = $rmtab ? " " : "\t";
my %align_center = map {($_,1)} split /,/, $centercols;
my %align_right = map {($_,1)} split /,/, $rightcols;
my %align_left = map {($_,1)} split /,/, $leftcols;

if (defined $align) {
  my $i = 0;
  foreach my $a (split //, $align) {
    $i++;
    $align_center{$i} = 1 if $a eq "c";
    $align_right{$i} = 1 if $a eq "r";
    $align_left{$i} = 1 if $a eq "l";
  }
}

if ($dett) {
  while (<>) {
    s/ *\t */\t/g;
    s/^ *| *$//g;
    print;
  }
  exit;
}

my $tabcache = "";
while(<>) {
  my $line = $_;
  if (/\t/ || $fullspan) {
    $tabcache .= $line;
  } else {
    printtab() if $tabcache;
    print $line;
  }
}
printtab() if $tabcache;

sub printtab {
  my $cols = 0;
  my @w;
  foreach my $l (split /\n/, $tabcache) {
    my @l = split /\t/, $l;
    $cols = $#l if $cols < $#l;
    foreach my $i (0 .. $#l) {
      $l[$i] =~ s/^ *| *$//g;
      $w[$i] = length($l[$i]) if length($l[$i]) > $w[$i];
    }
  }
  my $nl = 0;
  foreach my $l (split /\n/, $tabcache) {
    $nl++;
    my $padchar = " ";
    $padchar = "." if $dotfill && $nl %2 == 0;
    my @l = split /\t/, $l;
    # print "XXX: $l\nXXX: ".join("XXX", @l)."\n";
    foreach my $i (0 .. $cols) {
      $l[$i] =~ s/^ *| *$//g;
      if ($align_center{$i+1}) {
        my $lpad  = $padchar x int(($w[$i] - length($l[$i]))/2);
        my $rpad  = $padchar x ($w[$i] - length($l[$i]) - length($lpad));
        print $lpad.$l[$i].$rpad;
      } else { 
        my $pad  = $padchar x ($w[$i] - length($l[$i]));

        my $ali;
	if ($align_right{$i+1}) {
	  $ali = "right";
	} elsif ($align_left{$i+1}) {
	  $ali = "left";
	} elsif ($numbers_right && $l[$i] =~ /^[+-]?[0-9]*\.[0-9]+$|^[+-]?[0-9]+?$/) {
	  $ali = "right";
	} else {
	  $ali = "left";
	}
	  
        if ($ali eq "right") {
          print $pad.$l[$i];
        } else {
          print $l[$i].$pad if $i < $cols;
          print $l[$i] if $i == $cols;
        }
      }
      print $outfieldsep if $i < $cols;
    }
    print "\n";
  }
  undef @w;
  undef $tabcache;
}
