1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
# $Id: completion.tcl,v 1.6 2003/11/06 21:19:26 aleksey Exp $
namespace eval completion {
set options(prefix) ""
set options(suffix) " "
set options(nlprefix) ""
set options(nlsuffix) ": "
}
proc completion::complete {chatid} {
variable completion
variable options
variable comps {}
global grouproster
if {![info exists completion(state,$chatid)] || \
[cequal $completion(state,$chatid) normal]} {
set completion(state,$chatid) completed
}
set iw [chat::input_win $chatid]
if {$completion(state,$chatid) == "menu_next" && \
[$iw compare insert == compins]} {
set word $completion(word,$chatid)
hook::run generate_completions_hook \
$chatid [namespace current]::comps \
[clength [$iw get 1.0 compstart]] \
[$iw get 1.0 "end -1c"]
set len [clength $word]
set matches {}
foreach comp $comps {
if {[string equal -nocase -length $len $word $comp]} {
lappend matches $comp
}
}
set n [llength $matches]
if {!$n} {return}
set completion(idx,$chatid) [expr ($completion(idx,$chatid)+1) % $n]
set comp [lindex $matches $completion(idx,$chatid)]
$iw delete compstart compend
$iw insert compstart $comp
return
} elseif {$completion(state,$chatid) == "menu_next"} {
set completion(state,$chatid) completed
}
set ins [lindex [split [$iw index insert] .] 1]
set line [$iw get "insert linestart" "insert lineend"]
set lbefore [crange $line 0 [expr $ins - 1]]
#set lafter [crange $line $ins end]
regexp {(\S*)$} $lbefore temp word
set wordstart [expr $ins - [clength $word]]
#set word [$iw get "insert -1 chars wordstart" insert]
debugmsg plugins "COMPLETION: $word"
if {1 || $word != ""} {
hook::run generate_completions_hook \
$chatid [namespace current]::comps \
[clength [$iw get 1.0 "insert linestart +$wordstart chars"]] \
[$iw get 1.0 "end -1c"]
set len [clength $word]
set matches {}
foreach comp $comps {
if {[string equal -nocase -length $len $word $comp]} {
lappend matches $comp
}
}
debugmsg plugins "COMPLETION: $matches"
if {[llength [lrmdups $matches]] == 1 || \
$completion(state,$chatid) == "menu_start"} {
set comp [lindex $matches 0]
$iw delete "insert linestart +$wordstart chars" insert
$iw insert insert $comp
if {$completion(state,$chatid) == "menu_start"} {
set compstart $wordstart
set compend [expr $compstart + [clength $comp]]
$iw mark set compstart "insert linestart +$compstart chars"
$iw mark gravity compstart left
$iw mark set compend "insert linestart +$compend chars"
$iw mark gravity compend right
$iw mark set compins insert
set completion(state,$chatid) menu_next
set completion(word,$chatid) $word
set completion(idx,$chatid) 0
}
} elseif {[llength [lrmdups $matches]] > 1} {
set app ""
while {[set ch [same_char $matches $len]] != ""} {
debugmsg plugins "COMPLETION APP: $len; $ch"
append app $ch
incr len
}
$iw insert insert $app
set completion(state,$chatid) menu_start
}
}
}
proc completion::same_char {strings pos} {
if {![llength $strings]} {
return ""
}
set strs [lassign $strings str1]
set ch [string index $str1 $pos]
foreach str $strs {
if {![string equal -nocase $ch [string index $str $pos]]} {
return ""
}
}
return $ch
}
proc completion::nick_comps {chatid compsvar wordstart line} {
if {![chat::is_groupchat $chatid]} return
variable options
global grouproster
upvar 0 $compsvar comps
debugmsg plugins "COMPLETION N: $comps"
if {!$wordstart} {
set prefix $options(nlprefix)
set suffix $options(nlsuffix)
} else {
set prefix $options(prefix)
set suffix $options(suffix)
}
set nickcomps {}
foreach jid $grouproster(users,$chatid) {
lappend nickcomps $prefix[chat::get_nick $jid groupchat]$suffix
}
set nickcomps [lsort -dictionary -unique $nickcomps]
set comps [concat $nickcomps $comps]
debugmsg plugins "COMPLETION N: $comps"
}
hook::add generate_completions_hook \
[namespace current]::completion::nick_comps 90
proc completion::sort_comps {chatid compsvar wordstart line} {
upvar 0 $compsvar comps
set comps [lsort -dictionary -unique $comps]
debugmsg plugins "COMPLETION S: $comps"
}
hook::add generate_completions_hook \
[namespace current]::completion::sort_comps 75
proc completion::delete_suffix {chatid} {
variable completion
variable options
set iw [chat::input_win $chatid]
if {![info exists completion(state,$chatid)]} return
if {([cequal $completion(state,$chatid) menu_next] || \
[cequal $completion(state,$chatid) completed]) && \
[$iw compare insert == {end - 1 chars}]} {
set ind [list insert - [string length $options(suffix)] chars]
if {[cequal [$iw get $ind insert] $options(suffix)]} {
$iw delete $ind insert
}
}
set completion(state,$chatid) normal
}
proc completion::setup_bindings {chatid type} {
variable history
set iw [chat::input_win $chatid]
set cc CompCtl$iw
set bt [bindtags $iw]
set bt [lreplace $bt -1 -1 $cc]
bindtags $iw $bt
debugmsg plugins "COMPLETION TAGS: $bt"
bind $cc <Key-Tab> \
[list [namespace current]::complete [double% $chatid]]
bind $cc <Key-Tab> +break
bind $cc <Key-Return> [list [namespace current]::delete_suffix [double% $chatid]]
bind $cc <KeyPress> \
[list set \
[double% [namespace current]::completion(state,$chatid)] \
normal]
}
hook::add open_chat_post_hook [namespace current]::completion::setup_bindings
|