[Hackmeeting] kaostour a milano - 03-10 marzo 2005

Delete this message

Reply to this message
Autore: jaromil
Data:  
Oggetto: [Hackmeeting] kaostour a milano - 03-10 marzo 2005


#!/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


}