Currently there are several implementations of a table widget.
[[Please update the above list to document other examples]]
RS 2006-05-31: As data structures, tables (taken as rectangular matrixes of strings) can be well represented as a list of lists. Here is code for pretty-printing such a list, the resulting string looking (in fixed-pitch font only) like a table again:
proc fmtable table { set maxs {} foreach item [lindex $table 0] { lappend maxs [string length $item] } foreach row [lrange $table 1 end] { set i 0 foreach item $row max $maxs { if {[string length $item]>$max} { lset maxs $i [string length $item] } incr i } } set head + foreach max $maxs {append head -[string repeat - $max]-+} set res $head\n foreach row $table { append res | foreach item $row max $maxs {append res [format " %-${max}s |" $item]} append res \n } append res $head }
#-- Testing:
set data { {1 short "long field content"} {2 "another long one" short} {3 "" hello} } puts [fmtable $data]
#-- shows
+---+------------------+--------------------+ | 1 | short | long field content | | 2 | another long one | short | | 3 | | hello | +---+------------------+--------------------+
Extended version, with the framing lines optional:
proc fmtable {table {lines 0}} { set maxs {} foreach item [lindex $table 0] {lappend maxs [string length $item]} foreach row [lrange $table 1 end] { set i 0 foreach item $row max $maxs { if {[string length $item]>$max} { lset maxs $i [string length $item] } incr i } } if $lines { set head + foreach max $maxs {append head -[string repeat - $max]-+} set res $head\n set sep | } else {set sep ""} foreach row $table { append res $sep foreach item $row max $maxs {append res [format " %-${max}s $sep" $item]} append res \n } if $lines {append res $head} set res }
#-- Testing the two modes:
% fmtable {{hello world} {a longstring}} hello world a longstring % fmtable {{hello world} {a longstring}} 1 +-------+------------+ | hello | world | | a | longstring | +-------+------------+