You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
7.5 KiB

--[[
Snippets.lua
@Author : DengSir (tdaddon@163.com)
@Link : https://dengsir.github.io
]]
local ns = select(2, ...)
local Addon = ns.Addon
local Util = ns.Util
local Condition = ns.Condition
local Snippets = {} ns.Snippets = Snippets
do
local function factory(opts)
local words = opts.words or {}
local filter = opts.filter
if opts.extend then
local set = {}
local function add(k)
if set[k] then return end
set[k] = true
tinsert(words, k)
end
for k in pairs(opts.extend) do
add(strsplit('.', k))
add(k)
end
end
sort(words)
local function callback(item)
return tinsert(words, 1, table.remove(words, item.index))
end
local function default(list, word, ...)
if not word then
return
end
local front, tail
local len = #word
for i, v in ipairs(words) do
if v ~= word then
front = v:sub(1, len)
if front == word and (not filter or filter(v, word, ...)) then
tail = v:sub(len + 1)
tinsert(list, {
text = format('|cff00ff00%s|r%s', front, tail),
value = tail,
callback = callback,
index = i,
})
end
end
end
return 1
end
return {
__default = default,
}
end
Snippets.Condition = factory({
extend = Condition.apis,
filter = function(v, word, owner, pet, arg, non, petInputed, argInputed)
if not Condition.apis[v] then
return true
end
local opts = Condition.opts[v]
if not opts.owner ~= not owner and v ~= 'round' then
return false
end
if opts.pet and not pet then
return false
end
if not opts.pet and petInputed then
return false
end
if non and opts.type ~= 'boolean' then
return false
end
if not opts.arg and argInputed then
return false
end
local len = #word
local pos = v:find('.', nil, true)
if opts.arg and not argInputed and pos and len >= pos then
return false
end
if pos and pos > len then
return false
end
return true
end
})
Snippets.Action = factory({
words = { 'if', 'endif' },
extend = ns.Action.apis,
})
Snippets.Target = factory({
words = { 'self', 'enemy', 'ally' }
})
end
function Snippets:Check(line)
local list, column = {}
local condition = line:match('[[&]%s*([^&[]+)$')
if condition then
local owner, pet, word, arg, non, petInputed, argInputed = self:ParseCondition(condition)
word = word or line:match('(%w+)$')
if not word then
return
end
if not owner then
self.Target.__default(list, word)
end
if arg or not self.Condition[word] then
column = self.Condition.__default(list, word, owner, pet, arg, non, petInputed, argInputed)
else
column = self.Condition[word](list, word, owner, pet)
end
else
word = line:match('^%s*(%w+)$')
if not word then
return
end
if not self.Action[word] then
column = self.Action.__default(list, word)
else
column = self.Action[word](list, word)
end
end
if not column or #list == 0 then
return
end
return list, column
end
function Snippets:ParseCondition(condition)
if not condition then
return
end
local non do
local _cond
non, _cond = condition:match('^(!?)%s*(.+)$')
non = non == '!'
if non then
condition = _cond
end
end
local owner, pet, cmd, arg, petInputed, argInputed = Condition:ParseApi(condition)
return owner, pet, cmd, arg, non, petInputed, argInputed
end
local empty = {}
local function tfillrow(t, column)
for i = 1, column - #t % column do
tinsert(t, empty)
end
end
local function makeNameSnippet(name, id)
return {
text = name,
value = format('(%s:%d)', name, id),
}
end
local function makeIndexSnippet(index)
return {
text = format('#%d', index),
value = format('(#%d)', index),
}
end
local function makeIconSnippet(icon)
return {
icon = icon
}
end
local function fillAbility(list, owner, pet)
for i = 1, NUM_BATTLE_PET_ABILITIES do
local id, name, icon = C_PetBattles.GetAbilityInfo(owner, pet, i)
if id then
tinsert(list, makeIconSnippet(icon))
tinsert(list, makeNameSnippet(name, id))
tinsert(list, makeIndexSnippet(i))
end
end
return 3
end
local function fillPet(list, owner)
for i = 1, C_PetBattles.GetNumPets(owner) do
local name = C_PetBattles.GetName(owner, i)
local icon = C_PetBattles.GetIcon(owner, i)
local id = C_PetBattles.GetPetSpeciesID(owner, i)
tinsert(list, makeIconSnippet(icon))
tinsert(list, makeNameSnippet(name, id))
tinsert(list, makeIndexSnippet(i))
end
return 3
end
Snippets.Action.use = function(list)
return fillAbility(list, LE_BATTLE_PET_ALLY, C_PetBattles.GetActivePet(LE_BATTLE_PET_ALLY))
end
Snippets.Action.ability = Snippets.Action.use
local function fillNext(list, column)
tinsert(list, empty)
tinsert(list, {
text = 'next',
value = '(next)',
})
tfillrow(list, column)
return column
end
Snippets.Action.change = function(list)
return fillNext(list, fillPet(list, LE_BATTLE_PET_ALLY))
end
Snippets.Condition.enemy = function(list)
return fillPet(list, LE_BATTLE_PET_ENEMY)
end
Snippets.Condition.ally = function(list)
return fillPet(list, LE_BATTLE_PET_ALLY)
end
Snippets.Condition.self = Snippets.Condition.ally
Snippets.Condition.weather = function(list)
local weathers = { 596, 590, 229, 403, 171, 205, 718, 257, 454 }
-- 596 月光
-- 590 奥术之风
-- 229 净化之雨
-- 403 晴天
-- 171 灼燃大地
-- 205 暴风雪
-- 718 泥石流
-- 257 黑暗
-- 454 沙尘暴
for i, id in ipairs(weathers) do
local id, name, icon = C_PetBattles.GetAbilityInfoByID(id)
tinsert(list, makeIconSnippet(icon))
tinsert(list, makeNameSnippet(name, id))
end
return 2
end
Snippets.Condition.aura = function(list, word, owner, pet)
if not owner or not pet then
return
end
for _, pet in ipairs({pet, PET_BATTLE_PAD_INDEX}) do
for i = 1, C_PetBattles.GetNumAuras(owner, pet) do
local id, name, icon = C_PetBattles.GetAbilityInfoByID(C_PetBattles.GetAuraInfo(owner, pet, i))
tinsert(list, makeIconSnippet(icon))
tinsert(list, makeNameSnippet(name, id))
end
end
return 2
end
Snippets.Condition.ability = function(list, word, owner, pet)
return fillAbility(list, owner, pet)
end
Snippets.Condition.is = function(list, word, owner, pet)
return fillPet(list, owner)
end