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.
there is an unambigous completion, and if there is none, the text is not changed, but a list of all possible completions is returned.
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.
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. when there is > 1 completions, cycle through them BACKSPACE: Delete a whole path-component (filename or directory) if path exists, otherwise as much as is needed to be a startpoint for a possible completion again
To play with it in its current shape:
pathentry .e -textvar banzai pack .e ; set banzai /us
click on it with the right mousebutton, and play some :)
Current implementation (no need to add the points I talked about above, will do that soon :) goes here:
# pathentry: Offer an entry widget with automatic path completion # as well as TAB completion. There's a binding for Backspace, too. 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 {[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 #puts stderr "$pat $cmd $args" if {$cmd == {complete}} { if {[llength [set glo [glob -nocomplain "$acc*"]]]==1} { #puts stderr "..complete, llength: 1, val $glo" set acc $glo } else { #puts stderr "..complete, llength != 1, val $glo" ; return $glo } } elseif {$cmd == {popup}} { #puts stderr "..popup" foreach {xcoord ycoord} $args {break} #puts stderr "..popup: x: $xcoord, y: $ycoord; winfo exists $pat.popmen: [winfo exists $pat.popmen]" if {[winfo exists $pat.popmen]} {destroy $pat.popmen} menu $pat.popmen -tearoff 0 -title {Path Completion} ; set ctr 0 #puts stderr "..popup: menu created" 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" incr ctr #puts stderr "..poup: Added completion $poss, ctr: $ctr" } if {$ctr} { tk_popup $pat.popmen $xcoord $ycoord } else { destroy $pat.popmen } } else { eval [concat [lindex [info level [info level]] 0]_entry $cmd $args] } } bind $path <3> "$path popup %X %Y" }
Comments ? Welcome ...