#!/usr/bin/awk -f
#
# Script to justify plain text paragraphs with same length
# written on a train ride between Bangalore and Ahmedabad
# use inside vim: press !}giustifica.awk on the paragraph
# copyleft 2005 by jaromil \at\ dyne.org - GNU GPL
BEGIN {
COLUMNS = 72
queue["pos"] = 0
queue["head"] = 0
queue["tot"] = 0
queue["wtot"] = 0
}
function fill_line(q, l) {
# q = source array ; l = dest array
lw = 0
lf = 0
qp = q["pos"]
qh = q["head"]
qw = q["wtot"]
qt = q["tot"]
while(1) {
wl = length( q[qp] )
if(lw + wl + lf >= COLUMNS) break
lw = lw + wl
l[lf] = q[qp]
lf++
delete q[qp]
qp++
if(qp > qh) break # end of queue
qw = qw - wl
qt--
# if it's about one last space, go for it
if(lw + lf == COLUMNS) break
}
q["pos"] = qp
q["wtot"] = qw
q["tot"] = qt
l["len"] = lf
l["width"] = lw
return lf
}
function print_line(l) {
lf = l["len"]
lw = l["width"]
gap = COLUMNS - (lw + lf)
# don't justify if the gap is too big
# if( ! ( gap < (nfs*4) ) ) next
if( gap == 0 || gap > COLUMNS/2) { # perfect!
for(c=0; c<(lf-1); c++)
printf l[c] " "
print l[lf-1] # print the last without spacing
} else {
# line is shorter, we must space it
gs = 0 # global space to add after every field
ss = 0 # splitted space to add to begin/end fields
while(gap>0) {
gap = gap - (lf-1)
if(gap<0) ss = (lf-1) + gap
else gs++
}
for(c=0; c<(lf-1); c++) {
printf l[c] " "
for(cc=0; cc<gs; cc++) printf " "
if(ss>0) {
printf " "
ss--
}
}
print l[lf-1] # print the last without spacing
}
}
{
# save all the new words in our queue
qf = queue["head"]
qw = queue["wtot"]
for(c=1; c<=NF; c++) {
queue[qf] = $c
qf++
qw = qw + length($c)
queue["tot"]++
}
queue["head"] = qf
queue["wtot"] = qw
# queue more words (todo intentional newline)
if(qw < COLUMNS) next
fill_line(queue, line)
print_line(line)
delete line # could use split("", line) for portability
}
END {
while( queue["tot"]>0 ) {
fill_line(queue, line)
print_line(line)
}
delete queue
}