Version 0 of pathentry

Updated 2002-09-26 13:07:14

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.

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 and BACKSPACE bindings:
         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
  • The actions TAB and BACKSPACE invoke will be offered as widget commands, too.
  • binding on entering text into the widget: As soon as there is == 1 completion, complete. Change bg color as soon as there is == 0 completions.

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 ...