ilist

by Theo Verelst

of course feel free to comment, extend, ..

I was trying out some network (read: graph) things in Bwise, and am thinking about coming back to some basics I did years ago when I worked at university, for instance making an inspector window without all kinds of extra packages having to be loaded in simple enough and reusable tcl/tk code, and started by wanting to be able to in short list a hierarchy of lets call them objects..

Suppose we want to list all objects in the tk graphics hierarchy, like we would start with:

 winfo children .

And get a list of all root objects.

I made a routine called ilist which in short can do this hierarchically, with a simple and practical prettyprint, and which can be used for various other purposes:

 proc ilist { {begin {.}} {listf {winfo children}} {maxdepth {100}} {ident {0}} {isleaf {}} } {
 # isleaf function defined means not-leafs themselves are filtered out
 # and that puts of the results is turned off
   if {$maxdepth <1} return
   set de {}; set o {}
   for {set i 0} {$i < $ident} {incr i} {append de "   "}
   foreach i [eval "$listf $begin"] {
      if {$isleaf == {}} {
         lappend o $i
         puts "$de $i"
         eval lappend o [ilist [list $i] $listf [expr $maxdepth-1] [expr $ident +1] $isleaf]
      } {
         if {[isleaf $i]} {
            lappend o $i
         } {
            eval lappend o [ilist [list $i] $listf [expr $maxdepth-1] [expr $ident +1] $isleaf]
         }
      }
   }
   return $o
 }

TV (Dec 1 2003) I added a list around the last i above, to make the argument passing deal with file/path names with spaces in them as lists. That was using the wiki as storage to prepare for a page on Updating image directories from a memorystick automatically.

A day later I updated the function to include a isleaf procedure argument, because I wanted to make a hierarchical list of files, which should not include directories.

I didn't test the new ilist above with other than file hierarchies yet, but I guess it should be ok.

Example functions for list and isleaf are:

 proc files {d} {if [catch {glob $d/*} r] {return {}} {return $r} }
 proc isleaf {f} {if [file isdir $f] {return 0} {return 1}}

Example use:

 ilist . files 100 0 isleaf

to get a list of all files below the current directory, not listing hierarchy, only returning a list of the result (no idented printing), until a depth of 100.

On unix/linux/cygwin, you'd normally use:

 $ find . -name '*' -print

for a similar result, except a file per line, not a list, as result.

And I found out that glob doesn't list the windows invisible (hidden) files. Ah, at least in 8.4.4 there is glob -type hidden.


Of course advanced programmers know what a recursive procedure is and can easily do this maybe as a one liner from the top of their head, but it is good practice to think straight about things, and conceptually I find this pleasing enough.

calling simply ilist in bwise prints:

 .fb
    .fb.bnewb
    .fb.quit
    .fb.p
    .fb.bwire
    .fb.bcdrum
    .fb.bcscope
    .fb.bscan
    .fb.bdel
    .fb.bsave
    .fb.bload
 .mw
    .mw.hscroll
    .mw.vscroll
    .mw.c
       .mw.c.pm
 .f
    .f.l
    .f.t
    .f.f
       .f.f.b
       .f.f.b2
       .f.f.f
       .f.f.bs
 .tt
    .tt.t
    .tt.f
       .tt.f.e
       .tt.f.s
       .tt.f.l

Practically, the same routine can be reused also to list files at least when we first make an adapted glob called files:

 proc files {d} {if [catch {glob $d/*} r] {return {}} {return $r} }

Now use this as listing routine for ilist:

 ilist . files

gave as example:

 ./Nets
    ./Nets/array1
    ./Nets/array2.tcl
    ./Nets/vararray2.tcl
 ./bwise031.tcl
 ./defaultprocs.tcl
 ./paper.gif
 ./ilist.tcl

In a network I tried listing all possible functional decomposition paths, for example starting from the array like structure which comes with bwise and can be commandline called with

 newarray

without arguments, or instantiated anywhere on the canvas by pressing the right mouse button (when you have two, edit bwise by text searching for button-3 and replace just two occurances) and chosing the command with the same name.

now use:

 ilist array2_2 net_left

to get:

 array1_2
    array0_2
       array0_1
          array0_0
    array1_1
       array0_1
          array0_0
       array1_0
          array0_0
 array2_1
    array1_1
       array0_1
          array0_0
       array1_0
          array0_0
    array2_0
       array1_0
          array0_0

to make lists of preceding connected blocks until the 'left end' of the graph interpreted as a recursive function with reused partial functions.


Category File - Category GUI