vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: AceTab-2.0
3 Revision: $Rev: 16217 $
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
5 Website: http://www.wowace.com/
6 Documentation: http://www..wowace.com/index.php/AceTab-2.0
7 SVN: http://svn.wowace.com/root/trunk/Ace2/AceTab-2.0
8 Description: A tab-completion library
9 Dependencies: AceLibrary, AceEvent-2.0
10 ]]
11  
12 local MAJOR_VERSION = "AceTab-2.0"
13 local MINOR_VERSION = "$Revision: 16217 $"
14  
15 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
16 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
17  
18 local AceEvent
19 local AceTab = {}
20 local _G = getfenv()
21  
22 local hookedFrames = {}
23 local framesHooked = {}
24  
25 function AceTab:RegisterTabCompletion(descriptor, regex, wlfunc, usage, editframes)
26 self:argCheck(descriptor, 2, "string")
27 self:argCheck(regex, 3, "string", "table")
28 self:argCheck(wlfunc, 4, "string", "function", "nil")
29 self:argCheck(usage, 5, "string", "function", "boolean", "nil")
30 self:argCheck(editframe, 6, "string", "table", "nil")
31  
32 if type(regex) == "string" then regex = {regex} end
33  
34 if type(wlfunc) == "string" and type(self[wlfunc]) ~= "function" then
35 self:error("Cannot register function %q; it does not exist", wlfunc)
36 end
37  
38 if type(usage) == "string" and type(self[usage]) ~= "function" then
39 self:error("Cannot register usage function %q; it does not exist", usage)
40 end
41  
42 if not editframes then editframes = {"ChatFrameEditBox"} end
43  
44 if type(editframes) == "table" and editframes.Show then editframes = {editframes:GetName()} end
45  
46 for _, frame in pairs(editframes) do
47 local Gframe
48 if type(frame) == "table" then
49 Gframe = frame
50 frame = frame:GetName()
51 else
52 Gframe = _G[frame]
53 end
54  
55 if type(Gframe) ~= "table" or not Gframe.Show then
56 self:error("Cannot register frame %q; it does not exist", frame)
57 frame = nil
58 end
59  
60 if frame then
61 if Gframe:GetFrameType() ~= "EditBox" then
62 self:error("Cannot register frame %q; it is not an EditBox", frame)
63 frame = nil
64 else
65 if AceEvent and AceEvent:IsFullyInitialized() then
66 if not framesHooked[Gframe] then
67 framesHooked[Gframe] = true
68 local orig = Gframe:GetScript("OnTabPressed")
69 if type(orig) ~= "function" then
70 orig = function() end
71 end
72 Gframe:SetScript("OnTabPressed", function()
73 if self:OnTabPressed(Gframe) then
74 return orig()
75 end
76 end)
77 Gframe.curMatch = 0
78 Gframe.matches = {}
79 Gframe.pMatchLen = 0
80 end
81 else
82 hookedFrames[frame] = true
83 end
84 end
85 end
86 end
87  
88 if not self.registry[descriptor] then
89 self.registry[descriptor] = {}
90 end
91  
92 if not self.registry[descriptor][self] then
93 self.registry[descriptor][self] = {}
94 end
95 self.registry[descriptor][self] = {patterns = regex, wlfunc = wlfunc, usage = usage, frames = editframes}
96  
97  
98 if not AceEvent and AceLibrary:HasInstance("AceEvent-2.0") then
99 external(AceTab, "AceEvent-2.0", AceLibrary("AceEvent-2.0"))
100 end
101 if AceEvent then
102 if not self:IsEventRegistered("AceEvent_FullyInitialized") then
103 self:RegisterEvent("AceEvent_FullyInitialized", "AceEvent_FullyInitialized", true)
104 end
105 end
106 end
107  
108 function AceTab:IsTabCompletionRegistered(descriptor)
109 self:argCheck(descriptor, 2, "string")
110 return self.registry[descriptor] and self.registry[descriptor][self]
111 end
112  
113 function AceTab:UnregisterTabCompletion(descriptor)
114 self:argCheck(descriptor, 2, "string")
115 if self.registry[descriptor] and self.registry[descriptor][self] then
116 self.registry[descriptor][self] = nil
117 else
118 self:error("Cannot unregister a tab completion (%s) that you have not registered.", descriptor)
119 end
120 end
121  
122 local GCS
123 GCS = function(s1, s2)
124 if not s1 and not s2 then return end
125 if not s1 then s1 = s2 end
126 if not s2 then s2 = s1 end
127 local s1len, s2len = string.len(s1), string.len(s2)
128 if s2len < s1len then
129 s1, s2 = s2, s1
130 end
131 if string.find(string.lower(s2), string.lower(s1)) then
132 return s1
133 else
134 return GCS(string.sub(s1, 1, -2), s2)
135 end
136 end
137 local pos
138 local function CycleTab()
139 this.pMatchLen = string.len(this.lMatch)
140 local cMatch = 0
141 local matched = false
142 for desc, mList in pairs(this.matches) do
143 if not matched then
144 for _, m in ipairs(mList) do
145 cMatch = cMatch + 1
146 if cMatch == this.curMatch then
147 this.lMatch = m
148 this.curMatch = this.curMatch + 1
149 matched = true
150 break
151 end
152 end
153 end
154 end
155 if not matched then
156 this.curMatch = 1
157 this.lMatch = this.origWord
158 end
159 this:HighlightText(pos - this.pMatchLen, pos)
160 this:Insert(this.lMatch)
161 end
162  
163 function AceTab:OnTabPressed()
164 local ost = this:GetScript("OnTextSet")
165 if type(ost) ~= "function" then
166 ost = nil
167 end
168 if ost then this:SetScript("OnTextSet", nil) end
169 if this:GetText() == "" then return true end
170 this:Insert("\255")
171 pos = string.find(this:GetText(), "\255", 1) - 1
172 this:HighlightText(pos, pos+1)
173 this:Insert("\0")
174 if ost then this:SetScript("OnTextSet", ost) end
175 local fulltext = this:GetText()
176 local text = string.sub(fulltext, 0, pos) or ""
177  
178 local left = string.find(string.sub(text, 1, pos), "%w+$")
179 left = left and left-1 or pos
180 if not left or left == 1 and string.sub(text, 1, 1) == "/" then return true end
181  
182 local _, _, word = string.find(string.sub(text, left, pos), "(%w+)")
183 word = word or ""
184 this.lMatch = this.curMatch > 0 and (this.lMatch or this.origWord)
185  
186 if this.lMatch and this.lMatch ~= "" and string.find(string.sub(text, 1, pos), this.lMatch.."$") then
187 return CycleTab()
188 else
189 this.matches = {}
190 this.curMatch = 0
191 this.lMatch = nil
192 end
193  
194 local completions = {}
195 local numMatches = 0
196 local firstMatch, hasNonFallback
197  
198 for desc, entry in pairs(AceTab.registry) do
199 for _, s in pairs(entry) do
200 for _, f in pairs(s.frames) do
201 if _G[f] == this then
202 for _, regex in ipairs(s.patterns) do
203 local cands = {}
204 if string.find(string.sub(text, 1, left), regex.."$") then
205 local c = s.wlfunc(cands, fulltext, left)
206 if c ~= false then
207 local mtemp = {}
208 this.matches[desc] = this.matches[desc] or {}
209 for _, cand in ipairs(cands) do
210 if string.find(string.lower(cand), string.lower(word), 1, 1) == 1 then
211 mtemp[cand] = true
212 numMatches = numMatches + 1
213 if numMatches == 1 then firstMatch = cand end
214 end
215 end
216 for i in pairs(mtemp) do
217 table.insert(this.matches[desc], i)
218 end
219 this.matches[desc].usage = s.usage
220 if regex ~= "" and this.matches[desc][1] then
221 hasNonFallback = true
222 this.matches[desc].notFallback = true
223 end
224 end
225 end
226 end
227 end
228 end
229 end
230 end
231  
232 local _, set = next(this.matches)
233 if not set or numMatches == 0 and not hasNonFallback then return true end
234  
235 this:HighlightText(left, left + string.len(word))
236 if numMatches == 1 then
237 this:Insert(firstMatch)
238 this:Insert(" ")
239 else
240 if this.curMatch == 0 then
241 this.curMatch = 1
242 this.origWord = word
243 this.lMatch = word
244 CycleTab()
245 end
246 local gcs
247 for h, c in pairs(this.matches) do
248 if hasNonFallback and not c.notFallback then break end
249 local u = c.usage
250 c.usage = nil
251 local candUsage = u and {}
252 local gcs2
253 if next(c) then
254 if not u then DEFAULT_CHAT_FRAME:AddMessage(h..":") end
255 for _, m in ipairs(c) do
256 if not u then DEFAULT_CHAT_FRAME:AddMessage(m) end
257 gcs2 = GCS(gcs2, m)
258 end
259 end
260 gcs = GCS(gcs, gcs2)
261 if u then
262 if type(u) == "function" then
263 local us = u(candUsage, c, gcs2, string.sub(text, 1, left))
264 if candUsage and next(candUsage) then us = candUsage end
265 if type(us) == "string" then
266 DEFAULT_CHAT_FRAME:AddMessage(us)
267 elseif type(us) == "table" and numMatches > 0 then
268 for _, v in ipairs(c) do
269 if us[v] then DEFAULT_CHAT_FRAME:AddMessage(string.format("%s - %s", v, us[v])) end
270 end
271 end
272 end
273 end
274 end
275 if curMatch == 0 then
276 this:Insert(gcs or word)
277 end
278 end
279 end
280  
281 function AceTab:AceEvent_FullyInitialized()
282 for frame in pairs(hookedFrames) do
283 local Gframe = _G[frame]
284 if not framesHooked[Gframe] then
285 framesHooked[Gframe] = true
286 local orig = Gframe:GetScript("OnTabPressed")
287 if type(orig) ~= "function" then
288 orig = function() end
289 end
290 Gframe:SetScript("OnTabPressed", function()
291 if self:OnTabPressed(Gframe) then
292 return orig()
293 end
294 end)
295 Gframe.curMatch = 0
296 Gframe.matches = {}
297 Gframe.pMatchLen = 0
298 end
299 end
300 end
301  
302 local function external(self, major, instance)
303 if major == "AceEvent-2.0" then
304 if not AceEvent then
305 AceEvent = instance
306  
307 AceEvent:embed(self)
308 end
309 end
310 end
311  
312 local function activate(self, oldLib, oldDeactivate)
313 if oldLib then
314 self.registry = oldLib.registry
315 end
316  
317 if not self.registry then
318 self.registry = {}
319 end
320  
321 if oldDeactivate then
322 oldDeactivate(oldLib)
323 end
324 end
325  
326 AceLibrary:Register(AceTab, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
327 AceTab = AceLibrary(MAJOR_VERSION)