use str use ./list fn -repeat {|n s| repeat $n $s | str:join '' } fn left {|size s| var ss = (count $s) var d = (- $size $ss) if (<= $d 0) { put $s[:$size] } else { put $s(-repeat $d ' ') } } fn right {|size s| var ss = (count $s) var d = (- $size $ss) if (<= $d 0) { put $s[:$size] } else { put (-repeat $d ' ')$s } } fn center {|size s| use math var ss = (count $s) var d = (- $size $ss) if (<= $d 0) { var l = (math:ceil (/ -$d 2)) var r = (- (+ $ss $d) $l) put $s[$l':'$r] } else { var l = (math:ceil (/ $d 2)) var r = (- $d $l) put (-repeat $l ' ')$s(-repeat $r ' ') } } fn -c2map {|col| if (not-eq (kind-of $col) list) { put [] return } list:loop {|i c| var k = (kind-of $c) var cf = [&min=0] if (is $k string) { set cf[min] = $c } elif (is $k map) { if (has-key $c min) { set cf[min] = $c[min] } if (has-key $c align) { set cf[align] = $c[align] } } set col[$i] = $cf } $col put $col } fn -parsecols {|col &split=$false lst| set col = (-c2map $col) var cc lines = (count $col) $lst if $split { set lines = [ (eawk {|_ @args| put $args } $lst) ] } each {|l| var cl = (count $l) if (> $cl $cc) { set col = [ $@col (range (- $cl $cc) | each {|_| put [&align=left &min=0] }) ] set cc = $cl } list:loop {|i c| var ccl = (+ (count $c) 1) if (> $ccl $col[$i][min]) { set col[$i][min] = $ccl } } $l } $lines put $col } fn -format {|f e| var cb = $left~ if (has-key $f align) { var a = $f[align] if (is $a right) { set cb = $right~ } elif (is $a center) { set cb = $center~ } } $cb $f[min] $e } fn -formatline {|col line| list:loop {|i v| -format $col[$i] $v } $line | str:join '' } fn format {|&col=[] &split=$false @lst| var lines = (list:-p $@lst) if $split { set lines = [ (eawk {|l @args| put $args } $lines) ] } set col = (-parsecols $col $lines) each {|l| -formatline $col $l } $lines }