############################################################################ # # File: colmize.icn # # Subject: Procedures to arrange data into columns # # Author: Robert J. Alexander # # Date: June 15, 1990 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # colmize() -- Arrange data into columns. # # Procedure to arrange a number of data items into multiple columns. # Items are arranged in column-wise order, that is, the sequence runs # down the first column, then down the second, etc. # # This procedure goes to great lengths to print the items in as few # vertical lines as possible. # ############################################################################ procedure colmize(entries,maxcols,space,minwidth,tag,tagspace,tagminwidth,rowwise,distribute) local mean,cols,lines,width,i,x,wid,extra,t,j,first_tagfield,tagfield # # Process arguments -- provide defaults. # # entries: a list of items to be columnized /maxcols := 80 # max width of output lines /space := 2 # min nbr of spaces between columns /minwidth := 0 # min column width # tag: a label to be placed on the first line of output /tagminwidth := 0 /tagspace := 2 # rowwise: if nonnull, entries are listed in rowwise order rather than # columnwise # # # Process the tag field information. The tag will appear on the # first line to the left of the data. # if \tag then { tagminwidth <:= *tag + tagspace maxcols -:= tagminwidth first_tagfield := left(tag, tagminwidth - tagspace) || repl(" ",tagspace) tagfield := repl(" ",tagminwidth) } else tagfield := first_tagfield := "" # Starting with a trial number-of-columns that is guaranteed # to be too wide, successively reduce the number until the # items can be packed into the allotted width. # mean := 0 every mean +:= *!entries mean := mean / (0 ~= *entries) | 1 every cols := (maxcols + space) * 2 / (mean + space) to 1 by -1 do { lines := (*entries + cols - 1) / cols width := list(cols,minwidth) i := 0 if /rowwise then { # if column-wise every x := !entries do { width[i / lines + 1] <:= *x + space i +:= 1 } } else { # else row-wise every x := !entries do { width[i % cols + 1] <:= *x + space i +:= 1 } } wid := 0 every x := !width do wid +:= x if wid <= maxcols + space then break } # # Now output the data in columns. # extra := (\distribute & (maxcols - wid) / (0 < cols - 1)) | 0 if /rowwise then { # if column-wise every i := 1 to lines do { if i = 1 then t := first_tagfield else t := tagfield every j := 0 to cols - 1 do t ||:= left(entries[i + j * lines],width[j + 1] + extra) suspend trim(t) } } else { # else row-wise every i := 0 to lines - 1 do { if i = 0 then t := first_tagfield else t := tagfield every j := 1 to cols do t ||:= left(entries[j + i * cols],width[j] + extra) suspend trim(t) } } end