MSW: The goal is to offer an entry widget which does auto-path-completion, offers completion on TAB (with cycling through the possibilities), and a popup menu to allow the user to specify the next directory(/ies).
pathentry works as follows: It takes all the arguments an entry takes, (because it's basically an entry with some bindings and extra commands), and offers two own commands, complete and popup.
This implementation is not yet done! I just thought I'd share my thoughts with you, because it happens to be quite usable already :)
Things lacking:
TAB: when there is 1 completion, complete. (done now through keyrelease) when there is > 1 completions, cycle through them
Martin Lemburg - 27.09.2002:
There are a some other things lacking:
suggestions:
MSW: I don't have windows or mac to test :) For the auto-complete, -completion <bool> is supposed to handle that. If it's false, only complete on <TAB>.
For the cascading menus, thought about that, but initially I wanted to offer the whole directory tree - which would be too compute intensive imho. For what you suggested, sounds reasonable.
I'll read some more into platform independant file name handling...
How to play
pathentry .e pack .e Focus it, enter the following three characters: '/', 'u', 'b'. In the entry now there should be '/usr/bin/' (on a typical unix) Toy around with backspace and the right mousebutton :)
Current implementation (no need to add the points I talked about above, will do that soon :) goes here:
proc pathentry {path args} { set arg {} if {[string index $path 0] != {.}} { return -code error "$path is no valid widget path!" } foreach {sw ar} $args { switch -- $sw { -completion { if {![string is boolean -strict $ar]} { return -code error "-completion takes a boolean argument, $ar is none." } } -popup { if {![string is boolean -strict $ar]} { return -code error "-popup takes a boolen argument, $ar is none." } } default { lappend arg $sw $ar } } } if {[lsearch $arg {-te*}]==-1} { # we NEED a textvar! lappend arg {-textvariable} "${path}_var" } if {[catch { eval [concat entry $path $arg] } err]} { return -code error $err } rename $path ${path}_entry proc $path {cmd args} { upvar #0 [set vname [[set pat [lindex [info level [info level]] 0]]_entry cget -textvariable]] acc switch -- $cmd { complete { if {[llength [set glo [glob -nocomplain "$acc*"]]]==1} { if {[file isdirectory [set acc $glo]]} { append acc / } $pat icursor end $pat xview end } else { return $glo } } partdel { for {set ac $acc} {![file exists $ac] && ![llength [glob -nocomplain $ac*]]} {set ac [string range $ac 0 end-1]} {} if {$ac != $acc} { set acc $ac } elseif {[file exists $acc]} { set acc [file dirname $acc] if {$acc != {/}} {append acc /} } else { set acc [string range $acc 0 end-1] } $pat icursor end $pat xview end } popup { foreach {xcoord ycoord} $args {break} if {[winfo exists $pat.popmen]} {destroy $pat.popmen} menu $pat.popmen -tearoff 0 -title {Path Completion} ; set ctr 0 set possible [lsort [$pat complete]]; if {[llength $possible]==1} {return} foreach poss $possible { $pat.popmen add command -label [file tail $poss] \ -command "if {\[file isdirectory \[set ::$vname $poss\]\]} { append $vname / } ; $pat icursor end; $pat xview end" incr ctr } if {$ctr} { tk_popup $pat.popmen $xcoord $ycoord } else { destroy $pat.popmen } } default { eval [concat ${pat}_entry $cmd $args] } } } bind $path <KeyRelease> "$path complete" bind $path <3> "$path popup %X %Y" bind $path <KeyRelease-BackSpace> "$path partdel; break" bind $path <KeyPress-BackSpace> { break } }
Comments ? Welcome ...