Kevin Walzer I was trying to create a variation of the standard Tk file browser handled with a listbox, which would emulate the NeXT (now Mac OS X) style of file browsing: navigating horizontally across a file system. I hit a wall and asked for help on comp.lang.tcl. Kaitzschu came to the rescue and did more than add some guidance to my rough initial code; he radically transformed it. Thanks to Kaitzchu for the help.
The result is below, licensed under the standard Tcl BSD-style license. Embellishments and improvements are more than welcome!
package require Tcl 8.5 package require Tk namespace eval ::nextlist {namespace export nextlist} proc ::nextlist::nextlist {wid dir} { if {![file isdirectory $dir]} {error "non-directory $dir"} nlist [frame $wid] $dir 0 return $wid } proc ::nextlist::nlist {base dir cnt} { if {![file isdirectory $dir]} {return}; # here file-clicketyclicks # check for [file readable]? nah # dear santa, let children be in order destroy {*}[lrange [winfo children $base] [expr {2*$cnt}] end] # exportselection 0 looks good, but selection gets easily out-of-sync set l [listbox "[set b "$base.nl$cnt"]-list" -yscrollcommand [list "$b-scroll" set] -height 20 -exportselection 0] pack $l [scrollbar "$b-scroll" -command [list $l yview]] -side left -expand 1 -fill y -anchor w # I like my directories first and everything dictionarized, love {*} # could be done with intermediate list and $l insert end {*}$lst foreach item [concat [lsort -dictionary [glob -directory $dir -nocomplain -types {d} -- *]] \ [lsort -dictionary [glob -directory $dir -nocomplain -types {f} -- *]]] \ {$l insert end "[file tail $item][expr {[file isdirectory $item] ? {/} : {}}]"} bind $l <Double-1> [list ::nextlist::navigare $dir [incr cnt] %W %x %y] } proc ::nextlist::navigare {d c w x y} { if {[set subdir [$w get [$w index "@$x,$y"]]] eq {}} {return} nlist [winfo parent $w] [file join $d $subdir] $c } # To test this code, try the following command: pack [::nextlist::nextlist .nl ~/Desktop]
You will see listboxes added and deleted horizontally as you navigate through the file hierarchy.
With all due respect to the author's love of {*}, the second use of it is rather pointless:
[list {*}[lsort ...] {*}[lsort ...]]
is equivalent to, but not as clear as
[concat [lsort ...] [lsort ...]]
Kaitzschu Guilty as charged. Use concat, it is also very, very fast once lists get bigger. I wasn't familiar with this command, because its manual page is confounding wrt use with lists (trimming and spaces, sounds too much like strings).
jcw - And by writing "eval destroy [...]", the same code runs in 8.x ...
NEM - Removed a rogue "09" in the code that caused a dreaded octal error. Not sure where the stray 9 came from.
RKzn 20161027 - changed
if {![file isdirectory $dir]} {return; # here file-clicketyclicks}
to
if {![file isdirectory $dir]} {return}; # here file-clicketyclicks
because the first one breaks auto-indentation, with emacs' tcl-mode; and I agree with it that the second version it is clearer.
Also changed the "[list {*}[lsort ..." to "[concat [lsort ..." as suggested above and it works just fine (8.6.3)