fr - A prototype of word completion instant command completion in the iFile 1.1 console. Completion works on first word only in ComboBox entry. The string appended is the longest common beginning of all possible endings. Clickable continuations are displayed in a toplevel widget. Start typing a character, then repeatedly invoke the created buttons to get the wished command.
usage: append this to the iFile script or save this as q.tcl in same dir as iFile.tcl append following line to iFile.tcl PC: source [file join [file dirname [info script]] q.tcl] on PDA (WinCE): source q.tcl additional requirements: font_ce, puts_ce known bug: continuations not up to date when using the keyboard (e.g. tk_messageBox, open, option)
} namespace eval ::q { variable tracedvar variable entry variable pp "" variable pattern "" variable temp [list] variable suffixlist [list] variable packages [lsort [package names]] variable added_prefixes [list] } proc ::q::qcoco {entryname varname x mode} { # puts varname=$varname; puts x=$x; puts mode=$mode # completion for the first word if {$::q::ok} { set v :: append v $varname\($x\) set v [subst $$v] if {![regexp {^\S+\s} $v]} { set pos 0 # only first word is assumed to be a command set ns "" set colon "" set ::q::pattern "" regexp -nocase {(^[^:]*)(::)*([a-z0-9_:]*)} $v {&1&2&3} ns colon ::q::pattern if {$colon == ""} { set ::q::pattern $ns set ns :: } else { # learn used package names if {[lsearch -sorted $::q::added_prefixes $ns] < 0} { if {[lsearch -sorted $::q::packages $ns] >=0} { lappend ::q::added_prefixes $ns set ::q::added_prefixes [lsort $::q::added_prefixes] } } } incr pos [string length $::q::pattern] set pa ^$::q::pattern set ::q::pp $::q::pattern* set l [list] if {[::q::isnopackage $ns]} { namespace eval $ns {set ::q::commands [info command $::q::pp]} foreach x $::q::commands { lappend l [string range $x $pos end] } foreach idx [lsearch -all -sorted -regexp $::q::added_prefixes $pa] { lappend l [string range [lindex $::q::added_prefixes $idx] $pos end] } if {0} { # package names foreach x $::q::packages { if {[regexp $pa $x]} { lappend l [string range $x $pos end] } } } } else { set n :: append n $ns append n :: append n $::q::pattern set len [string length $n] append n * foreach x [info proc $n] { lappend l [string range $x $len end] } } ::q::conti [lsort -unique -dictionary $l] set add "" foreach ff [split [lindex $::q::suffixlist 0] {}] ll [split [lindex $::q::suffixlist end] {}] { expr {$ff==$ll ? [append add $ff] : [break] } } append v $add set xl [llength $l] if {[llength $l] == 1} { # no alternatives exist #append add { } $entryname insert insert $add set ::q::suffixlist [list] ;# no need to display } else { if {[llength $l]==0} { # invalid character entered if {![string equal $v :]} { set prev [$entryname index insert] incr prev -1 $entryname selection range $prev end } } else { $entryname insert insert $add # display continuations as buttons } } } else { set ::q::text "" set ::q::suffixlist [list] } } else { set ::q::ok 1 } ::q::topcon $entryname $varname } proc ::q::insertpos {entryname x y} { # todo # calculate position below insert mark of entry # add +y positions of .n (notebook).n.f5 (frame) .n.f5.e (ComboBox) # plus height of ComboBox upvar $x X upvar $y Y set X 20 set Y 110 } proc ::q::topcon {w var} { set name .qcon append name $w regsub -all -start 1 {\.} $name _ name #catch {destroy $name} #destroy & toplevel -> no more winhandle map slots set len [llength $::q::suffixlist] catch {wm withdraw $name} if {$len==0} {return} if {$len==1 && [lindex $::q::suffixlist] == { } } {return} if {![winfo exists $name]} { set widget [toplevel $name] } else { foreach x [winfo children $name.f] { destroy $x } destroy $name.f set widget $name } ::q::insertpos $w px py wm geometry $widget +$px+$py wm overrideredirect $widget 1 set sw $widget set sf [frame $sw.f] $sf configure -bg bisque set ii 0 foreach x $::q::suffixlist { set j [button $sf.b$ii -text $x -justify left -border 0 -bg white -fg black -activebackground skyblue -activeforeground white -takefocus 0] pack $j -side top -padx 2 -pady 1 -anchor w $j configure -command [list ::q::button_invoke $w $x] incr ii } pack $sf -fill both wm deiconify $name } proc ::q::button_invoke {entryname suffix} { global g set t [$entryname cget -text] append t $suffix $entryname insert insert $suffix focus $entryname set g(cmd) $t } proc ::q::isnopackage {v} { if {$v==""} {return 1} set pattern [format "^%s::" $v] foreach x $::q::packages { if {[regexp $pattern $x]} { return 0 } } return 1 } proc ::q::off {} { #set k [trace info variable $::q::tracedvar] # trace vdelete ::g(cmd) [lindex $k {0 1}] trace vdelete $::q::tracedvar w [list ::q::qcoco $::q::entry] set ::q::text "::q::on ;# instant command" bind $::q::entry <Key-BackSpace> {} } proc ::q::about {} { set t { iFile command completion basic prototype Roland Frank, Aalen 2005 www.deltadatentechnik.de } catch {destroy.qab} toplevel .qab wm title .qab contributors label .qab.l -justify center -text $t pack .qab.l -pady 10 } proc ::q::on {{entryname .n.f5.e.e}} { # activate command completion in "iFile console" global g set g(cmd) "" set ::q::entry $entryname set ::q::tracedvar ::[$entryname cget -textvariable] set ::q::ok 1 bind $entryname <Key-BackSpace> { set ::q::ok 0 set ::q::suffixlist [list] } trace add variable $::q::tracedvar write [list ::q::qcoco $entryname] $entryname selection range 0 end } proc ::q::conti {inlist} { set ::q::temp [list] foreach x $inlist { if {$x == ""} { set x " " } ::q::merge $x 0 } set ::q::suffixlist $::q::temp set text "" set n 0 foreach x $::q::temp { incr n [string length $x] if {$n>30} { append text \n set n 0 } else { append text " " incr n } append text $x } set ::q::text $text } proc ::q::merge {value minlen} { # merge value to common prefix with last element of list set last [lindex $::q::temp end] if {$last != ""} { set lastlen [string length $last] set c "" foreach t1 [split $last ""] t2 [split $value ""] { expr {$t1==$t2 ? [append c $t1] : [break]} } if {$c!=""} { set clen [string length $c] if {$clen>$minlen} { if {$clen==$lastlen} { # skip #lappend ::q::temp $value } else { lset ::q::temp end $c } } else { lappend ::q::temp $value } } else { lappend ::q::temp $value } } else { set ::q::temp [list $value] } } .n.f5.e.e configure -text "::q::on ;# instant command, ::q::off" $5.l configure -textvariable ::q::text