[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. * ''path'' complete tries to complete the current text in the entry if there is an unambigous completion, and if there is none, the text is not changed, but a list of all possible completions is returned. * ''path'' popup takes two arguments (X & Y coordinates) and pops up a menu to allow the user to choose from the possible completions. If there is only one unambigous completion, the completion is filled in, and no menu pops up. * ''path'' partdel (partial delete) deletes either the last path component if the current value exists, cuts back to the next possible start of possible globs if it doesn't and isn't a start of globs, or simply deletes a char if none of that is true. 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:''' * The options -popup and -completion only accept 0 and 1 for now, should also accept yes, no, false, true * The options -popup and -completion are ignore atm :) * an option -menusize, telling the popup menu to launch submenus for more than x entries (on unix, enter /usr/bin into the entry and click on it with the right mousebutton to see what I mean) * configure and cget must be caught, too, to offer runtime altering of the pathentries options * TAB bindings: TAB: when there is 1 completion, complete. (done now through keyrelease) when there is > 1 completions, cycle through them ---- '''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 {[catch { expr !$ar }]} { return -code error "-completion takes a boolean argument, $ar is none." } } -popup { if {[catch { expr !$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 "$path complete" bind $path <3> "$path popup %X %Y" bind $path "$path partdel; break" bind $path { break } } ---- '''Comments''' ? Welcome ...