Search code examples
formatmaxtclwidth

Output list items as ls does


I'm trying to output something that resembles as ls output. The ls command outputs like this:

file1.txt   file3.txt    file5.txt
file2.txt   file4.txt

But I this sample list:

a b c d e f g h i j k l m n o p q r s t u v w x y z

to appear as:

a e i m q u y
b f j n r v z
c g k o s w 
d h l p t x

In that case, it gave 7 columns which is fine, but I wanted up to 8 columns max. Next the following list:

a b c d e f g h i j k l m n o p q r s t u v w

will have to show as:

a d g j m p s v
b e h k n q t w
c f i l o r u

And "a b c d e f g h" will have to show as is because it is already 8 columns in 1 line, but:

a b c d e f g h i

will show as:

a c e g i 
b d f h

And:

a b c d e f g h i j

a c e g i 
b d f h j

Solution

  • One way:

    #!/usr/bin/env tclsh                                                                                                                                                                                                                             
    
    proc columnize {lst {columns 8}} {
        set len [llength $lst]
        set nrows [expr {int(ceil($len / (0.0 + $columns)))}]
        set cols [list]
        for {set n 0} {$n < $len} {incr n $nrows} {
            lappend cols [lrange $lst $n [expr {$n + $nrows - 1}]]
        }
        for {set n 0} {$n < $nrows} {incr n} {
            set row [list]
            foreach col $cols {
                lappend row [lindex $col $n]
            }
            puts [join $row " "]
        }
    }
    
    
    columnize {a b c d e f g h i j k l m n o p q r s t u v w x y z}
    puts ----
    columnize {a b c d e f g h i j k l m n o p q r s t u v w}
    puts ----
    columnize {a b c d e f g h}
    puts ----
    columnize {a b c d e f g h i}
    puts ----
    columnize {a b c d e f g h i j}
    

    The columnize function first figures out how many rows are needed with a simple division of the length of the list by the number of columns requested, then splits the list up into chunks of that length, one per column, and finally iterates through those sublists extracting the current row's element for each column, and prints the row out as a space-separated list.