#!/usr/bin/gawk -f
# /* vim: set filetype=awk : */ -*- awk -*-
#
# ----| malign |--------------------------------------
#
# _ _ _ _ _ ((
# |=|=|=|=|=|.----------------------------. _))_
# |-|-|-|-|-|| a 'requirez' code bundle | ___\__/)_
# |_|_|_|_|_|'----------------------------'|_||_~~_|_|
#
# Built by "oelrawas" on Wed Nov 22 13:09:51 EST 2006.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
# #---- [str.awk ] ------------------------------------------
#
Generate a string of characters
function str(n,c, x) {
while ((n--) > 0) x= x c;
return x;
}
# #---- [trim.awk ] ------------------------------------------
#trim.awk
Trim whitespace.
function trim(str) {
sub(/^[ \t]*/,"",str);
sub(/[ \t]*$/,"",str);
return str
}
# #---- [ranges.awk ] ------------------------------------------
function from(x,y,z) {
return (z >= x && z <= y) ? z : bad(z " not in [" x ".." y "]");
}
function round(x) {
return x<0 ? int(x-0.5) : int(x+0.5)
}
function between(min,max) {
return max==min ? min : min + ((max-min)*rand())
}
function most(x,y) { return x > y ? x : y }
function least(x,y) { return x < y ? x : y }
function within(min,max,bias) {
# pick a number between "min" and "max", with a little "bias"
return min + (max - min)*rand()^bias
# if bias = A >= 1 then mean = (max+min)*B is towards to "min" end
# BIAS mean
# ---- ----
# 1 0.5
# 2 0.33
# 3 0.25
# 4 0.2
# 5 0.17
# 6 0.14
# 7 0.13
# 8 0.11
# 9 0.10
# 10 0.09
# if bias = A < 1 then mean = (max+min)*B is towards the "max" end
# BIAS mean
# ---- ----
# 0.5 0.67
# 0.33 0.75
# 0.25 0.8
# 0.2 0.83
# 0.167 0.86
# 0.14 0.87
# 0.125 0.89
# 0.11 0.9
# 0.10 0.91
}
# #---- [about.awk ] ------------------------------------------
# #---- [commandLine.awk ] ------------------------------------------
# #---- [copyleft.awk ] ------------------------------------------
function copyleft() {
about(Who,What,When,Why);
print "";
print "This program is free software; you can redistribute it and/or";
print "modify it under the terms of the GNU Lesser General Public";
print "License as published by the Free Software Foundation; version 2.1.";
print "";
print "This program is distributed in the hope that it will be useful"
print "but WITHOUT ANY WARRANTY; without even the implied warranty of";
print "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU";
print "Lesser General Public License for more details.";
print "";
print "You should have received a copy of the GNU Lesser General Public";
print "License along with this program; if not write to the Free Software";
print "Foundation Inc. 51 Franklin St Fifth Floor Boston MA 02110-1301 USA";
}
function about(who,what,when,why) {
print what " : " why;
print "Copyright " when " " who ;
}
##---- [prints.awk ] ------------------------------------------
function prints(a0,b0,c0,d0,e0,f0,g0,h0,i0,j0,k0,l0,m0,n0,o0,p0,q0,r0,s0,t0,u0,v0,w0,x0,y0,z0,\
a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1,\
a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2,p2,q2,r2,s2,t2,u2,v2,w2,x2,y2,z2,\
a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,o3,p3,q3,r3,s3,t3,u3,v3,w3,x3,y3,z3,\
a4,b4,c4,d4,e4,f4,g4,h4,i4,j4,k4,l4,m4,n4,o4,p4,q4,r4,s4,t4,u4,v4,w4,x4,y4,z4,\
a5,b5,c5,d5,e5,f5,g5,h5,i5,j5,k5,l5,m5,n5,o5,p5,q5,r5,s5,t5,u5,v5,w5,x5,y5,z5,\
a6,b6,c6,d6,e6,f6,g6,h6,i6,j6,k6,l6,m6,n6,o6,p6,q6,r6,s6,t6,u6,v6,w6,x6,y6,z6,\
a7,b7,c7,d7,e7,f7,g7,h7,i7,j7,k7,l7,m7,n7,o7,p7,q7,r7,s7,t7,u7,v7,w7,x7,y7,z7,\
a8,b8,c8,d8,e8,f8,g8,h8,i8,j8,k8,l8,m8,n8,o8,p8,q8,r8,s8,t8,u8,v8,w8,x8,y8,z8,\
a9,b9,c9,d9,e9,f9,g9,h9,i9,j9,k9,l9,m9,n9,o9,p9,q9,r9,s9,t9,u9,v9) {
prints26(a0,b0,c0,d0,e0,f0,g0,h0,i0,j0,k0,l0,m0,n0,o0,p0,q0,r0,s0,t0,u0,v0,w0,x0,y0,z0);
prints26(a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1);
prints26(a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2,p2,q2,r2,s2,t2,u2,v2,w2,x2,y2,z2);
prints26(a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,o3,p3,q3,r3,s3,t3,u3,v3,w3,x3,y3,z3);
prints26(a4,b4,c4,d4,e4,f4,g4,h4,i4,j4,k4,l4,m4,n4,o4,p4,q4,r4,s4,t4,u4,v4,w4,x4,y4,z4);
prints26(a5,b5,c5,d5,e5,f5,g5,h5,i5,j5,k5,l5,m5,n5,o5,p5,q5,r5,s5,t5,u5,v5,w5,x5,y5,z5);
prints26(a6,b6,c6,d6,e6,f6,g6,h6,i6,j6,k6,l6,m6,n6,o6,p6,q6,r6,s6,t6,u6,v6,w6,x6,y6,z6);
prints26(a7,b7,c7,d7,e7,f7,g7,h7,i7,j7,k7,l7,m7,n7,o7,p7,q7,r7,s7,t7,u7,v7,w7,x7,y7,z7);
prints26(a8,b8,c8,d8,e8,f8,g8,h8,i8,j8,k8,l8,m8,n8,o8,p8,q8,r8,s8,t8,u8,v8,w8,x8,y8,z8);
prints26(a9,b9,c9,d9,e9,f9,g9,h9,i9,j9,k9,l9,m9,n9,o9,p9,q9,r9,s9,t9,u9);
}
function prints26(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) {
if (a) {print prints1(a) } else {return 1};
if (b) {print prints1(b) } else {return 1};
if (c) {print prints1(c) } else {return 1};
if (d) {print prints1(d) } else {return 1};
if (e) {print prints1(e) } else {return 1};
if (f) {print prints1(f) } else {return 1};
if (g) {print prints1(g) } else {return 1};
if (h) {print prints1(h) } else {return 1};
if (i) {print prints1(i) } else {return 1};
if (j) {print prints1(j) } else {return 1};
if (k) {print prints1(k) } else {return 1};
if (l) {print prints1(l) } else {return 1};
if (m) {print prints1(m) } else {return 1};
if (n) {print prints1(n) } else {return 1};
if (o) {print prints1(o) } else {return 1};
if (p) {print prints1(p) } else {return 1};
if (q) {print prints1(q) } else {return 1};
if (r) {print prints1(r) } else {return 1};
if (s) {print prints1(s) } else {return 1};
if (t) {print prints1(t) } else {return 1};
if (u) {print prints1(u) } else {return 1};
if (v) {print prints1(v) } else {return 1};
if (w) {print prints1(w) } else {return 1};
if (x) {print prints1(x) } else {return 1};
if (y) {print prints1(y) } else {return 1};
if (z) {print prints1(z) } else {return 1};
}
function prints1(x) { # if starts with a " ", then indent this string
return x ~ /^ / ? " "x : x;
}
# #---- [getopt.awk ] ------------------------------------------
#!/usr/bin/gawk -f
# getopt --- do C library getopt(3) function in awk
# Author: arnold@gnu.ai.mit.edu (in the 1990s)
# (and the clearArgs() function was added at the suggestion of Mathew Hall
# Tue, 2 Aug 2005)
# Valid options are passed to a function opt(opts,opt,arg) which
# must be supplied outside this file. e.g.
#
# function opt(opts,flag,arg) { print opt "= [" arg "]" }
# USAGE:
# a call to "getOpts(String)" (e.g. getopts("ab:cd") )
# will lead to on call xoof opt for each valid argument
function getOpts(opts, debug, tmp) {
Optind = 1; # skip ARGV[0]
Opterr = debug; # default is to diagnose
while ((tmp = getopt(ARGC, ARGV, opts)) != -1)
set(tmp, Optarg);
clearARGV(debug);
}
# External variables:
# Optind -- index of ARGV for first non-option argument
# Optarg -- string value of argument to current option
# Opterr -- if non-zero, print our own diagnostic
# Optopt -- current option letter
# Returns
# -1 at end of options
# ? for unrecognized option
# a character representing the current option
function getopt(argc, argv, options, thisopt, i) {
if (length(options) == 0) # no options given
return -1;
if (argv[Optind] == "--") { # all done
Optind++;
_opti = 0;
return -1;
} else if (argv[Optind] !~ /^-[^: \t\n\f\r\v\b]/) {
_opti = 0;
return -1;
}
if (_opti == 0)
_opti = 2;
thisopt = substr(argv[Optind], _opti, 1);
Optopt = thisopt;
i = index(options, thisopt);
if (i == 0) {
if (Opterr)
printf("%c -- invalid option\n",
thisopt) > "/dev/stderr"
if (_opti >= length(argv[Optind])) {
Optind++;
_opti = 0;
} else
_opti++;
return "?";
}
if (substr(options, i + 1, 1) == ":") {
# get option argument
if (length(substr(argv[Optind], _opti + 1)) > 0)
Optarg = substr(argv[Optind], _opti + 1);
else
Optarg = argv[++Optind];
_opti = 0;
} else
Optarg = "";
if (_opti == 0 || _opti >= length(argv[Optind])) {
Optind++;
_opti = 0
} else
_opti++;
return thisopt;
}
function clearARGV(debug, i,n,tmp) {
for(i=0;i<=ARGC;i++)
if(i>=Optind ) {
tmp[++n]=ARGV[i];
if(debug && i!=ARGC) printf("\trest ARGV[%d] = <%s>\n",i, ARGV[i]);
} else {
if(debug) printf("\tused ARGV[%d] = <%s>\n",i, ARGV[i]);
}
split("",ARGV,"");
ARGC=0
for(i in tmp)
ARGV[++ARGC]=tmp[i];
}
# #---- [inits.awk ] ------------------------------------------
function inits(flags,str, argp,tmp,n,i,x) {
argps(argp,flags);
n=split(str,tmp," ");
while(i < n) {
i++;
x=tmp[i];
if (sub(/^-/,"",x)) {
if(argp[x]) {
set(x,tmp[i+1]); i++
} else { set(x) }
} else {bad("skipping " tmp[i-1] " " x)}
}
}
function argps(argp,flags, x,n,tmp,i) {
n=split(flags,tmp,"");
for(i=1;i<=n;i++)
if (tmp[i]==":")
argp[tmp[i-1]]=1
}
# #---- [bad.awk ] ------------------------------------------
#Stuff
function bad(str) {
print str >> "/dev/stderr";
fflush("/dev/stderr");
Errors++;
Patience--;
}
function imPatient() {
if (Patience<=0) {
print "Aborting" >> "/dev/stderr";
fflush("/dev/stderr");
exit 1 }
}
function badIf(check,txt) {
if (check) bad(txt); return check;
}
BEGIN { Who = "Tim Menzies";
What = "malign";
When = "2006";
How = "cht:b:o:w:g:r";
Why = "align columns in a text file";
}
function usage() {
about(Who,What,When,Why);
prints("Usage: "What" [FLAGS] ",
" -r raw mode: turns off cell trimming",
" -w NUM minimum column width",
" -g NUM minimum gutter width",
" -b CHAR input file sepertor",
" -o CHAR output file sepertor",
" -c show copyright",
" -h show help");
}
function defaults() {
inits(How,"-w 1 -g 1 -b , -o ,");
}
function set(x,y) {
if (x == "r") {return set("t",0) };
if (x == "t") {return Trim = y};
if (x == "w") {return Width = y};
if (x == "g") {return Gutter = y};
if (x == "b") {return FS = y};
if (x == "o") {return OFS = y};
if (x == "c") {copyleft(); exit};
if (x == "h") {usage(); exit};
bad("usage: " What " " How); exit;
}
BEGIN {defaults(); getOpts(How); }
# #---- [malign.awk ] ------------------------------------------
{ N++;
for(I=1;I<=NF;I++) {
$I=Trim ? trim($I) : $I;
if( (L=length($I)) > Max[I]) Max[I]=L;
++Data[N,0]
Data[N,I]=$I;}
}
END {
for(J=1;J<=N;J++) {
Str=Sep1="";
if (Data[J,0]>1) {
for(I=1;I<=NF;I++) {
L=length(Data[J,I]);
Str = Str Sep1 str(most(Width,Max[I]+Gutter)-L," ") Data[J,I];
Sep1= OFS;
}} else {Str=Data[J,1]}
print Str;}
}