flickerstreak@30: --[[
flickerstreak@30: Name: LibRock-1.0
flickerstreak@30: Revision: $Rev: 63317 $
flickerstreak@30: Developed by: ckknight (ckknight@gmail.com)
flickerstreak@30: Website: http://www.wowace.com/
flickerstreak@30: Description: Library to allow for library and addon creation and easy table recycling functions.
flickerstreak@30: License: LGPL v2.1
flickerstreak@30: ]]
flickerstreak@30:
flickerstreak@30: local MAJOR_VERSION = "LibRock-1.0"
flickerstreak@30: local MINOR_VERSION = tonumber(("$Revision: 63317 $"):match("(%d+)")) - 60000
flickerstreak@30:
flickerstreak@30: local _G = _G
flickerstreak@30: local GetLocale = _G.GetLocale
flickerstreak@30: local CATEGORIES
flickerstreak@30: if GetLocale() == "deDE" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "Aktionsleisten",
flickerstreak@30: ["Auction"] = "Auktion",
flickerstreak@30: ["Audio"] = "Audio",
flickerstreak@30: ["Battlegrounds/PvP"] = "Schlachtfeld/PvP",
flickerstreak@30: ["Buffs"] = "Stärkungszauber",
flickerstreak@30: ["Chat/Communication"] = "Chat/Kommunikation",
flickerstreak@30: ["Druid"] = "Druide",
flickerstreak@30: ["Hunter"] = "Jäger",
flickerstreak@30: ["Mage"] = "Magier",
flickerstreak@30: ["Paladin"] = "Paladin",
flickerstreak@30: ["Priest"] = "Priester",
flickerstreak@30: ["Rogue"] = "Schurke",
flickerstreak@30: ["Shaman"] = "Schamane",
flickerstreak@30: ["Warlock"] = "Hexenmeister",
flickerstreak@30: ["Warrior"] = "Krieger",
flickerstreak@30: ["Healer"] = "Heiler",
flickerstreak@30: ["Tank"] = "Tank",
flickerstreak@30: ["Caster"] = "Zauberer",
flickerstreak@30: ["Combat"] = "Kampf",
flickerstreak@30: ["Compilations"] = "Zusammenstellungen",
flickerstreak@30: ["Data Export"] = "Datenexport",
flickerstreak@30: ["Development Tools"] = "Entwicklungstools",
flickerstreak@30: ["Guild"] = "Gilde",
flickerstreak@30: ["Frame Modification"] = "Frameveränderungen",
flickerstreak@30: ["Interface Enhancements"] = "Interfaceverbesserungen",
flickerstreak@30: ["Inventory"] = "Inventar",
flickerstreak@30: ["Library"] = "Bibliotheken",
flickerstreak@30: ["Map"] = "Karte",
flickerstreak@30: ["Mail"] = "Post",
flickerstreak@30: ["Miscellaneous"] = "Diverses",
flickerstreak@30: ["Quest"] = "Quest",
flickerstreak@30: ["Raid"] = "Schlachtzug",
flickerstreak@30: ["Tradeskill"] = "Beruf",
flickerstreak@30: ["UnitFrame"] = "Einheiten-Fenster",
flickerstreak@30: }
flickerstreak@30: elseif GetLocale() == "frFR" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "Barres d'action",
flickerstreak@30: ["Auction"] = "Hôtel des ventes",
flickerstreak@30: ["Audio"] = "Audio",
flickerstreak@30: ["Battlegrounds/PvP"] = "Champs de bataille/JcJ",
flickerstreak@30: ["Buffs"] = "Buffs",
flickerstreak@30: ["Chat/Communication"] = "Chat/Communication",
flickerstreak@30: ["Druid"] = "Druide",
flickerstreak@30: ["Hunter"] = "Chasseur",
flickerstreak@30: ["Mage"] = "Mage",
flickerstreak@30: ["Paladin"] = "Paladin",
flickerstreak@30: ["Priest"] = "Prêtre",
flickerstreak@30: ["Rogue"] = "Voleur",
flickerstreak@30: ["Shaman"] = "Chaman",
flickerstreak@30: ["Warlock"] = "Démoniste",
flickerstreak@30: ["Warrior"] = "Guerrier",
flickerstreak@30: ["Healer"] = "Soigneur",
flickerstreak@30: ["Tank"] = "Tank",
flickerstreak@30: ["Caster"] = "Casteur",
flickerstreak@30: ["Combat"] = "Combat",
flickerstreak@30: ["Compilations"] = "Compilations",
flickerstreak@30: ["Data Export"] = "Exportation de données",
flickerstreak@30: ["Development Tools"] = "Outils de développement",
flickerstreak@30: ["Guild"] = "Guilde",
flickerstreak@30: ["Frame Modification"] = "Modification des fenêtres",
flickerstreak@30: ["Interface Enhancements"] = "Améliorations de l'interface",
flickerstreak@30: ["Inventory"] = "Inventaire",
flickerstreak@30: ["Library"] = "Bibliothèques",
flickerstreak@30: ["Map"] = "Carte",
flickerstreak@30: ["Mail"] = "Courrier",
flickerstreak@30: ["Miscellaneous"] = "Divers",
flickerstreak@30: ["Quest"] = "Quêtes",
flickerstreak@30: ["Raid"] = "Raid",
flickerstreak@30: ["Tradeskill"] = "Métiers",
flickerstreak@30: ["UnitFrame"] = "Fenêtres d'unité",
flickerstreak@30: }
flickerstreak@30: elseif GetLocale() == "koKR" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "액션바",
flickerstreak@30: ["Auction"] = "경매",
flickerstreak@30: ["Audio"] = "음향",
flickerstreak@30: ["Battlegrounds/PvP"] = "전장/PvP",
flickerstreak@30: ["Buffs"] = "버프",
flickerstreak@30: ["Chat/Communication"] = "대화/의사소통",
flickerstreak@30: ["Druid"] = "드루이드",
flickerstreak@30: ["Hunter"] = "사냥꾼",
flickerstreak@30: ["Mage"] = "마법사",
flickerstreak@30: ["Paladin"] = "성기사",
flickerstreak@30: ["Priest"] = "사제",
flickerstreak@30: ["Rogue"] = "도적",
flickerstreak@30: ["Shaman"] = "주술사",
flickerstreak@30: ["Warlock"] = "흑마법사",
flickerstreak@30: ["Warrior"] = "전사",
flickerstreak@30: ["Healer"] = "힐러",
flickerstreak@30: ["Tank"] = "탱커",
flickerstreak@30: ["Caster"] = "캐스터",
flickerstreak@30: ["Combat"] = "전투",
flickerstreak@30: ["Compilations"] = "복합",
flickerstreak@30: ["Data Export"] = "자료 출력",
flickerstreak@30: ["Development Tools"] = "개발 도구",
flickerstreak@30: ["Guild"] = "길드",
flickerstreak@30: ["Frame Modification"] = "구조 변경",
flickerstreak@30: ["Interface Enhancements"] = "인터페이스 강화",
flickerstreak@30: ["Inventory"] = "인벤토리",
flickerstreak@30: ["Library"] = "라이브러리",
flickerstreak@30: ["Map"] = "지도",
flickerstreak@30: ["Mail"] = "우편",
flickerstreak@30: ["Miscellaneous"] = "기타",
flickerstreak@30: ["Quest"] = "퀘스트",
flickerstreak@30: ["Raid"] = "공격대",
flickerstreak@30: ["Tradeskill"] = "전문기술",
flickerstreak@30: ["UnitFrame"] = "유닛 프레임",
flickerstreak@30: }
flickerstreak@30: elseif GetLocale() == "zhTW" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "動作列",
flickerstreak@30: ["Auction"] = "拍賣",
flickerstreak@30: ["Audio"] = "音效",
flickerstreak@30: ["Battlegrounds/PvP"] = "戰場/PvP",
flickerstreak@30: ["Buffs"] = "增益",
flickerstreak@30: ["Chat/Communication"] = "聊天/通訊",
flickerstreak@30: ["Druid"] = "德魯伊",
flickerstreak@30: ["Hunter"] = "獵人",
flickerstreak@30: ["Mage"] = "法師",
flickerstreak@30: ["Paladin"] = "聖騎士",
flickerstreak@30: ["Priest"] = "牧師",
flickerstreak@30: ["Rogue"] = "盜賊",
flickerstreak@30: ["Shaman"] = "薩滿",
flickerstreak@30: ["Warlock"] = "術士",
flickerstreak@30: ["Warrior"] = "戰士",
flickerstreak@30: ["Healer"] = "治療者",
flickerstreak@30: ["Tank"] = "坦克",
flickerstreak@30: ["Caster"] = "施法者",
flickerstreak@30: ["Combat"] = "戰鬥",
flickerstreak@30: ["Compilations"] = "整合",
flickerstreak@30: ["Data Export"] = "資料匯出",
flickerstreak@30: ["Development Tools"] = "開發工具",
flickerstreak@30: ["Guild"] = "公會",
flickerstreak@30: ["Frame Modification"] = "框架修改",
flickerstreak@30: ["Interface Enhancements"] = "介面增強",
flickerstreak@30: ["Inventory"] = "庫存",
flickerstreak@30: ["Library"] = "程式庫",
flickerstreak@30: ["Map"] = "地圖",
flickerstreak@30: ["Mail"] = "郵件",
flickerstreak@30: ["Miscellaneous"] = "雜項",
flickerstreak@30: ["Quest"] = "任務",
flickerstreak@30: ["Raid"] = "團隊",
flickerstreak@30: ["Tradeskill"] = "交易技能",
flickerstreak@30: ["UnitFrame"] = "頭像框架",
flickerstreak@30: }
flickerstreak@30: elseif GetLocale() == "zhCN" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "动作条",
flickerstreak@30: ["Auction"] = "拍卖",
flickerstreak@30: ["Audio"] = "音频",
flickerstreak@30: ["Battlegrounds/PvP"] = "战场/PvP",
flickerstreak@30: ["Buffs"] = "增益魔法",
flickerstreak@30: ["Chat/Communication"] = "聊天/交流",
flickerstreak@30: ["Druid"] = "德鲁伊",
flickerstreak@30: ["Hunter"] = "猎人",
flickerstreak@30: ["Mage"] = "法师",
flickerstreak@30: ["Paladin"] = "圣骑士",
flickerstreak@30: ["Priest"] = "牧师",
flickerstreak@30: ["Rogue"] = "潜行者",
flickerstreak@30: ["Shaman"] = "萨满祭司",
flickerstreak@30: ["Warlock"] = "术士",
flickerstreak@30: ["Warrior"] = "战士",
flickerstreak@30: ["Healer"] = "治疗",
flickerstreak@30: ["Tank"] = "坦克",
flickerstreak@30: ["Caster"] = "远程输出",
flickerstreak@30: ["Combat"] = "战斗",
flickerstreak@30: ["Compilations"] = "编译",
flickerstreak@30: ["Data Export"] = "数据导出",
flickerstreak@30: ["Development Tools"] = "开发工具",
flickerstreak@30: ["Guild"] = "公会",
flickerstreak@30: ["Frame Modification"] = "框架修改",
flickerstreak@30: ["Interface Enhancements"] = "界面增强",
flickerstreak@30: ["Inventory"] = "背包",
flickerstreak@30: ["Library"] = "库",
flickerstreak@30: ["Map"] = "地图",
flickerstreak@30: ["Mail"] = "邮件",
flickerstreak@30: ["Miscellaneous"] = "杂项",
flickerstreak@30: ["Quest"] = "任务",
flickerstreak@30: ["Raid"] = "团队",
flickerstreak@30: ["Tradeskill"] = "商业技能",
flickerstreak@30: ["UnitFrame"] = "头像框架",
flickerstreak@30: }
flickerstreak@30: elseif GetLocale() == "esES" then
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "Barras de Acción",
flickerstreak@30: ["Auction"] = "Subasta",
flickerstreak@30: ["Audio"] = "Audio",
flickerstreak@30: ["Battlegrounds/PvP"] = "Campos de Batalla/JcJ",
flickerstreak@30: ["Buffs"] = "Buffs",
flickerstreak@30: ["Chat/Communication"] = "Chat/Comunicación",
flickerstreak@30: ["Druid"] = "Druida",
flickerstreak@30: ["Hunter"] = "Cazador",
flickerstreak@30: ["Mage"] = "Mago",
flickerstreak@30: ["Paladin"] = "Paladín",
flickerstreak@30: ["Priest"] = "Sacerdote",
flickerstreak@30: ["Rogue"] = "Pícaro",
flickerstreak@30: ["Shaman"] = "Chamán",
flickerstreak@30: ["Warlock"] = "Brujo",
flickerstreak@30: ["Warrior"] = "Guerrero",
flickerstreak@30: ["Healer"] = "Sanador",
flickerstreak@30: ["Tank"] = "Tanque",
flickerstreak@30: ["Caster"] = "Conjurador",
flickerstreak@30: ["Combat"] = "Combate",
flickerstreak@30: ["Compilations"] = "Compilaciones",
flickerstreak@30: ["Data Export"] = "Exportar Datos",
flickerstreak@30: ["Development Tools"] = "Herramientas de Desarrollo",
flickerstreak@30: ["Guild"] = "Hermandad",
flickerstreak@30: ["Frame Modification"] = "Modificación de Marcos",
flickerstreak@30: ["Interface Enhancements"] = "Mejoras de la Interfaz",
flickerstreak@30: ["Inventory"] = "Inventario",
flickerstreak@30: ["Library"] = "Biblioteca",
flickerstreak@30: ["Map"] = "Mapa",
flickerstreak@30: ["Mail"] = "Correo",
flickerstreak@30: ["Miscellaneous"] = "Misceláneo",
flickerstreak@30: ["Quest"] = "Misión",
flickerstreak@30: ["Raid"] = "Banda",
flickerstreak@30: ["Tradeskill"] = "Habilidad de Comercio",
flickerstreak@30: ["UnitFrame"] = "Marco de Unidades",
flickerstreak@30: }
flickerstreak@30: else -- enUS
flickerstreak@30: CATEGORIES = {
flickerstreak@30: ["Action Bars"] = "Action Bars",
flickerstreak@30: ["Auction"] = "Auction",
flickerstreak@30: ["Audio"] = "Audio",
flickerstreak@30: ["Battlegrounds/PvP"] = "Battlegrounds/PvP",
flickerstreak@30: ["Buffs"] = "Buffs",
flickerstreak@30: ["Chat/Communication"] = "Chat/Communication",
flickerstreak@30: ["Druid"] = "Druid",
flickerstreak@30: ["Hunter"] = "Hunter",
flickerstreak@30: ["Mage"] = "Mage",
flickerstreak@30: ["Paladin"] = "Paladin",
flickerstreak@30: ["Priest"] = "Priest",
flickerstreak@30: ["Rogue"] = "Rogue",
flickerstreak@30: ["Shaman"] = "Shaman",
flickerstreak@30: ["Warlock"] = "Warlock",
flickerstreak@30: ["Warrior"] = "Warrior",
flickerstreak@30: ["Healer"] = "Healer",
flickerstreak@30: ["Tank"] = "Tank",
flickerstreak@30: ["Caster"] = "Caster",
flickerstreak@30: ["Combat"] = "Combat",
flickerstreak@30: ["Compilations"] = "Compilations",
flickerstreak@30: ["Data Export"] = "Data Export",
flickerstreak@30: ["Development Tools"] = "Development Tools",
flickerstreak@30: ["Guild"] = "Guild",
flickerstreak@30: ["Frame Modification"] = "Frame Modification",
flickerstreak@30: ["Interface Enhancements"] = "Interface Enhancements",
flickerstreak@30: ["Inventory"] = "Inventory",
flickerstreak@30: ["Library"] = "Library",
flickerstreak@30: ["Map"] = "Map",
flickerstreak@30: ["Mail"] = "Mail",
flickerstreak@30: ["Miscellaneous"] = "Miscellaneous",
flickerstreak@30: ["Quest"] = "Quest",
flickerstreak@30: ["Raid"] = "Raid",
flickerstreak@30: ["Tradeskill"] = "Tradeskill",
flickerstreak@30: ["UnitFrame"] = "UnitFrame",
flickerstreak@30: }
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local select = _G.select
flickerstreak@30: local tostring = _G.tostring
flickerstreak@30: local pairs = _G.pairs
flickerstreak@30: local ipairs = _G.ipairs
flickerstreak@30: local error = _G.error
flickerstreak@30: local setmetatable = _G.setmetatable
flickerstreak@30: local getmetatable = _G.getmetatable
flickerstreak@30: local type = _G.type
flickerstreak@30: local pcall = _G.pcall
flickerstreak@30: local next = _G.next
flickerstreak@30: local tonumber = _G.tonumber
flickerstreak@30: local strmatch = _G.strmatch
flickerstreak@30: local table_remove = _G.table.remove
flickerstreak@30: local debugstack = _G.debugstack
flickerstreak@30: local LoadAddOn = _G.LoadAddOn
flickerstreak@30: local GetAddOnInfo = _G.GetAddOnInfo
flickerstreak@30: local GetAddOnMetadata = _G.GetAddOnMetadata
flickerstreak@30: local GetNumAddOns = _G.GetNumAddOns
flickerstreak@30: local DisableAddOn = _G.DisableAddOn
flickerstreak@30: local EnableAddOn = _G.EnableAddOn
flickerstreak@30: local IsAddOnLoadOnDemand = _G.IsAddOnLoadOnDemand
flickerstreak@30: local IsLoggedIn = _G.IsLoggedIn
flickerstreak@30: local geterrorhandler = _G.geterrorhandler
flickerstreak@30: local assert = _G.assert
flickerstreak@30: local collectgarbage = _G.collectgarbage
flickerstreak@30: local table_sort = _G.table.sort
flickerstreak@30: local table_concat = _G.table.concat
flickerstreak@30:
flickerstreak@30: -- #AUTODOC_NAMESPACE Rock
flickerstreak@30:
flickerstreak@30:
flickerstreak@30: local LibStub = _G.LibStub
flickerstreak@30:
flickerstreak@30: local Rock = LibStub:GetLibrary(MAJOR_VERSION, true) or _G.Rock
flickerstreak@30: local oldRock
flickerstreak@30: if not Rock then
flickerstreak@30: Rock = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
flickerstreak@30: if not Rock then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: Rock.name = MAJOR_VERSION
flickerstreak@30: else
flickerstreak@30: Rock, oldRock = Rock:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
flickerstreak@30: if not Rock then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: _G.Rock = Rock
flickerstreak@30:
flickerstreak@30: local L = setmetatable({}, {__index=function(self,key) self[key] = key; return key end})
flickerstreak@30: if GetLocale() == "zhCN" then
flickerstreak@30: L["Advanced options"] = "高级选项"
flickerstreak@30: L["Advanced options for developers and power users."] = "开发者与高级用户的高级选项"
flickerstreak@30: L["Unit tests"] = "框体测试"
flickerstreak@30: L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "开启框体测试,仅供开发者使用。\n\n需要重载用户界面。"
flickerstreak@30: L["Contracts"] = "侦错协定"
flickerstreak@30: L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "启用侦错协定,这是给插件作者用来通报错误所使用。"
flickerstreak@30: L["Reload UI"] = "重载UI"
flickerstreak@30: L["Reload the User Interface for some changes to take effect."] = "部分功能更改需要重载用户界面才会生效。"
flickerstreak@30: L["Reload"] = "重载"
flickerstreak@30: L["Give donation"] = "捐赠"
flickerstreak@30: L["Donate"] = "捐赠"
flickerstreak@30: L["Give a much-needed donation to the author of this addon."] = "给插件作者捐赠支持插件开发。"
flickerstreak@30: L["File issue"] = "通报错误"
flickerstreak@30: L["Report"] = "报告"
flickerstreak@30: L["File a bug or request a new feature or an improvement to this addon."] = "发送错误报告或请求新功能及要改进的部分。"
flickerstreak@30: L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C复制网址,Alt-Tab切换到桌面,打开浏览器,在地址栏贴上网址。"
flickerstreak@30: L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C复制网址,Cmd-Tab切换到电脑桌面,打开浏览器,在地址栏贴上网址。"
flickerstreak@30: L["Enabled"] = "开启"
flickerstreak@30: L["Enable or disable this addon."] = "启用这个插件。"
flickerstreak@30:
flickerstreak@30: elseif GetLocale() == "zhTW" then
flickerstreak@30: L["Advanced options"] = "進階選項"
flickerstreak@30: L["Advanced options for developers and power users."] = "插件作者、進階用戶選項"
flickerstreak@30: L["Unit tests"] = "單元測試"
flickerstreak@30: L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "啟用單元測試,這是給插件作者使用的功能。\n\n需要重載介面才能使用。"
flickerstreak@30: L["Contracts"] = "偵錯協定"
flickerstreak@30: L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "啟用偵錯協定,這是給插件作者用來通報錯誤所使用。"
flickerstreak@30: L["Reload UI"] = "重載介面"
flickerstreak@30: L["Reload the User Interface for some changes to take effect."] = "重新載入使用者介面,部分功能才會生效。"
flickerstreak@30: L["Reload"] = "重載"
flickerstreak@30: L["Give donation"] = "捐贈"
flickerstreak@30: L["Donate"] = "捐贈"
flickerstreak@30: L["Give a much-needed donation to the author of this addon."] = "捐贈金錢給插件作者。"
flickerstreak@30: L["File issue"] = "通報錯誤"
flickerstreak@30: L["Report"] = "報告"
flickerstreak@30: L["File a bug or request a new feature or an improvement to this addon."] = "發出錯誤報告或請求新功能及要改進的部分。"
flickerstreak@30: L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C複製網址,Alt-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
flickerstreak@30: L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C複製網址,Cmd-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
flickerstreak@30: L["Enabled"] = "啟用"
flickerstreak@30: L["Enable or disable this addon."] = "啟用這個插件。"
flickerstreak@30: elseif GetLocale() == "koKR" then
flickerstreak@30: L["Advanced options"] = "상세 옵션"
flickerstreak@30: L["Advanced options for developers and power users."] = "개발자와 파워 사용자를 위한 상세 옵션입니다."
flickerstreak@30: L["Unit tests"] = "유닛 테스트"
flickerstreak@30: L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "유닛 테스트를 사용합니다. 이것은 개발자만을 위한 옵션입니다.\n\n변경된 결과를 적용하기 위해 당신의 UI를 재실행 합니다."
flickerstreak@30: L["Contracts"] = "계약"
flickerstreak@30: L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "계약을 사용합니다. 이것은 개발자와 버그 파일을 알릴 분이면 누구나 사용 가능합니다. 계약이 가능하지 않으면 버그 파일을 보내지 마십시오. 이것은 당신의 애드온 속도를 약간 떨어뜨립니다."
flickerstreak@30: L["Reload UI"] = "UI 재실행"
flickerstreak@30: L["Reload the User Interface for some changes to take effect."] = "변경된 결과를 적용하기 위해 사용자 인터페이스를 재실행합니다."
flickerstreak@30: L["Reload"] = "재실행"
flickerstreak@30: L["Give donation"] = "기부"
flickerstreak@30: L["Donate"] = "기부"
flickerstreak@30: L["Give a much-needed donation to the author of this addon."] = "이 애드온의 제작자에게 필요한 기부를 합니다."
flickerstreak@30: L["File issue"] = "파일 이슈"
flickerstreak@30: L["Report"] = "보고"
flickerstreak@30: L["File a bug or request a new feature or an improvement to this addon."] = "버그 파일을 알리거나 새로운 기능 또는 이 애드온에 대한 개선을 부탁합니다."
flickerstreak@30: L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C로 복사합니다. Alt-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
flickerstreak@30: L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C로 복사합니다. Cmd-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
flickerstreak@30: L["Enabled"] = "사용"
flickerstreak@30: L["Enable or disable this addon."] = "이 애드온을 사용하거나 사용하지 않습니다."
flickerstreak@30: elseif GetLocale() == "frFR" then
flickerstreak@30: L["Advanced options"] = "Options avancées"
flickerstreak@30: L["Advanced options for developers and power users."] = "Options avancées à l'attention des développeurs et des utilisateurs expérimentés."
flickerstreak@30: L["Reload UI"] = "Recharger IU"
flickerstreak@30: L["Reload the User Interface for some changes to take effect."] = "Recharge l'interface utilisateur afin que certains changements prennent effet."
flickerstreak@30: L["Reload"] = "Recharger"
flickerstreak@30: L["Give donation"] = "Faire un don"
flickerstreak@30: L["Donate"] = "Don"
flickerstreak@30: L["Give a much-needed donation to the author of this addon."] = "Permet de faire un don bien mérité à l'auteur de cet addon."
flickerstreak@30: L["File issue"] = "Problème"
flickerstreak@30: L["Report"] = "Signaler"
flickerstreak@30: L["File a bug or request a new feature or an improvement to this addon."] = "Permet de signaler un bogue ou de demander une amélioration à cet addon."
flickerstreak@30: L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse."
flickerstreak@30: L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse."
flickerstreak@30: L["Enabled"] = "Activé"
flickerstreak@30: L["Enable or disable this addon."] = "Active ou désactive cet addon."
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local isStandalone = debugstack():match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\") == MAJOR_VERSION or nil
flickerstreak@30: local unitTestDB, enableContracts
flickerstreak@30:
flickerstreak@30: local weakKey = { __mode = 'k' }
flickerstreak@30:
flickerstreak@30: -- frame to manage events from
flickerstreak@30: Rock.frame = oldRock and oldRock.frame or _G.CreateFrame("Frame")
flickerstreak@30: local frame = Rock.frame
flickerstreak@30: -- dict of libraries in { ["major"] = object } form
flickerstreak@30: Rock.libraries = oldRock and oldRock.libraries or { [MAJOR_VERSION] = Rock }
flickerstreak@30: local libraries = Rock.libraries
flickerstreak@30: -- set of libraries which have gone through the finalization process in { [object] = true } form
flickerstreak@30: Rock.finalizedLibraries = setmetatable(oldRock and oldRock.finalizedLibraries or { }, weakKey)
flickerstreak@30: local finalizedLibraries = Rock.finalizedLibraries
flickerstreak@30: -- set of libraries which have been tried to be loaded.
flickerstreak@30: Rock.scannedLibraries = oldRock and oldRock.scannedLibraries or {}
flickerstreak@30: local scannedLibraries = Rock.scannedLibraries
flickerstreak@30: -- exportedMethods[library] = { "method1", "method2" }
flickerstreak@30: Rock.exportedMethods = setmetatable(oldRock and oldRock.exportedMethods or {}, weakKey)
flickerstreak@30: local exportedMethods = Rock.exportedMethods
flickerstreak@30: -- mixinToObject[mixin][object] = true
flickerstreak@30: Rock.mixinToObject = setmetatable(oldRock and oldRock.mixinToObject or {}, weakKey)
flickerstreak@30: local mixinToObject = Rock.mixinToObject
flickerstreak@30: -- dict of addons in { ["name"] = object } form
flickerstreak@30: Rock.addons = oldRock and oldRock.addons or {}
flickerstreak@30: local addons = Rock.addons
flickerstreak@30: -- set of libraries that should be finalized before ADDON_LOADED.
flickerstreak@30: Rock.pendingLibraries = setmetatable(oldRock and oldRock.pendingLibraries or { }, weakKey)
flickerstreak@30: local pendingLibraries = Rock.pendingLibraries
flickerstreak@30: -- list of addons in order of created that need to be initialized by ADDON_LOADED.
flickerstreak@30: Rock.pendingAddons = oldRock and oldRock.pendingAddons or {}
flickerstreak@30: local pendingAddons = Rock.pendingAddons
flickerstreak@30: -- dictionary of addons to their folder names
flickerstreak@30: Rock.addonToFolder = oldRock and oldRock.addonToFolder or {}
flickerstreak@30: local addonToFolder = Rock.addonToFolder
flickerstreak@30: -- set of folders which have been loaded
flickerstreak@30: Rock.foldersLoaded = oldRock and oldRock.foldersLoaded or {}
flickerstreak@30: local foldersLoaded = Rock.foldersLoaded
flickerstreak@30: -- list of addons in order of created that need to be enabled by PLAYER_LOGIN.
flickerstreak@30: Rock.pendingAddonsEnable = oldRock and oldRock.pendingAddonsEnable or {}
flickerstreak@30: local pendingAddonsEnable = Rock.pendingAddonsEnable
flickerstreak@30: -- set of addons which have been enabled at least once.
flickerstreak@30: Rock.addonsAlreadyEnabled = oldRock and oldRock.addonsAlreadyEnabled or {}
flickerstreak@30: local addonsAlreadyEnabled = Rock.addonsAlreadyEnabled
flickerstreak@30: -- set of addons which have no database and are set to be inactive.
flickerstreak@30: Rock.inactiveAddons = oldRock and oldRock.inactiveAddons or {}
flickerstreak@30: local inactiveAddons = Rock.inactiveAddons
flickerstreak@30: -- set of addons which are currently enabled (not necessarily should be)
flickerstreak@30: Rock.currentlyEnabledAddons = oldRock and oldRock.currentlyEnabledAddons or {}
flickerstreak@30: local currentlyEnabledAddons = Rock.currentlyEnabledAddons
flickerstreak@30: -- dictionary of namespace to list of functions which will be run.
flickerstreak@30: Rock.unitTests = oldRock and oldRock.unitTests or {}
flickerstreak@30: local unitTests = Rock.unitTests
flickerstreak@30: -- metatable for addons
flickerstreak@30: Rock.addon_mt = oldRock and oldRock.addon_mt or {}
flickerstreak@30: local addon_mt = Rock.addon_mt
flickerstreak@30: for k in pairs(addon_mt) do
flickerstreak@30: addon_mt[k] = nil
flickerstreak@30: end
flickerstreak@30: function addon_mt:__tostring()
flickerstreak@30: return tostring(self.name)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function better_tostring(self)
flickerstreak@30: if type(self) == "table" and self.name then
flickerstreak@30: return tostring(self.name)
flickerstreak@30: end
flickerstreak@30: return tostring(self)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function figureCurrentAddon(pos)
flickerstreak@30: local stack = debugstack(pos+1, 1, 0)
flickerstreak@30: local folder = stack:match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\")
flickerstreak@30: if folder then
flickerstreak@30: return folder
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local partFolder = stack:match("...([^\\]+)\\")
flickerstreak@30: if partFolder then
flickerstreak@30: local partFolder_len = #partFolder
flickerstreak@30: for i = 1, GetNumAddOns() do
flickerstreak@30: local name = GetAddOnInfo(i)
flickerstreak@30: if #name >= partFolder_len then
flickerstreak@30: local partName = name:sub(-partFolder_len)
flickerstreak@30: if partName == partFolder then
flickerstreak@30: return name
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return nil
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Returns:
flickerstreak@30: string - the localized name of the given category.
flickerstreak@30: Arguments:
flickerstreak@30: string - the English name of the category.
flickerstreak@30: Example:
flickerstreak@30: local uf = Rock:GetLocalizedCategory("UnitFrame")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetLocalizedCategory(name)
flickerstreak@30: if type(name) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `GetLocalizedCategory'. Expected %q, got %q."):format("string", type(name)), 2)
flickerstreak@30: end
flickerstreak@30: local cat = CATEGORIES[name]
flickerstreak@30: if cat then
flickerstreak@30: return cat
flickerstreak@30: end
flickerstreak@30: local name_lower = name:lower()
flickerstreak@30: for k in pairs(CATEGORIES) do
flickerstreak@30: if k:lower() == name_lower then
flickerstreak@30: return k
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return _G.UNKNOWN or "Unknown"
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local weak = {__mode = 'kv'}
flickerstreak@30:
flickerstreak@30: Rock.recycleData = oldRock and oldRock.recycleData or {}
flickerstreak@30: local recycleData = Rock.recycleData
flickerstreak@30: if recycleData.pools then
flickerstreak@30: setmetatable(recycleData.pools, weak)
flickerstreak@30: end
flickerstreak@30: if recycleData.debugPools then
flickerstreak@30: setmetatable(recycleData.debugPools, weak)
flickerstreak@30: end
flickerstreak@30: if recycleData.newList then
flickerstreak@30: setmetatable(recycleData.newList, weak)
flickerstreak@30: end
flickerstreak@30: if recycleData.newDict then
flickerstreak@30: setmetatable(recycleData.newDict, weak)
flickerstreak@30: end
flickerstreak@30: if recycleData.newSet then
flickerstreak@30: setmetatable(recycleData.newSet, weak)
flickerstreak@30: end
flickerstreak@30: if recycleData.del then
flickerstreak@30: setmetatable(recycleData.del, weak)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local tmp = {}
flickerstreak@30: local function myUnpack(t, start)
flickerstreak@30: if not start then
flickerstreak@30: start = 1
flickerstreak@30: end
flickerstreak@30: local value = t[start]
flickerstreak@30: if value == nil then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: t[start] = nil
flickerstreak@30: return value, myUnpack(t, start+1)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * Returns functions for the specified namespace based on what is provided.
flickerstreak@30: * function types:
flickerstreak@30: ; "newList" : to create a list
flickerstreak@30: ; "newDict" : to create a dictionary
flickerstreak@30: ; "newSet" : to create a set
flickerstreak@30: ; "del" : to delete a table
flickerstreak@30: ; "unpackListAndDel" : deletes a table and returns what its contents were as a list, in order.
flickerstreak@30: ; "unpackSetAndDel" : deletes a table and returns what its contents were as a set, in no particular order.
flickerstreak@30: ; "unpackDictAndDel" : deletes a table and returns what its contents were as a dictionary, in no particular order.
flickerstreak@30: * If you provide "Debug" as the last argument, then the namespace can be debugged with ''':DebugRecycle'''
flickerstreak@30: * It is '''not recommended''' to use table recycling with tables that have more than 128 keys, as it is typically faster to let lua's garbage collector handle it.
flickerstreak@30: Arguments:
flickerstreak@30: string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30: Example:
flickerstreak@30: local newList, newDict, newSet, del, unpackListAndDel, unpackSetAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions("MyNamespace", "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel")
flickerstreak@30:
flickerstreak@30: local t = newList('alpha', 'bravo') -- same as t = {'alpha', 'bravo'}
flickerstreak@30: local u = newDict('alpha', 'bravo') -- same as t = {['alpha'] = 'bravo'}
flickerstreak@30: local v = newSet('alpha', 'bravo') -- same as t = {['alpha'] = true, ['bravo'] = true}
flickerstreak@30: t = del(t) -- you want to clear your reference as well as deleting.
flickerstreak@30: u = del(u)
flickerstreak@30: v = del(v)
flickerstreak@30:
flickerstreak@30: -- for debugging
flickerstreak@30: local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug")
flickerstreak@30: local t = newList()
flickerstreak@30: Rock:DebugRecycle("MyNamespace")
flickerstreak@30: t = del(t)
flickerstreak@30:
flickerstreak@30: -- unpacking functions
flickerstreak@30: unpackListAndDel(newList(...)) => ...
flickerstreak@30: unpackSetAndDel(newSet(...)) => ...
flickerstreak@30: unpackDictAndDel(newDict(...)) => ...
flickerstreak@30: newList(unpackListAndDel(t)) => t
flickerstreak@30: newSet(unpackSetAndDel(t)) => t
flickerstreak@30: newDict(unpackDictAndDel(t)) => t
flickerstreak@30: -- as you can see, they are inverses of each other.
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetRecyclingFunctions(namespace, ...)
flickerstreak@30: local pools = recycleData.pools
flickerstreak@30: if not pools then
flickerstreak@30: pools = setmetatable({}, weak)
flickerstreak@30: recycleData.pools = pools
flickerstreak@30: end
flickerstreak@30: if namespace == "newList" or namespace == "newSet" or namespace == "newDict" or namespace == "del" or namespace == "unpackListAndDel" or namespace == "unpackSetAndDel" or namespace == "unpackDictAndDel" then
flickerstreak@30: error(("Bad argument #2 to `GetRecyclingFunctions'. Cannot be %q"):format(namespace), 2)
flickerstreak@30: end
flickerstreak@30: local pool = pools[namespace]
flickerstreak@30: if not pool then
flickerstreak@30: pool = setmetatable({}, weak)
flickerstreak@30: pools[namespace] = pool
flickerstreak@30: end
flickerstreak@30: local n = select('#', ...)
flickerstreak@30: local debug = select(n, ...) == "Debug"
flickerstreak@30: if debug then
flickerstreak@30: n = n - 1
flickerstreak@30: local debugPools = recycleData.debugPools
flickerstreak@30: if not debugPools then
flickerstreak@30: debugPools = setmetatable({}, weak)
flickerstreak@30: recycleData.debugPools = debugPools
flickerstreak@30: end
flickerstreak@30: debug = debugPools[namespace]
flickerstreak@30: if not debug then
flickerstreak@30: debug = { num = 0 }
flickerstreak@30: debugPools[namespace] = debug
flickerstreak@30: end
flickerstreak@30: elseif recycleData.debugPools and recycleData.debugPools[namespace] then
flickerstreak@30: debug = recycleData.debugPools[namespace]
flickerstreak@30: end
flickerstreak@30: for i = 1, n do
flickerstreak@30: local func = select(i, ...)
flickerstreak@30: local recycleData_func = recycleData[func]
flickerstreak@30: if not recycleData_func then
flickerstreak@30: recycleData_func = setmetatable({}, weak)
flickerstreak@30: recycleData[func] = recycleData_func
flickerstreak@30: end
flickerstreak@30: if func == "newList" then
flickerstreak@30: local newList = recycleData_func[namespace]
flickerstreak@30: if not newList then
flickerstreak@30: function newList(...)
flickerstreak@30: local t = next(pool)
flickerstreak@30: local n = select('#', ...)
flickerstreak@30: if t then
flickerstreak@30: pool[t] = nil
flickerstreak@30: for i = 1, n do
flickerstreak@30: t[i] = select(i, ...)
flickerstreak@30: end
flickerstreak@30: else
flickerstreak@30: t = { ... }
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = debugstack(2)
flickerstreak@30: debug.num = debug.num + 1
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return t, n
flickerstreak@30: end
flickerstreak@30: recycleData_func[namespace] = newList
flickerstreak@30: end
flickerstreak@30: tmp[i] = newList
flickerstreak@30: elseif func == "newDict" then
flickerstreak@30: local newDict = recycleData_func[namespace]
flickerstreak@30: if not newDict then
flickerstreak@30: function newDict(...)
flickerstreak@30: local t = next(pool)
flickerstreak@30: if t then
flickerstreak@30: pool[t] = nil
flickerstreak@30: else
flickerstreak@30: t = {}
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for i = 1, select('#', ...), 2 do
flickerstreak@30: t[select(i, ...)] = select(i+1, ...)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = debugstack(2)
flickerstreak@30: debug.num = debug.num + 1
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return t
flickerstreak@30: end
flickerstreak@30: recycleData_func[namespace] = newDict
flickerstreak@30: end
flickerstreak@30: tmp[i] = newDict
flickerstreak@30: elseif func == "newSet" then
flickerstreak@30: local newSet = recycleData_func[namespace]
flickerstreak@30: if not newSet then
flickerstreak@30: function newSet(...)
flickerstreak@30: local t = next(pool)
flickerstreak@30: if t then
flickerstreak@30: pool[t] = nil
flickerstreak@30: else
flickerstreak@30: t = {}
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for i = 1, select('#', ...) do
flickerstreak@30: t[select(i, ...)] = true
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = debugstack(2)
flickerstreak@30: debug.num = debug.num + 1
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return t
flickerstreak@30: end
flickerstreak@30: recycleData_func[namespace] = newSet
flickerstreak@30: end
flickerstreak@30: tmp[i] = newSet
flickerstreak@30: elseif func == "del" then
flickerstreak@30: local del = recycleData_func[namespace]
flickerstreak@30: if not del then
flickerstreak@30: function del(t)
flickerstreak@30: if not t then
flickerstreak@30: error(("Bad argument #1 to `del'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30: end
flickerstreak@30: if pool[t] then
flickerstreak@30: local _, ret = pcall(error, "Error, double-free syndrome.", 3)
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: setmetatable(t, nil)
flickerstreak@30: for k in pairs(t) do
flickerstreak@30: t[k] = nil
flickerstreak@30: end
flickerstreak@30: t[true] = true
flickerstreak@30: t[true] = nil
flickerstreak@30: pool[t] = true
flickerstreak@30:
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = nil
flickerstreak@30: debug.num = debug.num - 1
flickerstreak@30: end
flickerstreak@30: return nil
flickerstreak@30: end
flickerstreak@30: recycleData_func[namespace] = del
flickerstreak@30: end
flickerstreak@30: tmp[i] = del
flickerstreak@30: elseif func == "unpackListAndDel" then
flickerstreak@30: local unpackListAndDel = recycleData_func[namespace]
flickerstreak@30: if not unpackListAndDel then
flickerstreak@30: local function f(t, start, finish)
flickerstreak@30: if start > finish then
flickerstreak@30: for k in pairs(t) do
flickerstreak@30: t[k] = nil
flickerstreak@30: end
flickerstreak@30: t[true] = true
flickerstreak@30: t[true] = nil
flickerstreak@30: pool[t] = true
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: return t[start], f(t, start+1, finish)
flickerstreak@30: end
flickerstreak@30: function unpackListAndDel(t, start, finish)
flickerstreak@30: if not t then
flickerstreak@30: error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30: end
flickerstreak@30: if not start then
flickerstreak@30: start = 1
flickerstreak@30: end
flickerstreak@30: if not finish then
flickerstreak@30: finish = #t
flickerstreak@30: end
flickerstreak@30: setmetatable(t, nil)
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = nil
flickerstreak@30: debug.num = debug.num - 1
flickerstreak@30: end
flickerstreak@30: return f(t, start, finish)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: tmp[i] = unpackListAndDel
flickerstreak@30: elseif func == "unpackSetAndDel" then
flickerstreak@30: local unpackSetAndDel = recycleData_func[namespace]
flickerstreak@30: if not unpackSetAndDel then
flickerstreak@30: local function f(t, current)
flickerstreak@30: current = next(t, current)
flickerstreak@30: if current == nil then
flickerstreak@30: for k in pairs(t) do
flickerstreak@30: t[k] = nil
flickerstreak@30: end
flickerstreak@30: t[true] = true
flickerstreak@30: t[true] = nil
flickerstreak@30: pool[t] = true
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: return current, f(t, current)
flickerstreak@30: end
flickerstreak@30: function unpackSetAndDel(t)
flickerstreak@30: if not t then
flickerstreak@30: error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30: end
flickerstreak@30: setmetatable(t, nil)
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = nil
flickerstreak@30: debug.num = debug.num - 1
flickerstreak@30: end
flickerstreak@30: return f(t, nil)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: tmp[i] = unpackSetAndDel
flickerstreak@30: elseif func == "unpackDictAndDel" then
flickerstreak@30: local unpackDictAndDel = recycleData_func[namespace]
flickerstreak@30: if not unpackDictAndDel then
flickerstreak@30: local function f(t, current)
flickerstreak@30: local value
flickerstreak@30: current, value = next(t, current)
flickerstreak@30: if current == nil then
flickerstreak@30: for k in pairs(t) do
flickerstreak@30: t[k] = nil
flickerstreak@30: end
flickerstreak@30: t[true] = true
flickerstreak@30: t[true] = nil
flickerstreak@30: pool[t] = true
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: return current, value, f(t, current)
flickerstreak@30: end
flickerstreak@30: function unpackDictAndDel(t)
flickerstreak@30: if not t then
flickerstreak@30: error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30: end
flickerstreak@30: setmetatable(t, nil)
flickerstreak@30: if debug then
flickerstreak@30: debug[t] = nil
flickerstreak@30: debug.num = debug.num - 1
flickerstreak@30: end
flickerstreak@30: return f(t, nil)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: tmp[i] = unpackDictAndDel
flickerstreak@30: else
flickerstreak@30: error(("Bad argument #%d to `GetRecyclingFunctions': %q, %q, %q, %q, %q, %q, or %q expected, got %s"):format(i+2, "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel", type(func) == "string" and ("%q"):format(func) or tostring(func)), 2)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return myUnpack(tmp)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * Prints information about the specified recycling namespace, including what tables are still in play and where they come from and how many there are.
flickerstreak@30: * This goes in tandem with ''':GetRecyclingFunctions'''
flickerstreak@30: Arguments:
flickerstreak@30: string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30: Example:
flickerstreak@30: local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug")
flickerstreak@30: local t = newList()
flickerstreak@30: Rock:DebugRecycle("MyNamespace")
flickerstreak@30: t = del(t)
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:DebugRecycle(namespace)
flickerstreak@30: local debug = recycleData.debugPools and recycleData.debugPools[namespace]
flickerstreak@30: if not debug then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: for k, v in pairs(debug) do
flickerstreak@30: if k ~= "num" then
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(v)
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage("------")
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(("%s: %d tables in action."):format(tostring(namespace), debug.num))
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local newList, del, unpackListAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions(MAJOR_VERSION, "newList", "del", "unpackListAndDel", "unpackDictAndDel")
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * Adds a unit test for the specified namespace
flickerstreak@30: * The function provided is called, and it should be where tests are performed, if a problem occurs, an error should fire. If no problems occur, it should return silently.
flickerstreak@30: * You can have as many tests per namespace as you want.
flickerstreak@30: Arguments:
flickerstreak@30: string - the namespace.
flickerstreak@30: function - the function to call.
flickerstreak@30: Example:
flickerstreak@30: Rock:AddUnitTest("LibMonkey-1.0", function()
flickerstreak@30: local LibMonkey = Rock("LibMonkey-1.0")
flickerstreak@30: assert(LibMonkey:Fling() == "Poo")
flickerstreak@30: end)
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:AddUnitTest(namespace, func)
flickerstreak@30: if not isStandalone then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: if type(namespace) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `AddUnitTest'. Expected %q, got %q."):format("string", type(namespace)), 2)
flickerstreak@30: end
flickerstreak@30: if namespace:find("^Lib[A-Z]") then
flickerstreak@30: local addon = figureCurrentAddon(2)
flickerstreak@30: if addon ~= namespace then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if type(func) ~= "function" then
flickerstreak@30: error(("Bad argument #3 to `AddUnitTest'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30: end
flickerstreak@30: local addon = figureCurrentAddon(2)
flickerstreak@30: if libraries[namespace] and addon ~= namespace then
flickerstreak@30: -- only work on standalone libraries.
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: local unitTests_namespace = unitTests[namespace]
flickerstreak@30: if not unitTests_namespace then
flickerstreak@30: unitTests_namespace = newList()
flickerstreak@30: unitTests[namespace] = unitTests_namespace
flickerstreak@30: end
flickerstreak@30: if not unitTests_namespace.addon then
flickerstreak@30: unitTests_namespace.addon = addon
flickerstreak@30: end
flickerstreak@30: if unitTestDB and not unitTestDB[namespace] then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: unitTests_namespace[#unitTests_namespace+1] = func
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local LibRockEvent
flickerstreak@30: local LibRockModuleCore
flickerstreak@30: local OpenDonationFrame, OpenIssueFrame
flickerstreak@30: function Rock:OnLibraryLoad(major, library)
flickerstreak@30: if major == "LibRockEvent-1.0" then
flickerstreak@30: LibRockEvent = library
flickerstreak@30: LibRockEvent:Embed(Rock)
flickerstreak@30: elseif major == "LibRockModuleCore-1.0" then
flickerstreak@30: LibRockModuleCore = library
flickerstreak@30: elseif major == "LibRockConfig-1.0" then
flickerstreak@30: if isStandalone then
flickerstreak@30: library.rockOptions.args.advanced = {
flickerstreak@30: type = 'group',
flickerstreak@30: groupType = 'inline',
flickerstreak@30: name = L["Advanced options"],
flickerstreak@30: desc = L["Advanced options for developers and power users."],
flickerstreak@30: order = -1,
flickerstreak@30: args = {
flickerstreak@30: unitTests = {
flickerstreak@30: type = 'multichoice',
flickerstreak@30: name = L["Unit tests"],
flickerstreak@30: desc = L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."],
flickerstreak@30: get = function(key)
flickerstreak@30: return unitTestDB[key]
flickerstreak@30: end,
flickerstreak@30: set = function(key, value)
flickerstreak@30: unitTestDB[key] = value or nil
flickerstreak@30: end,
flickerstreak@30: choices = function()
flickerstreak@30: local t = newList()
flickerstreak@30: for k in pairs(unitTests) do
flickerstreak@30: t[k] = k
flickerstreak@30: end
flickerstreak@30: return "@dict", unpackDictAndDel(t)
flickerstreak@30: end
flickerstreak@30: },
flickerstreak@30: contracts = {
flickerstreak@30: type = 'boolean',
flickerstreak@30: name = L["Contracts"],
flickerstreak@30: desc = L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."],
flickerstreak@30: get = function()
flickerstreak@30: return enableContracts
flickerstreak@30: end,
flickerstreak@30: set = function(value)
flickerstreak@30: _G.LibRock_1_0DB.contracts = value or nil
flickerstreak@30: enableContracts = value
flickerstreak@30: end,
flickerstreak@30: }
flickerstreak@30: }
flickerstreak@30: }
flickerstreak@30: end
flickerstreak@30: library.rockOptions.args.reloadui = {
flickerstreak@30: type = 'execute',
flickerstreak@30: name = L["Reload UI"],
flickerstreak@30: desc = L["Reload the User Interface for some changes to take effect."],
flickerstreak@30: buttonText = L["Reload"],
flickerstreak@30: func = function()
flickerstreak@30: _G.ReloadUI()
flickerstreak@30: end,
flickerstreak@30: order = -2,
flickerstreak@30: }
flickerstreak@30: Rock.donate = "Paypal:ckknight AT gmail DOT com"
flickerstreak@30: library.rockOptions.args.donate = {
flickerstreak@30: type = 'execute',
flickerstreak@30: name = L["Give donation"],
flickerstreak@30: buttonText = L["Donate"],
flickerstreak@30: desc = L["Give a much-needed donation to the author of this addon."],
flickerstreak@30: func = OpenDonationFrame,
flickerstreak@30: passValue = Rock,
flickerstreak@30: order = -3,
flickerstreak@30: }
flickerstreak@30: Rock.issueTracker = "Wowace:10027"
flickerstreak@30: library.rockOptions.args.issue = {
flickerstreak@30: type = 'execute',
flickerstreak@30: name = L["File issue"],
flickerstreak@30: buttonText = L["Report"],
flickerstreak@30: desc = L["File a bug or request a new feature or an improvement to this addon."],
flickerstreak@30: func = OpenIssueFrame,
flickerstreak@30: passValue = Rock,
flickerstreak@30: order = -4,
flickerstreak@30: }
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: addon_mt.__index = {}
flickerstreak@30: local addon_mt___index = addon_mt.__index
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: #FORCE_DOC
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all addons.
flickerstreak@30: * This information is retrieved from LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally.
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the addon is in an active state or not.
flickerstreak@30: Example:
flickerstreak@30: local active = MyAddon:IsActive()
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function addon_mt___index:IsActive()
flickerstreak@30: if LibRockModuleCore then
flickerstreak@30: local core = LibRockModuleCore:HasModule(self)
flickerstreak@30: if core then
flickerstreak@30: return core:IsModuleActive(self)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local self_db = self.db
flickerstreak@30: if self_db then
flickerstreak@30: local disabled
flickerstreak@30: local self_db_raw = self_db.raw
flickerstreak@30: if self_db_raw then
flickerstreak@30: local self_db_raw_disabled = self_db_raw.disabled
flickerstreak@30: if self_db_raw_disabled then
flickerstreak@30: local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false
flickerstreak@30: disabled = self_db_raw_disabled[profile]
flickerstreak@30: end
flickerstreak@30: else
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: return not disabled
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return not inactiveAddons[self]
flickerstreak@30: end
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: #FORCE_DOC
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all addons.
flickerstreak@30: * If it enables the addon, it will call :OnEnable(first) on the addon and :OnEmbedEnable(addon, first) on all its mixins.
flickerstreak@30: * If it disables the addon, it will call :OnDisable(first) on the addon and :OnEmbedDisable(addon, first) on all its mixins.
flickerstreak@30: * This information is stored by LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally.
flickerstreak@30: Arguments:
flickerstreak@30: [optional] boolean - whether the addon should be in an active state or not. Default: not :IsActive()
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the addon is in an active state or not.
flickerstreak@30: Example:
flickerstreak@30: MyAddon:ToggleActive() -- switch
flickerstreak@30: MyAddon:ToggleActive(true) -- force on
flickerstreak@30: MyAddon:ToggleActive(false) -- force off
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function addon_mt___index:ToggleActive(state)
flickerstreak@30: if state and state ~= true then
flickerstreak@30: error(("Bad argument #2 to `ToggleActive'. Expected %q or %q, got %q."):format("boolean", "nil", type(state)), 2)
flickerstreak@30: end
flickerstreak@30: if LibRockModuleCore then
flickerstreak@30: local core = LibRockModuleCore:HasModule(self)
flickerstreak@30: if core then
flickerstreak@30: return core:ToggleModuleActive(self, state)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local self_db = self.db
flickerstreak@30: if self_db then
flickerstreak@30: local self_db_raw = self_db.raw
flickerstreak@30: if not self_db_raw then
flickerstreak@30: error("Error saving to database with `ToggleActive'. db.raw not available.", 2)
flickerstreak@30: end
flickerstreak@30: local self_db_raw_disabled = self_db_raw.disabled
flickerstreak@30: if not self_db_raw_disabled then
flickerstreak@30: self_db_raw_disabled = newList()
flickerstreak@30: self_db_raw.disabled = self_db_raw_disabled
flickerstreak@30: end
flickerstreak@30: local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false
flickerstreak@30: if state == nil then
flickerstreak@30: state = not not self_db_raw_disabled[profile]
flickerstreak@30: elseif (not self_db_raw_disabled[profile]) == state then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: self_db_raw_disabled[profile] = not state or nil
flickerstreak@30: if next(self_db_raw_disabled) == nil then
flickerstreak@30: self_db_raw.disabled = del(self_db_raw_disabled)
flickerstreak@30: end
flickerstreak@30: else
flickerstreak@30: if state == nil then
flickerstreak@30: state = not not inactiveAddons[self]
flickerstreak@30: elseif (not inactiveAddons[self]) == state then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: inactiveAddons[self] = not state or nil
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock:RecheckEnabledStates()
flickerstreak@30:
flickerstreak@30: return state
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function noop() end
flickerstreak@30:
flickerstreak@30: do
flickerstreak@30: local preconditions = setmetatable({}, weakKey)
flickerstreak@30: local postconditions = setmetatable({}, weakKey)
flickerstreak@30: local postconditionsOld = setmetatable({}, weakKey)
flickerstreak@30:
flickerstreak@30: local currentMethod = nil
flickerstreak@30:
flickerstreak@30: local function hook(object, method)
flickerstreak@30: local object_method = object[method]
flickerstreak@30: object[method] = function(...)
flickerstreak@30: local pre = preconditions[object_method]
flickerstreak@30: local post = postconditions[object_method]
flickerstreak@30: if pre then
flickerstreak@30: local old_currentMethod = currentMethod
flickerstreak@30: currentMethod = method
flickerstreak@30: pre(...)
flickerstreak@30: currentMethod = old_currentMethod
flickerstreak@30: end
flickerstreak@30: if not post then
flickerstreak@30: return object_method(...)
flickerstreak@30: end
flickerstreak@30: local oldFunc = postconditionsOld[object_method]
flickerstreak@30: local old
flickerstreak@30: if oldFunc then
flickerstreak@30: old = newList()
flickerstreak@30: oldFunc(old, ...)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local old_currentMethod = currentMethod
flickerstreak@30: currentMethod = nil
flickerstreak@30: local ret, n = newList(object_method(...))
flickerstreak@30:
flickerstreak@30: currentMethod = method
flickerstreak@30: if old then
flickerstreak@30: post(old, ret, ...)
flickerstreak@30: old = del(old)
flickerstreak@30: else
flickerstreak@30: post(ret, ...)
flickerstreak@30: end
flickerstreak@30: currentMethod = old_currentMethod
flickerstreak@30: return unpackListAndDel(ret, 1, n)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function precondition(object, method, func)
flickerstreak@30: if type(object) ~= "table" then
flickerstreak@30: error(("Bad argument #1 to `precondition'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30: end
flickerstreak@30: if type(object[method]) ~= "function" then
flickerstreak@30: error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2)
flickerstreak@30: end
flickerstreak@30: if type(func) ~= "function" then
flickerstreak@30: error(("Bad argument #3 to `precondition'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local object_method = object[method]
flickerstreak@30: if preconditions[object_method] then
flickerstreak@30: error("Cannot call `preconditon' on the same method twice.", 2)
flickerstreak@30: end
flickerstreak@30: preconditions[object_method] = func
flickerstreak@30:
flickerstreak@30: if not postconditions[object_method] then
flickerstreak@30: hook(object, method)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function postcondition(object, method, func, fillOld)
flickerstreak@30: if type(object) ~= "table" then
flickerstreak@30: error(("Bad argument #1 to `postcondition'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30: end
flickerstreak@30: if type(object[method]) ~= "function" then
flickerstreak@30: error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2)
flickerstreak@30: end
flickerstreak@30: if type(func) ~= "function" then
flickerstreak@30: error(("Bad argument #3 to `postcondition'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30: end
flickerstreak@30: if fillOld and type(fillOld) ~= "function" then
flickerstreak@30: error(("Bad argument #4 to `postcondition'. Expected %q or %q, got %q."):format("function", "nil", type(func)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local object_method = object[method]
flickerstreak@30: if postconditions[object_method] then
flickerstreak@30: error("Cannot call `postcondition' on the same method twice.", 2)
flickerstreak@30: end
flickerstreak@30: postconditions[object_method] = func
flickerstreak@30: postconditionsOld[object_method] = fillOld
flickerstreak@30:
flickerstreak@30: if not preconditions[object_method] then
flickerstreak@30: hook(object, method)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function argCheck(value, position, ...)
flickerstreak@30: if not currentMethod then
flickerstreak@30: error("Cannot call `argCheck' outside of a pre/post-condition.", 2)
flickerstreak@30: end
flickerstreak@30: if type(position) ~= "number" then
flickerstreak@30: error(("Bad argument #2 to `argCheck'. Expected %q, got %q"):format("number", type(position)), 2)
flickerstreak@30: end
flickerstreak@30: local type_value = type(value)
flickerstreak@30: for i = 1, select('#', ...) do
flickerstreak@30: local v = select(i, ...)
flickerstreak@30: if type(v) ~= "string" then
flickerstreak@30: error(("Bad argument #%d to `argCheck'. Expected %q, got %q"):format(i+1, "string", type(v)), 2)
flickerstreak@30: end
flickerstreak@30: if v == type_value then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: local t = newList(...)
flickerstreak@30: t[#t] = nil
flickerstreak@30: for i,v in ipairs(t) do
flickerstreak@30: t[i] = ("%q"):format(v)
flickerstreak@30: end
flickerstreak@30: local s
flickerstreak@30: if #t == 0 then
flickerstreak@30: s = ("%q"):format((...))
flickerstreak@30: elseif #t == 1 then
flickerstreak@30: s = ("%q or %q"):format(...)
flickerstreak@30: else
flickerstreak@30: s = table_concat(t, ", ") .. ", or " .. ("%q"):format(select(#t+1, ...))
flickerstreak@30: end
flickerstreak@30: t = del(t)
flickerstreak@30:
flickerstreak@30: error(("Bad argument #%d to `%s'. Expected %s, got %q."):format(position, tostring(currentMethod), s, type_value), 4)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * Returns functions for the specified namespace based on what is provided.
flickerstreak@30: * function types:
flickerstreak@30: ; "precondition" : to set the pre-condition for a method.
flickerstreak@30: ; "postcondition" : to set the post-condition for a method.
flickerstreak@30: ; "argCheck" : to check the type of an argument, to be executed within a pre-condition.
flickerstreak@30: * preconditon is in the form of precondition(object, "methodName", func(self, ...))
flickerstreak@30: * postcondition is in the form of either postcondition(object, "methodName", func(returnValues, self, ...)) or postcondition(object, "methodName", func(oldValues, returnValues, self, ...), populateOld(oldValues, self, ...))
flickerstreak@30: ** returnValues is the list of return values, empty if no return values were sent.
flickerstreak@30: ** if the populateOld function is provided, then the empty oldValues table is provided and expected to be filled, and then given to the func.
flickerstreak@30: * argCheck is in the form of argCheck(value, n, "type1" [, "type2", ...])
flickerstreak@30: ** value is the value provided to the function you're checking.
flickerstreak@30: ** n is the argument position. ''Note: 1 is the position of `self'. 2 would be the first "real" position.''
flickerstreak@30: ** the tuple of types can be any string, but specifically "nil", "boolean", "string", "number", "function", "userdata", "table", etc.
flickerstreak@30: Arguments:
flickerstreak@30: string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30: Example:
flickerstreak@30: local precondition, postcondition, argCheck = Rock:GetRecyclingFunctions("Stack", "precondition", "postcondition", "argCheck")
flickerstreak@30:
flickerstreak@30: local stack = {}
flickerstreak@30: stack.IsEmpty = function(self)
flickerstreak@30: return self[1] == nil
flickerstreak@30: end
flickerstreak@30: stack.GetLength = function(self)
flickerstreak@30: return #self
flickerstreak@30: end
flickerstreak@30: stack.Push = function(self, value)
flickerstreak@30: self[#self+1] = value
flickerstreak@30: end
flickerstreak@30: precondition(stack, "Push", function(self, value)
flickerstreak@30: argCheck(value, 2, "string") -- only accept strings, no other values
flickerstreak@30: end)
flickerstreak@30: postcondition(stack, "Push", function(old, ret, self, value)
flickerstreak@30: assert(self:GetLength() == old.length+1)
flickerstreak@30: assert(not self:IsEmpty())
flickerstreak@30: end, function(old, self)
flickerstreak@30: old.length = self:GetLength()
flickerstreak@30: end)
flickerstreak@30: stack.Pop = function(self)
flickerstreak@30: local value = self[#self]
flickerstreak@30: self[#self] = nil
flickerstreak@30: return value
flickerstreak@30: end
flickerstreak@30: precondition(stack, "Pop", function(self)
flickerstreak@30: assert(self:GetLength() >= 1)
flickerstreak@30: end)
flickerstreak@30: postcondition(stack, "Pop", function(old, ret, self)
flickerstreak@30: assert(self:GetLength() == old.length-1)
flickerstreak@30: end, function(old, self)
flickerstreak@30: old.length = self:GetLength()
flickerstreak@30: end)
flickerstreak@30: stack.Peek = function(self)
flickerstreak@30: return self[#self]
flickerstreak@30: end
flickerstreak@30: precondition(stack, "Peek", function(self)
flickerstreak@30: assert(self:GetLength() >= 1)
flickerstreak@30: end)
flickerstreak@30: postcondition(stack, "Peek", function(old, ret, self)
flickerstreak@30: assert(self:GetLength() == old.length)
flickerstreak@30: end, function(old, self)
flickerstreak@30: old.length = self:GetLength()
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: local t = setmetatable({}, {__index=stack})
flickerstreak@30: t:Push("Alpha")
flickerstreak@30: t:Push("Bravo")
flickerstreak@30: t:Push(5) -- error, only strings
flickerstreak@30: assert(t:Pop() == "Bravo")
flickerstreak@30: assert(t:Pop() == "Alpha")
flickerstreak@30: t:Pop() -- error, out of values
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetContractFunctions(namespace, ...)
flickerstreak@30: if namespace == "precondition" or namespace == "postcondition" or namespace == "argCheck" then
flickerstreak@30: error(("Bad argument #2 to `GetContractFunctions'. Cannot be %q."):format(namespace), 2)
flickerstreak@30: end
flickerstreak@30: local t = newList()
flickerstreak@30: if enableContracts then
flickerstreak@30: for i = 1, select('#', ...) do
flickerstreak@30: local v = select(i, ...)
flickerstreak@30: if v == "precondition" then
flickerstreak@30: t[i] = precondition
flickerstreak@30: elseif v == "postcondition" then
flickerstreak@30: t[i] = postcondition
flickerstreak@30: elseif v == "argCheck" then
flickerstreak@30: t[i] = argCheck
flickerstreak@30: else
flickerstreak@30: error(("Bad argument #%d to `GetContractFunctions'. Expected %q, %q, or %q, got %q."):format(i+2, "precondition", "postcondition", "argCheck", tostring(v)))
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: else
flickerstreak@30: for i = 1, select('#', ...) do
flickerstreak@30: t[i] = noop
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return unpackListAndDel(t)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * convert a revision string to a number
flickerstreak@30: Arguments:
flickerstreak@30: string - revision string
flickerstreak@30: Returns:
flickerstreak@30: string or number - the string given or the number retrieved from it.
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: local function coerceRevisionToNumber(version)
flickerstreak@30: if type(version) == "string" then
flickerstreak@30: return tonumber(version:match("(%-?%d+)")) or version
flickerstreak@30: else
flickerstreak@30: return version
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * try to enable the standalone library specified
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the library is properly enabled and loadable.
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: local function TryToEnable(addon)
flickerstreak@30: local islod = IsAddOnLoadOnDemand(addon)
flickerstreak@30: if islod then
flickerstreak@30: local _, _, _, enabled = GetAddOnInfo(addon)
flickerstreak@30: EnableAddOn(addon)
flickerstreak@30: local _, _, _, _, loadable = GetAddOnInfo(addon)
flickerstreak@30: if not loadable and not enabled then
flickerstreak@30: DisableAddOn(addon)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return loadable
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * try to load the standalone library specified
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the library is loaded.
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: local function TryToLoadStandalone(major)
flickerstreak@30: major = major:lower()
flickerstreak@30: if scannedLibraries[major] then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: scannedLibraries[major] = true
flickerstreak@30: local name, _, _, enabled, loadable, state = GetAddOnInfo(major)
flickerstreak@30: if state == "MISSING" or not IsAddOnLoadOnDemand(major) then
flickerstreak@30: -- backwards compatibility for X-AceLibrary
flickerstreak@30: local field = "X-AceLibrary-" .. major
flickerstreak@30: local loaded
flickerstreak@30: for i = 1, GetNumAddOns() do
flickerstreak@30: if GetAddOnMetadata(i, field) then
flickerstreak@30: name, _, _, enabled, loadable = GetAddOnInfo(i)
flickerstreak@30:
flickerstreak@30: loadable = (enabled and loadable) or TryToEnable(name)
flickerstreak@30: if loadable then
flickerstreak@30: loaded = true
flickerstreak@30: LoadAddOn(name)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return loaded
flickerstreak@30: elseif (enabled and loadable) or TryToEnable(major) then
flickerstreak@30: LoadAddOn(major)
flickerstreak@30: return true
flickerstreak@30: else
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * Return the LibStub library, casing is unimportant.
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: Returns:
flickerstreak@30: table or nil - library
flickerstreak@30: number - minor version
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: local function GetLibStubLibrary(major)
flickerstreak@30: local lib, minor = LibStub:GetLibrary(major, true)
flickerstreak@30: if lib then
flickerstreak@30: return lib, minor
flickerstreak@30: end
flickerstreak@30: major = major:lower()
flickerstreak@30: for m, lib in LibStub:IterateLibraries() do
flickerstreak@30: if m:lower() == major then
flickerstreak@30: return LibStub:GetLibrary(m)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return nil, nil
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local finishLibraryRegistration
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * create a new library if the version provided is not out of date.
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: number - version of the library.
flickerstreak@30: Returns:
flickerstreak@30: library, oldLibrary
flickerstreak@30: * table or nil - the library with which to manipulate
flickerstreak@30: * table or nil - the old version of the library to upgrade from
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30: if not LibMonkey then
flickerstreak@30: -- opt out now, out of date
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:NewLibrary(major, version)
flickerstreak@30: if type(major) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `NewLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30: end
flickerstreak@30: if not major:match("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$") then
flickerstreak@30: error(("Bad argument #2 to `NewLibrary'. Must match %q, got %q."):format("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$", major), 2)
flickerstreak@30: end
flickerstreak@30: TryToLoadStandalone(major)
flickerstreak@30: version = coerceRevisionToNumber(version)
flickerstreak@30: if type(version) ~= "number" then
flickerstreak@30: error(("Bad argument #3 to `NewLibrary'. Expected %q, got %q."):format("number", type(version)), 2)
flickerstreak@30: end
flickerstreak@30: local library, oldMinor = LibStub:GetLibrary(major, true)
flickerstreak@30: if oldMinor and oldMinor >= version then
flickerstreak@30: -- in case LibStub is acting funny
flickerstreak@30: return nil, nil
flickerstreak@30: end
flickerstreak@30: local library, oldMinor = LibStub:NewLibrary(major, version)
flickerstreak@30: if not library then
flickerstreak@30: return nil, nil
flickerstreak@30: end
flickerstreak@30: local unitTests_major = unitTests[major]
flickerstreak@30: if unitTests_major then
flickerstreak@30: for k,v in pairs(unitTests_major) do
flickerstreak@30: unitTests_major[k] = nil
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: for k, v in pairs(recycleData) do
flickerstreak@30: v[major] = nil
flickerstreak@30: end
flickerstreak@30: local mixinToObject_library = mixinToObject[library]
flickerstreak@30:
flickerstreak@30: local oldLib
flickerstreak@30: if oldMinor then
flickerstreak@30: -- previous version exists
flickerstreak@30: local mixins = newList()
flickerstreak@30: for mixin, objectSet in pairs(mixinToObject) do
flickerstreak@30: if objectSet[library] then
flickerstreak@30: mixins[mixin] = true
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: for mixin in pairs(mixins) do
flickerstreak@30: mixin:Unembed(library)
flickerstreak@30: end
flickerstreak@30: mixins = del(mixins)
flickerstreak@30: oldLib = newList()
flickerstreak@30: for k, v in pairs(library) do
flickerstreak@30: oldLib[k] = v
flickerstreak@30: library[k] = nil
flickerstreak@30: end
flickerstreak@30: setmetatable(oldLib, getmetatable(library))
flickerstreak@30: setmetatable(library, nil)
flickerstreak@30: end
flickerstreak@30: finishLibraryRegistration(major, version, library, figureCurrentAddon(2))
flickerstreak@30:
flickerstreak@30: return library, oldLib
flickerstreak@30: end
flickerstreak@30: function finishLibraryRegistration(major, version, library, folder)
flickerstreak@30: library.name = major
flickerstreak@30:
flickerstreak@30: libraries[major] = library
flickerstreak@30: pendingLibraries[library] = folder
flickerstreak@30: local exportedMethods_library = exportedMethods[library]
flickerstreak@30: if exportedMethods_library then
flickerstreak@30: local mixinToObject_library = mixinToObject[library]
flickerstreak@30: if mixinToObject_library then
flickerstreak@30: for object in pairs(mixinToObject_library) do
flickerstreak@30: for _,v in ipairs(exportedMethods_library) do
flickerstreak@30: object[v] = nil
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: exportedMethods[library] = del(exportedMethods_library)
flickerstreak@30: end
flickerstreak@30: if library ~= Rock then
flickerstreak@30: Rock:Embed(library)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: frame:Show()
flickerstreak@30: end
flickerstreak@30: if not oldRock then
flickerstreak@30: finishLibraryRegistration(MAJOR_VERSION, MINOR_VERSION, Rock, figureCurrentAddon(1))
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: -- #NODOC
flickerstreak@30: local function __removeLibrary(libName)
flickerstreak@30: libraries[libName] = nil
flickerstreak@30: if LibStub.libs then
flickerstreak@30: LibStub.libs[libName] = nil
flickerstreak@30: end
flickerstreak@30: if LibStub.minors then
flickerstreak@30: LibStub.minors[libName] = nil
flickerstreak@30: end
flickerstreak@30: local lastCount
flickerstreak@30: repeat
flickerstreak@30: lastCount = collectgarbage('count')
flickerstreak@30: collectgarbage('collect')
flickerstreak@30: until lastCount == collectgarbage('count')
flickerstreak@30: end
flickerstreak@30: local function run(_,a)
flickerstreak@30: if a < 1/30 then
flickerstreak@30: collectgarbage('step')
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * properly finalizes the library, essentially stating that it has loaded properly.
flickerstreak@30: * This will call :OnLibraryLoad("major", library) on every other library
flickerstreak@30: * This will also call :OnLibraryLoad("major", library) on the library provided, using every other library as the arguments.
flickerstreak@30: * An error will occur if this is not done before ADDON_LOADED.
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30: if not LibMonkey then
flickerstreak@30: -- opt out now, out of date
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: Rock:FinalizeLibrary("LibMonkey-1.0")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:FinalizeLibrary(major)
flickerstreak@30: if type(major) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `FinalizeLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30: end
flickerstreak@30: local library = libraries[major]
flickerstreak@30: if not library then
flickerstreak@30: error(("Bad argument #2 to `FinalizeLibrary'. %q is not a library."):format("string", major), 2)
flickerstreak@30: end
flickerstreak@30: pendingLibraries[library] = nil
flickerstreak@30: local library_OnLibraryLoad = library.OnLibraryLoad
flickerstreak@30: if library_OnLibraryLoad then
flickerstreak@30: for maj, lib in LibStub:IterateLibraries() do -- for all libraries
flickerstreak@30: if maj ~= major then
flickerstreak@30: local success, ret = pcall(library_OnLibraryLoad, library, maj, lib)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if finalizedLibraries[library] then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: finalizedLibraries[library] = true
flickerstreak@30: for maj, lib in pairs(libraries) do -- just Rock libraries
flickerstreak@30: if maj ~= major then
flickerstreak@30: local lib_OnLibraryLoad = lib.OnLibraryLoad
flickerstreak@30: if lib_OnLibraryLoad then
flickerstreak@30: local success, ret = pcall(lib_OnLibraryLoad, lib, major, library)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if LibRockEvent then
flickerstreak@30: self:DispatchEvent("LibraryLoad", major, library)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function manualFinalize(major, library)
flickerstreak@30: if libraries[major] then -- non-Rock libraries only
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: if finalizedLibraries[library] then -- don't do it twice
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: finalizedLibraries[library] = true
flickerstreak@30: for maj, lib in pairs(libraries) do -- just Rock libraries
flickerstreak@30: if maj ~= major then
flickerstreak@30: local lib_OnLibraryLoad = lib.OnLibraryLoad
flickerstreak@30: if lib_OnLibraryLoad then
flickerstreak@30: local success, ret = pcall(lib_OnLibraryLoad, lib, major, library)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if LibRockEvent then
flickerstreak@30: Rock:DispatchEvent("LibraryLoad", major, library)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: [optional] boolean - whether to not load a library if it is not found. Default: false
flickerstreak@30: [optional] boolean - whether to not error if a library is not found. Default: false
flickerstreak@30: Returns:
flickerstreak@30: library
flickerstreak@30: * table or nil - the library requested
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:GetLibrary("LibMonkey-1.0")
flickerstreak@30: -- or
flickerstreak@30: local LibMonkey = Rock("LibMonkey-1.0")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetLibrary(major, dontLoad, dontError)
flickerstreak@30: if type(major) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `GetLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30: end
flickerstreak@30: if dontLoad and dontLoad ~= true then
flickerstreak@30: error(("Bad argument #3 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2)
flickerstreak@30: end
flickerstreak@30: if dontError and dontError ~= true then
flickerstreak@30: error(("Bad argument #4 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontError)), 2)
flickerstreak@30: end
flickerstreak@30: if not dontLoad then
flickerstreak@30: TryToLoadStandalone(major)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local library = GetLibStubLibrary(major)
flickerstreak@30: if not library then
flickerstreak@30: if dontError then
flickerstreak@30: return nil
flickerstreak@30: end
flickerstreak@30: error(("Library %q not found."):format(major), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return library
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: setmetatable(Rock, { __call = Rock.GetLibrary })
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the library exists and is a proper mixin which can be embedded.
flickerstreak@30: Example:
flickerstreak@30: local isMixin = Rock:IsLibraryMixin("LibMonkey-1.0")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:IsLibraryMixin(name)
flickerstreak@30: local library = self:GetLibrary(name, false, true)
flickerstreak@30: if not library then
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: return not not exportedMethods[library]
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the library.
flickerstreak@30: [optional] boolean - whether to not load a library if it is not found. Default: false
flickerstreak@30: Returns:
flickerstreak@30: library
flickerstreak@30: * table or nil - the library requested
flickerstreak@30: Example:
flickerstreak@30: local hasLibMonkey = Rock:HasLibrary("LibMonkey-1.0")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:HasLibrary(major, dontLoad)
flickerstreak@30: if type(major) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `HasLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30: end
flickerstreak@30: if dontLoad and dontLoad ~= true then
flickerstreak@30: error(("Bad argument #3 to `HasLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2)
flickerstreak@30: end
flickerstreak@30: if not dontLoad then
flickerstreak@30: TryToLoadStandalone(major)
flickerstreak@30: end
flickerstreak@30: return not not GetLibStubLibrary(major)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all libraries
flickerstreak@30: Returns:
flickerstreak@30: major, minor
flickerstreak@30: * string - name of the library
flickerstreak@30: * number - version of the library
flickerstreak@30: Example:
flickerstreak@30: local major, minor = Rock:GetLibraryVersion() -- will be "LibRock-1.0", 12345
flickerstreak@30: local major, minor = LibMonkey:GetLibraryVersion() -- will be "LibMonkey-1.0", 50
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetLibraryVersion()
flickerstreak@30: if type(self) ~= "table" then
flickerstreak@30: return nil, nil
flickerstreak@30: end
flickerstreak@30: local major
flickerstreak@30: local name = self.name
flickerstreak@30: if name and GetLibStubLibrary(name) == self then
flickerstreak@30: major = name
flickerstreak@30: else
flickerstreak@30: for m, instance in LibStub:IterateLibraries() do
flickerstreak@30: if instance == self then
flickerstreak@30: major = m
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if not major then
flickerstreak@30: return nil, nil
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: local _, minor = GetLibStubLibrary(major)
flickerstreak@30: return major, minor
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Returns:
flickerstreak@30: an iterator to traverse all registered libraries.
flickerstreak@30: Example:
flickerstreak@30: for major, library in Rock:IterateLibraries() do
flickerstreak@30: -- do something with major and library
flickerstreak@30: end
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:IterateLibraries()
flickerstreak@30: return LibStub:IterateLibraries()
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all libraries
flickerstreak@30: * Allows you to set precisely what methods for the library to export.
flickerstreak@30: * This automatically turns a library into a mixin.
flickerstreak@30: Arguments:
flickerstreak@30: tuple - the list of method names to export.
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30: LibMonkey.FlingPoo = function(self)
flickerstreak@30: return "Splat!"
flickerstreak@30: end
flickerstreak@30: LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30: -- later
flickerstreak@30: local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30: assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:SetExportedMethods(...)
flickerstreak@30: if exportedMethods[self] then
flickerstreak@30: error("Cannot call `SetExportedMethods' more than once.", 2)
flickerstreak@30: end
flickerstreak@30: local t = newList(...)
flickerstreak@30: if #t == 0 then
flickerstreak@30: error("Must supply at least 1 method to `SetExportedMethods'.", 2)
flickerstreak@30: end
flickerstreak@30: for i,v in ipairs(t) do
flickerstreak@30: if type(self[v]) ~= "function" then
flickerstreak@30: error(("Bad argument #%d to `SetExportedMethods'. Method %q does not exist."):format(i+1, tostring(v)), 2)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: exportedMethods[self] = t
flickerstreak@30:
flickerstreak@30: local mixinToObject_library = mixinToObject[self]
flickerstreak@30: if mixinToObject_library then
flickerstreak@30: for object in pairs(mixinToObject_library) do
flickerstreak@30: for _,method in ipairs(t) do
flickerstreak@30: object[method] = self[method]
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all libraries
flickerstreak@30: * Embeds all the methods previously set to export onto a table.
flickerstreak@30: * This will call :OnEmbed(object) on the library if it is available.
flickerstreak@30: Arguments:
flickerstreak@30: table - the table with which to export methods onto.
flickerstreak@30: Returns:
flickerstreak@30: The table provided, after embedding.
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30: LibMonkey.FlingPoo = function(self)
flickerstreak@30: return "Splat!"
flickerstreak@30: end
flickerstreak@30: LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30: -- later
flickerstreak@30: local Darwin = {}
flickerstreak@30: Rock("LibMonkey-1.0"):Embed(Darwin)
flickerstreak@30: assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:Embed(object)
flickerstreak@30: if not exportedMethods[self] then
flickerstreak@30: error(("Cannot call `Embed' for library %q if `SetExportedMethods' has not been called."):format(tostring(self.name)), 2)
flickerstreak@30: end
flickerstreak@30: if type(object) ~= "table" then
flickerstreak@30: error(("Bad argument #2 to `Embed'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for i,v in ipairs(exportedMethods[self]) do
flickerstreak@30: if type(self[v]) ~= "function" then
flickerstreak@30: error(("Problem embedding method %q from library %q. Expected %q, got %q."):format(tostring(v), better_tostring(self), "function", type(self[v])))
flickerstreak@30: end
flickerstreak@30: object[v] = self[v]
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if not mixinToObject[self] then
flickerstreak@30: -- weak because objects come and go
flickerstreak@30: mixinToObject[self] = setmetatable(newList(), weakKey)
flickerstreak@30: end
flickerstreak@30: if mixinToObject[self][object] then
flickerstreak@30: error(("Cannot embed library %q into the same object %q more than once."):format(better_tostring(self), better_tostring(object)), 2)
flickerstreak@30: end
flickerstreak@30: mixinToObject[self][object] = true
flickerstreak@30: if type(rawget(object, 'mixins')) == "table" then
flickerstreak@30: object.mixins[self] = true
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local self_OnEmbed = self.OnEmbed
flickerstreak@30: if self_OnEmbed then
flickerstreak@30: local success, ret = pcall(self_OnEmbed, self, object)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return object
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * This is exported to all libraries
flickerstreak@30: * Unembeds all the methods previously set to export onto a table.
flickerstreak@30: * This will error if the library is not embedded on the object
flickerstreak@30: * This will call :OnUnembed(object) on the library if it is available.
flickerstreak@30: Arguments:
flickerstreak@30: table - the table with which to export methods onto.
flickerstreak@30: Returns:
flickerstreak@30: The table provided, after embedding.
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30: LibMonkey.FlingPoo = function(self)
flickerstreak@30: return "Splat!"
flickerstreak@30: end
flickerstreak@30: LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30: -- later
flickerstreak@30: local Darwin = {}
flickerstreak@30: Rock("LibMonkey-1.0"):Embed(Darwin)
flickerstreak@30: assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30: Rock("LibMonkey-1.0"):Unembed(Darwin)
flickerstreak@30: assert(Darwin.FlingPoo == nil)
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:Unembed(object)
flickerstreak@30: if not exportedMethods[self] then
flickerstreak@30: error(("Cannot call `Unembed' for library %q if `SetExportedMethods' has not been called."):format(better_tostring(self)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if not mixinToObject[self] or not mixinToObject[self][object] then
flickerstreak@30: error(("Cannot unembed library %q from object %q, since it is not embedded originally."):format(better_tostring(self), better_tostring(object)), 2)
flickerstreak@30: end
flickerstreak@30: local mixinToObject_self = mixinToObject[self]
flickerstreak@30: mixinToObject_self[object] = nil
flickerstreak@30: if not next(mixinToObject_self) then
flickerstreak@30: mixinToObject[self] = del(mixinToObject_self)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local mixin_OnUnembed = self.OnUnembed
flickerstreak@30: if mixin_OnUnembed then
flickerstreak@30: local success, ret = pcall(mixin_OnUnembed, self, object)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for i,v in ipairs(exportedMethods[self]) do
flickerstreak@30: object[v] = nil
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function embedAce2Mixin(mixin, object)
flickerstreak@30: if not mixinToObject[mixin] then
flickerstreak@30: mixinToObject[mixin] = setmetatable(newList(), weakKey)
flickerstreak@30: end
flickerstreak@30: mixinToObject[mixin][object] = true
flickerstreak@30: mixin:embed(object)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function embedLibStubMixin(mixin, object)
flickerstreak@30: if not mixinToObject[mixin] then
flickerstreak@30: mixinToObject[mixin] = setmetatable(newList(), weakKey)
flickerstreak@30: end
flickerstreak@30: mixinToObject[mixin][object] = true
flickerstreak@30: mixin:Embed(object)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * create a new addon with the specified name.
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the addon.
flickerstreak@30: tuple - list of mixins with which to embed into this addon.
flickerstreak@30: Returns:
flickerstreak@30: addon
flickerstreak@30: * table - the addon with which to manipulate
flickerstreak@30: Example:
flickerstreak@30: local MyAddon = Rock:NewAddon("MyAddon", "Mixin-1.0", "OtherMixin-2.0")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:NewAddon(name, ...)
flickerstreak@30: if type(name) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `NewAddon'. Expected %q, got %q"):format("string", type(name)), 2)
flickerstreak@30: end
flickerstreak@30: if name:match("^Lib[A-Z]") then
flickerstreak@30: error(("Bad argument #2 to `NewAddon'. Cannot start with %q, got %q."):format("Lib", name), 2)
flickerstreak@30: end
flickerstreak@30: if self == Rock and name:match("_") then
flickerstreak@30: error(("Bad argument #2 to `NewAddon'. Cannot contain underscores, got %q."):format(name), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if addons[name] then
flickerstreak@30: error(("Bad argument #2 to `NewAddon'. Addon %q already created."):format(name), 2)
flickerstreak@30: end
flickerstreak@30: local addon = setmetatable(newList(), addon_mt)
flickerstreak@30: addon.name = name
flickerstreak@30:
flickerstreak@30: local mixinSet = newList()
flickerstreak@30:
flickerstreak@30: for i = 1, select('#', ...) do
flickerstreak@30: local libName = select(i, ...)
flickerstreak@30: if mixinSet[libName] then
flickerstreak@30: error(("Bad argument #%d to `NewAddon'. %q already stated."):format(i+2, tostring(libName)), 2)
flickerstreak@30: end
flickerstreak@30: mixinSet[libName] = true
flickerstreak@30: TryToLoadStandalone(libName)
flickerstreak@30: local library = Rock:GetLibrary(libName, false, true)
flickerstreak@30: if not library then
flickerstreak@30: error(("Bad argument #%d to `NewAddon'. Library %q is not found."):format(i+2, tostring(libName)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local style = 'rock'
flickerstreak@30:
flickerstreak@30: if not exportedMethods[library] then
flickerstreak@30: local good = false
flickerstreak@30: if AceLibrary then
flickerstreak@30: local AceOO = AceLibrary:HasInstance("AceOO-2.0", false) and AceLibrary("AceOO-2.0")
flickerstreak@30: if AceOO.inherits(library, AceOO.Mixin) then
flickerstreak@30: good = true
flickerstreak@30: style = 'ace2'
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if not good and type(rawget(library, 'Embed')) == "function" then
flickerstreak@30: good = true
flickerstreak@30: style = 'libstub'
flickerstreak@30: end
flickerstreak@30: if not good then
flickerstreak@30: error(("Bad argument #%d to `NewAddon'. Library %q is not a mixin."):format(i+2, tostring(libName)), 2)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if library == Rock then
flickerstreak@30: error(("Bad argument #%d to `NewAddon'. Cannot use %q as a mixin."):format(i+2, tostring(libName)), 2)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if style == 'rock' then
flickerstreak@30: library:Embed(addon)
flickerstreak@30: elseif style == 'ace2' then
flickerstreak@30: embedAce2Mixin(library, addon)
flickerstreak@30: elseif style == 'libstub' then
flickerstreak@30: embedLibStubMixin(library, addon)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: mixinSet = del(mixinSet)
flickerstreak@30:
flickerstreak@30: addons[name] = addon
flickerstreak@30: pendingAddons[#pendingAddons+1] = addon
flickerstreak@30: pendingAddonsEnable[#pendingAddonsEnable+1] = addon
flickerstreak@30: addonToFolder[addon] = figureCurrentAddon(self == Rock and 2 or 4)
flickerstreak@30:
flickerstreak@30: frame:Show()
flickerstreak@30:
flickerstreak@30: return addon
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string - name of the addon.
flickerstreak@30: Returns:
flickerstreak@30: addon
flickerstreak@30: * table or nil - the addon requested
flickerstreak@30: Example:
flickerstreak@30: local MyAddon = Rock:GetAddon("MyAddon")
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetAddon(name)
flickerstreak@30: if type(name) ~= "string" then
flickerstreak@30: return nil
flickerstreak@30: end
flickerstreak@30: local addon = addons[name]
flickerstreak@30: if addon then
flickerstreak@30: return addon
flickerstreak@30: end
flickerstreak@30: name = name:lower()
flickerstreak@30: for k, v in pairs(addons) do
flickerstreak@30: if k:lower() == name then
flickerstreak@30: return v
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return nil
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string or table - name of the addon or the addon itself.
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the addon requested exists.
flickerstreak@30: Example:
flickerstreak@30: local hasMyAddon = Rock:HasAddon("MyAddon")
flickerstreak@30: -- or
flickerstreak@30: local hasMyAddon = Rock:HasAddon(MyAddon)
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:HasAddon(name)
flickerstreak@30: if type(name) == "string" then
flickerstreak@30: local addon = addons[name]
flickerstreak@30: if addon then
flickerstreak@30: return true
flickerstreak@30: end
flickerstreak@30: name = name:lower()
flickerstreak@30: for k, v in pairs(addons) do
flickerstreak@30: if k:lower() == name then
flickerstreak@30: return true
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: elseif type(name) == "table" then
flickerstreak@30: for k,v in pairs(addons) do
flickerstreak@30: if v == name then
flickerstreak@30: return true
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Returns:
flickerstreak@30: an iterator to traverse all addons created with Rock.
flickerstreak@30: Example:
flickerstreak@30: for name, addon in Rock:IterateAddons() do
flickerstreak@30: -- do something with name and addon
flickerstreak@30: end
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:IterateAddons()
flickerstreak@30: return pairs(addons)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: string - major version of the mixin library
flickerstreak@30: Returns:
flickerstreak@30: an iterator to traverse all objects that the given mixin has embedded into
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30: local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30: for object in LibMonkey:IterateMixinObjects("LibMonkey-1.0") do
flickerstreak@30: assert(object == Darwin)
flickerstreak@30: end
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:IterateMixinObjects(mixinName)
flickerstreak@30: local mixin
flickerstreak@30: if type(mixinName) == "table" then
flickerstreak@30: mixin = mixinName
flickerstreak@30: else
flickerstreak@30: if type(mixinName) ~= "string" then
flickerstreak@30: error(("Bad argument #2 to `IterateMixinObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2)
flickerstreak@30: end
flickerstreak@30: mixin = libraries[mixinName]
flickerstreak@30: end
flickerstreak@30: local mixinToObject_mixin = mixinToObject[mixin]
flickerstreak@30: if not mixinToObject_mixin then
flickerstreak@30: return noop
flickerstreak@30: end
flickerstreak@30: return pairs(mixinToObject_mixin)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function iter(object, mixin)
flickerstreak@30: mixin = next(mixinToObject, mixin)
flickerstreak@30: if not mixin then
flickerstreak@30: return nil
flickerstreak@30: elseif mixinToObject[mixin][object] then
flickerstreak@30: return mixin
flickerstreak@30: end
flickerstreak@30: return iter(object, mixin) -- try next mixin
flickerstreak@30: end
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Returns:
flickerstreak@30: an iterator to traverse all mixins that an object has embedded
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30: local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30: for mixin in Rock:IterateObjectMixins(Darwin) do
flickerstreak@30: assert(mixin == LibMonkey)
flickerstreak@30: end
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:IterateObjectMixins(object)
flickerstreak@30: if type(object) ~= "table" then
flickerstreak@30: error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30: end
flickerstreak@30: return iter, object, nil
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Arguments:
flickerstreak@30: table - the object to check
flickerstreak@30: string - the mixin to check
flickerstreak@30: Returns:
flickerstreak@30: boolean - whether the object has the given mixin embedded into it.
flickerstreak@30: Example:
flickerstreak@30: local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30: local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30: assert(Rock:DoesObjectUseMixin(Darwin, "LibMonkey-1.0"))
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:DoesObjectUseMixin(object, mixinName)
flickerstreak@30: if type(object) ~= "table" then
flickerstreak@30: error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30: end
flickerstreak@30: local mixin
flickerstreak@30: if type(mixinName) == "table" then
flickerstreak@30: mixin = mixinName
flickerstreak@30: else
flickerstreak@30: if type(mixinName) ~= "string" then
flickerstreak@30: error(("Bad argument #3 to `IterateMiDoesObjectUseMixininObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2)
flickerstreak@30: end
flickerstreak@30: mixin = libraries[mixinName]
flickerstreak@30: end
flickerstreak@30: if not mixin then
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local mixinToObject_mixin = mixinToObject[mixin]
flickerstreak@30: if not mixinToObject_mixin then
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: return not not mixinToObject_mixin[object]
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock.UID_NUM = oldRock and oldRock.UID_NUM or 0
flickerstreak@30: --[[---------------------------------------------------------------------------
flickerstreak@30: Notes:
flickerstreak@30: * This UID is not unique across sessions. If you save a UID in a saved variable, the same UID can be generated in another session.
flickerstreak@30: Returns:
flickerstreak@30: number - a unique number.
flickerstreak@30: Example:
flickerstreak@30: local UID = Rock:GetUID()
flickerstreak@30: -----------------------------------------------------------------------------]]
flickerstreak@30: function Rock:GetUID()
flickerstreak@30: local num = Rock.UID_NUM + 1
flickerstreak@30: Rock.UID_NUM = num
flickerstreak@30: return num
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function unobfuscateEmail(email)
flickerstreak@30: return email:gsub(" AT ", "@"):gsub(" DOT ", ".")
flickerstreak@30: end
flickerstreak@30: local function fix(char)
flickerstreak@30: return ("%%%02x"):format(char:byte())
flickerstreak@30: end
flickerstreak@30: local function urlencode(text)
flickerstreak@30: return text:gsub("[^0-9A-Za-z]", fix)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local url
flickerstreak@30: local function makeURLFrame()
flickerstreak@30: makeURLFrame = nil
flickerstreak@30: local function bumpFrameLevels(frame, amount)
flickerstreak@30: frame:SetFrameLevel(frame:GetFrameLevel()+amount)
flickerstreak@30: local children = newList(frame:GetChildren())
flickerstreak@30: for _,v in ipairs(children) do
flickerstreak@30: bumpFrameLevels(v, amount)
flickerstreak@30: end
flickerstreak@30: children = del(children)
flickerstreak@30: end
flickerstreak@30: -- some code borrowed from Prat here
flickerstreak@30: StaticPopupDialogs["ROCK_SHOW_URL"] = {
flickerstreak@30: text = not IsMacClient() and L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] or L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."],
flickerstreak@30: button2 = ACCEPT,
flickerstreak@30: hasEditBox = 1,
flickerstreak@30: hasWideEditBox = 1,
flickerstreak@30: showAlert = 1, -- HACK : it's the only way I found to make de StaticPopup have sufficient width to show WideEditBox :(
flickerstreak@30:
flickerstreak@30: OnShow = function()
flickerstreak@30: local editBox = _G[this:GetName() .. "WideEditBox"]
flickerstreak@30: editBox:SetText(url)
flickerstreak@30: editBox:SetFocus()
flickerstreak@30: editBox:HighlightText(0)
flickerstreak@30: editBox:SetScript("OnTextChanged", function() StaticPopup_EditBoxOnTextChanged() end)
flickerstreak@30:
flickerstreak@30: local button = _G[this:GetName() .. "Button2"]
flickerstreak@30: button:ClearAllPoints()
flickerstreak@30: button:SetWidth(200)
flickerstreak@30: button:SetPoint("CENTER", editBox, "CENTER", 0, -30)
flickerstreak@30:
flickerstreak@30: _G[this:GetName() .. "AlertIcon"]:Hide() -- HACK : we hide the false AlertIcon
flickerstreak@30: this:SetFrameStrata("FULLSCREEN_DIALOG")
flickerstreak@30: bumpFrameLevels(this, 30)
flickerstreak@30: end,
flickerstreak@30: OnHide = function()
flickerstreak@30: local editBox = _G[this:GetName() .. "WideEditBox"]
flickerstreak@30: editBox:SetScript("OnTextChanged", nil)
flickerstreak@30: this:SetFrameStrata("DIALOG")
flickerstreak@30: bumpFrameLevels(this, -30)
flickerstreak@30: end,
flickerstreak@30: OnAccept = function() end,
flickerstreak@30: OnCancel = function() end,
flickerstreak@30: EditBoxOnEscapePressed = function() this:GetParent():Hide() end,
flickerstreak@30: EditBoxOnTextChanged = function()
flickerstreak@30: this:SetText(url)
flickerstreak@30: this:SetFocus()
flickerstreak@30: this:HighlightText(0)
flickerstreak@30: end,
flickerstreak@30: timeout = 0,
flickerstreak@30: whileDead = 1,
flickerstreak@30: hideOnEscape = 1
flickerstreak@30: }
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: function OpenDonationFrame(self)
flickerstreak@30: if makeURLFrame then
flickerstreak@30: makeURLFrame()
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local donate = self.donate
flickerstreak@30: if type(donate) ~= "string" then
flickerstreak@30: donate = "Wowace"
flickerstreak@30: end
flickerstreak@30: local style, data = (":"):split(donate, 2)
flickerstreak@30: style = style:lower()
flickerstreak@30: if style ~= "website" and style ~= "paypal" then
flickerstreak@30: style = "wowace"
flickerstreak@30: end
flickerstreak@30: if style == "wowace" then
flickerstreak@30: url = "http://www.wowace.com/wiki/Donations"
flickerstreak@30: elseif style == "website" then
flickerstreak@30: url = data
flickerstreak@30: else -- PayPal
flickerstreak@30: local text = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" .. urlencode(unobfuscateEmail(data))
flickerstreak@30: local name
flickerstreak@30: if type(self.title) == "string" then
flickerstreak@30: name = self.title
flickerstreak@30: elseif type(self.name) == "string" then
flickerstreak@30: name = self.name
flickerstreak@30: end
flickerstreak@30: if name == MAJOR_VERSION then
flickerstreak@30: name = "Rock"
flickerstreak@30: end
flickerstreak@30: if name then
flickerstreak@30: name = name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "")
flickerstreak@30: text = text .. "&item_name=" .. urlencode(name)
flickerstreak@30: end
flickerstreak@30: url = text
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: StaticPopup_Show("ROCK_SHOW_URL")
flickerstreak@30: end
flickerstreak@30: function OpenIssueFrame(self)
flickerstreak@30: if makeURLFrame then
flickerstreak@30: makeURLFrame()
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local issueTracker = self.issueTracker
flickerstreak@30: if type(issueTracker) ~= "string" then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: local style, data = (":"):split(issueTracker, 2)
flickerstreak@30: style = style:lower()
flickerstreak@30: if style ~= "website" and style ~= "wowace" then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: if style == "wowace" then
flickerstreak@30: url = "http://jira.wowace.com/secure/CreateIssue.jspa?pid=" .. data
flickerstreak@30: elseif style == "website" then
flickerstreak@30: url = data
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: StaticPopup_Show("ROCK_SHOW_URL")
flickerstreak@30: end
flickerstreak@30: local function donate_hidden(addon)
flickerstreak@30: return type(addon.donate) ~= "string"
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function issue_hidden(addon)
flickerstreak@30: return type(addon.issueTracker) ~= "string"
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: -- #NODOC
flickerstreak@30: function Rock:GetRockConfigOptions(addon)
flickerstreak@30: return 'active', {
flickerstreak@30: type = 'boolean',
flickerstreak@30: name = L["Enabled"],
flickerstreak@30: desc = L["Enable or disable this addon."],
flickerstreak@30: get = 'IsActive',
flickerstreak@30: set = 'ToggleActive',
flickerstreak@30: handler = addon,
flickerstreak@30: order = -1,
flickerstreak@30: }, 'donate', {
flickerstreak@30: type = 'execute',
flickerstreak@30: name = L["Give donation"],
flickerstreak@30: buttonText = L["Donate"],
flickerstreak@30: desc = L["Give a much-needed donation to the author of this addon."],
flickerstreak@30: func = OpenDonationFrame,
flickerstreak@30: hidden = donate_hidden,
flickerstreak@30: passValue = addon,
flickerstreak@30: order = -2,
flickerstreak@30: }, 'issue', {
flickerstreak@30: type = 'execute',
flickerstreak@30: name = L["File issue"],
flickerstreak@30: buttonText = L["Report"],
flickerstreak@30: desc = L["File a bug or request a new feature or an improvement to this addon."],
flickerstreak@30: func = OpenIssueFrame,
flickerstreak@30: hidden = issue_hidden,
flickerstreak@30: passValue = addon,
flickerstreak@30: order = -3,
flickerstreak@30: }
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function initAddon(addon, name)
flickerstreak@30: name = addonToFolder[addon] or name or ""
flickerstreak@30: -- TOC checks
flickerstreak@30: if addon.title == nil then
flickerstreak@30: addon.title = GetAddOnMetadata(name, "Title")
flickerstreak@30: end
flickerstreak@30: if type(addon.title) == "string" then
flickerstreak@30: addon.title = addon.title:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):gsub("%-Rock%-$", ""):trim()
flickerstreak@30: end
flickerstreak@30: if addon.notes == nil then
flickerstreak@30: addon.notes = GetAddOnMetadata(name, "Notes")
flickerstreak@30: end
flickerstreak@30: if type(addon.notes) == "string" then
flickerstreak@30: addon.notes = addon.notes:trim()
flickerstreak@30: end
flickerstreak@30: if addon.version == nil then
flickerstreak@30: addon.version = GetAddOnMetadata(name, "Version")
flickerstreak@30: end
flickerstreak@30: if type(addon.version) == "string" then
flickerstreak@30: addon.version = addon.version:trim()
flickerstreak@30: end
flickerstreak@30: if addon.author == nil then
flickerstreak@30: addon.author = GetAddOnMetadata(name, "Author")
flickerstreak@30: end
flickerstreak@30: if type(addon.author) == "string" then
flickerstreak@30: addon.author = addon.author:trim()
flickerstreak@30: end
flickerstreak@30: if addon.credits == nil then
flickerstreak@30: addon.credits = GetAddOnMetadata(name, "X-Credits")
flickerstreak@30: end
flickerstreak@30: if type(addon.credits) == "string" then
flickerstreak@30: addon.credits = addon.credits:trim()
flickerstreak@30: end
flickerstreak@30: if addon.donate == nil then
flickerstreak@30: addon.donate = GetAddOnMetadata(name, "X-Donate")
flickerstreak@30: end
flickerstreak@30: if type(addon.donate) == "string" then
flickerstreak@30: addon.donate = addon.donate:trim()
flickerstreak@30: end
flickerstreak@30: if addon.issueTracker == nil then
flickerstreak@30: addon.issueTracker = GetAddOnMetadata(name, "X-IssueTracker")
flickerstreak@30: end
flickerstreak@30: if type(addon.issueTracker) == "string" then
flickerstreak@30: addon.issueTracker = addon.issueTracker:trim()
flickerstreak@30: end
flickerstreak@30: if addon.category == nil then
flickerstreak@30: addon.category = GetAddOnMetadata(name, "X-Category")
flickerstreak@30: end
flickerstreak@30: if type(addon.category) == "string" then
flickerstreak@30: addon.category = addon.category:trim()
flickerstreak@30: end
flickerstreak@30: if addon.email == nil then
flickerstreak@30: addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email")
flickerstreak@30: end
flickerstreak@30: if type(addon.email) == "string" then
flickerstreak@30: addon.email = addon.email:trim()
flickerstreak@30: end
flickerstreak@30: if addon.license == nil then
flickerstreak@30: addon.license = GetAddOnMetadata(name, "X-License")
flickerstreak@30: end
flickerstreak@30: if type(addon.license) == "string" then
flickerstreak@30: addon.license = addon.license:trim()
flickerstreak@30: end
flickerstreak@30: if addon.website == nil then
flickerstreak@30: addon.website = GetAddOnMetadata(name, "X-Website")
flickerstreak@30: end
flickerstreak@30: if type(addon.website) == "string" then
flickerstreak@30: addon.website = addon.website:trim()
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30: local mixin_OnEmbedInitialize = mixin.OnEmbedInitialize
flickerstreak@30: if mixin_OnEmbedInitialize then
flickerstreak@30: local success, ret = pcall(mixin_OnEmbedInitialize, mixin, addon)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local addon_OnInitialize = addon.OnInitialize
flickerstreak@30: if addon_OnInitialize then
flickerstreak@30: local success, ret = pcall(addon_OnInitialize, addon)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if LibRockEvent then
flickerstreak@30: Rock:DispatchEvent("AddonInitialized", addon)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30:
flickerstreak@30: local function manualEnable(addon)
flickerstreak@30: for i,v in ipairs(pendingAddons) do
flickerstreak@30: if v == addon then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if currentlyEnabledAddons[addon] then
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: currentlyEnabledAddons[addon] = true
flickerstreak@30:
flickerstreak@30: local first = not addonsAlreadyEnabled[addon]
flickerstreak@30: addonsAlreadyEnabled[addon] = true
flickerstreak@30:
flickerstreak@30: for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30: local mixin_OnEmbedEnable = mixin.OnEmbedEnable
flickerstreak@30: if mixin_OnEmbedEnable then
flickerstreak@30: local success, ret = pcall(mixin_OnEmbedEnable, mixin, addon, first)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: local addon_OnEnable = addon.OnEnable
flickerstreak@30: if addon_OnEnable then
flickerstreak@30: local success, ret = pcall(addon_OnEnable, addon, first)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if LibRockEvent then
flickerstreak@30: Rock:DispatchEvent("AddonEnabled", addon, first)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: return true, first
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function manualDisable(addon)
flickerstreak@30: if not currentlyEnabledAddons[addon] then
flickerstreak@30: return false
flickerstreak@30: end
flickerstreak@30: currentlyEnabledAddons[addon] = nil
flickerstreak@30:
flickerstreak@30: for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30: local mixin_OnEmbedDisable = mixin.OnEmbedDisable
flickerstreak@30: if mixin_OnEmbedDisable then
flickerstreak@30: local success, ret = pcall(mixin_OnEmbedDisable, mixin, addon)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: local addon_OnDisable = addon.OnDisable
flickerstreak@30: if addon_OnDisable then
flickerstreak@30: local success, ret = pcall(addon_OnDisable, addon)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if LibRockEvent then
flickerstreak@30: Rock:DispatchEvent("AddonDisabled", addon)
flickerstreak@30: end
flickerstreak@30: return true
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local function enableAddon(addon)
flickerstreak@30: for i,v in ipairs(pendingAddons) do
flickerstreak@30: if v == addon then
flickerstreak@30: return
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if addon_mt___index.IsActive(addon) then
flickerstreak@30: manualEnable(addon)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: -- #NODOC
flickerstreak@30: -- This is used by internal Rock libraries after updating the active state.
flickerstreak@30: function Rock:RecheckEnabledStates()
flickerstreak@30: local changed = false
flickerstreak@30: for _,addon in pairs(addons) do
flickerstreak@30: local good = true
flickerstreak@30: for _,a in ipairs(pendingAddonsEnable) do
flickerstreak@30: if addon == a then
flickerstreak@30: good = false
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if good then
flickerstreak@30: if addon_mt___index.IsActive(addon) then
flickerstreak@30: if manualEnable(addon) then
flickerstreak@30: changed = true
flickerstreak@30: end
flickerstreak@30: else
flickerstreak@30: if manualDisable(addon) then
flickerstreak@30: changed = true
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if changed then
flickerstreak@30: return self:RecheckEnabledStates()
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: frame:UnregisterAllEvents()
flickerstreak@30: frame:RegisterEvent("ADDON_LOADED")
flickerstreak@30: frame:RegisterEvent("PLAYER_LOGIN")
flickerstreak@30: local function runMainAddonLoadedChunk(name)
flickerstreak@30: local tmp = newList()
flickerstreak@30: tmp, pendingAddons = pendingAddons, tmp
flickerstreak@30: for i, addon in ipairs(tmp) do
flickerstreak@30: local folder = addonToFolder[addon]
flickerstreak@30: if name and folder and not foldersLoaded[folder] then
flickerstreak@30: for j = i, #tmp do
flickerstreak@30: pendingAddons[#pendingAddons+1] = tmp[j]
flickerstreak@30: tmp[j] = nil
flickerstreak@30: end
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: initAddon(addon, name)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if IsLoggedIn() then
flickerstreak@30: for i, addon in ipairs(tmp) do
flickerstreak@30: for j, v in ipairs(pendingAddonsEnable) do
flickerstreak@30: if v == addon then
flickerstreak@30: table_remove(pendingAddonsEnable, i)
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: enableAddon(addon)
flickerstreak@30: end
flickerstreak@30: for i, addon in ipairs(pendingAddonsEnable) do
flickerstreak@30: local good = true
flickerstreak@30: for j, v in ipairs(pendingAddons) do
flickerstreak@30: if v == addon then
flickerstreak@30: good = false
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if not good then
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: pendingAddonsEnable[i] = nil
flickerstreak@30: enableAddon(addon)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: tmp = del(tmp)
flickerstreak@30: for library, addonName in pairs(pendingLibraries) do
flickerstreak@30: if not name or foldersLoaded[addonName] then
flickerstreak@30: local success, ret = pcall(error, ("Library %q not finalized before ADDON_LOADED."):format(better_tostring(library)), 3)
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: Rock:FinalizeLibrary((library:GetLibraryVersion()))
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if isStandalone then
flickerstreak@30: local LibRock_1_0DB = _G.LibRock_1_0DB
flickerstreak@30: if type(LibRock_1_0DB) ~= "table" then
flickerstreak@30: LibRock_1_0DB = {}
flickerstreak@30: _G.LibRock_1_0DB = LibRock_1_0DB
flickerstreak@30: end
flickerstreak@30: if type(LibRock_1_0DB.unitTests) ~= "table" then
flickerstreak@30: LibRock_1_0DB.unitTests = {}
flickerstreak@30: end
flickerstreak@30: enableContracts = LibRock_1_0DB.contracts or false
flickerstreak@30: unitTestDB = LibRock_1_0DB.unitTests
flickerstreak@30: for namespace, data in pairs(unitTests) do
flickerstreak@30: if not unitTestDB[namespace] then
flickerstreak@30: if data then
flickerstreak@30: del(data)
flickerstreak@30: unitTests[namespace] = false
flickerstreak@30: end
flickerstreak@30: elseif data and (not name or data.addon == name) then
flickerstreak@30: local stats = newList()
flickerstreak@30: for i,v in ipairs(data) do
flickerstreak@30: data[i] = nil
flickerstreak@30:
flickerstreak@30: local libs = newList()
flickerstreak@30: for k,v in pairs(libraries) do
flickerstreak@30: libs[k] = v
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local success, ret = pcall(v)
flickerstreak@30: if not success then
flickerstreak@30: geterrorhandler()(ret)
flickerstreak@30: stats[i] = ret
flickerstreak@30: else
flickerstreak@30: stats[i] = false
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for k in pairs(libraries) do
flickerstreak@30: if not libs[k] then
flickerstreak@30: __removeLibrary(k)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: libs = del(libs)
flickerstreak@30:
flickerstreak@30: local lastCount
flickerstreak@30: repeat
flickerstreak@30: lastCount = collectgarbage('count')
flickerstreak@30: collectgarbage('collect')
flickerstreak@30: until lastCount == collectgarbage('count')
flickerstreak@30: end
flickerstreak@30: del(data)
flickerstreak@30: unitTests[namespace] = false
flickerstreak@30: if #stats >= 1 then
flickerstreak@30: local pass, fail = 0, 0
flickerstreak@30: for i,v in ipairs(stats) do
flickerstreak@30: if v then
flickerstreak@30: fail = fail + 1
flickerstreak@30: else
flickerstreak@30: pass = pass + 1
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local color
flickerstreak@30: if fail == 0 then
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(("|cff00ff00%s: %d unit test(s) passed."):format(namespace, pass))
flickerstreak@30: elseif pass > 0 then
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) passed, %d unit test(s) failed."):format(namespace, pass, fail))
flickerstreak@30: else
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) failed."):format(namespace, fail))
flickerstreak@30: end
flickerstreak@30: for i,v in ipairs(stats) do
flickerstreak@30: if v then
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s|r"):format(tostring(v)))
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if fail > 0 then
flickerstreak@30: _G.DEFAULT_CHAT_FRAME:AddMessage("|cffff0000----------|r")
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: stats = del(stats)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if isStandalone and name == MAJOR_VERSION then
flickerstreak@30: Rock("LibRockEvent-1.0", false, true) -- load if possible
flickerstreak@30: Rock("LibRockConsole-1.0", false, true) -- load if possible - I like the default chat commands
flickerstreak@30: Rock("LibRockComm-1.0", false, true) -- load if possible - has version checking and the like
flickerstreak@30: Rock("LibRockConfig-1.0", false, true) -- load if possible - LibRock-1.0 registers with it.
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: for major, library in LibStub:IterateLibraries() do
flickerstreak@30: manualFinalize(major, library)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: if IsLoggedIn() then
flickerstreak@30: collectgarbage('collect')
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: frame:Show()
flickerstreak@30: frame:SetScript("OnUpdate", function(this, elapsed)
flickerstreak@30: -- capture all un-initialized addons.
flickerstreak@30: runMainAddonLoadedChunk()
flickerstreak@30: collectgarbage('collect')
flickerstreak@30: this:SetScript("OnUpdate", run)
flickerstreak@30: end)
flickerstreak@30: frame:SetScript("OnEvent", function(this, event, ...)
flickerstreak@30: if event == "ADDON_LOADED" then
flickerstreak@30: -- this creates a new table and flushes the old in case someone LoDs an addon inside ADDON_LOADED.
flickerstreak@30: local name = ...
flickerstreak@30: foldersLoaded[name] = true
flickerstreak@30: runMainAddonLoadedChunk(name)
flickerstreak@30: frame:Show()
flickerstreak@30: elseif event == "PLAYER_LOGIN" then
flickerstreak@30: for i, addon in ipairs(pendingAddonsEnable) do
flickerstreak@30: local good = true
flickerstreak@30: for _, a in ipairs(pendingAddons) do
flickerstreak@30: if a == addon then
flickerstreak@30: good = false
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: if good then
flickerstreak@30: pendingAddonsEnable[i] = nil
flickerstreak@30: enableAddon(addon)
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: collectgarbage('collect')
flickerstreak@30: end
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:SetExportedMethods("SetExportedMethods", "Embed", "Unembed", "GetLibraryVersion")
flickerstreak@30:
flickerstreak@30: Rock:FinalizeLibrary(MAJOR_VERSION)
flickerstreak@30:
flickerstreak@30: for major, library in LibStub:IterateLibraries() do
flickerstreak@30: manualFinalize(major, library)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: -- test recycling
flickerstreak@30: local newList, newDict, newSet, del = Rock:GetRecyclingFunctions(MAJOR_VERSION .. "_UnitTest", "newList", "newDict", "newSet", "del", "Debug")
flickerstreak@30: local t = newList("Alpha", "Bravo", "Charlie")
flickerstreak@30: assert(t[1] == "Alpha")
flickerstreak@30: assert(t[2] == "Bravo")
flickerstreak@30: assert(t[3] == "Charlie")
flickerstreak@30: t = del(t)
flickerstreak@30: t = newList("Alpha", "Bravo", "Charlie")
flickerstreak@30: -- check recycled table
flickerstreak@30: assert(t[1] == "Alpha")
flickerstreak@30: assert(t[2] == "Bravo")
flickerstreak@30: assert(t[3] == "Charlie")
flickerstreak@30: t = del(t)
flickerstreak@30: t = newDict("Alpha", "Bravo", "Charlie", "Delta")
flickerstreak@30: assert(t.Alpha == "Bravo")
flickerstreak@30: assert(t.Charlie == "Delta")
flickerstreak@30: t = del(t)
flickerstreak@30: t = newSet("Alpha", "Bravo", "Charlie")
flickerstreak@30: assert(t.Alpha)
flickerstreak@30: assert(t.Bravo)
flickerstreak@30: assert(t.Charlie)
flickerstreak@30: t = del(t)
flickerstreak@30:
flickerstreak@30: local debug = recycleData.debugPools[MAJOR_VERSION .. "_UnitTest"]
flickerstreak@30: assert(debug.num == 0)
flickerstreak@30: t = newList()
flickerstreak@30: assert(debug.num == 1)
flickerstreak@30: t[1] = newList()
flickerstreak@30: assert(debug.num == 2)
flickerstreak@30: t[2] = newList()
flickerstreak@30: assert(debug.num == 3)
flickerstreak@30: t[1] = del(t[1])
flickerstreak@30: assert(debug.num == 2)
flickerstreak@30: t[2] = del(t[2])
flickerstreak@30: assert(debug.num == 1)
flickerstreak@30: t = del(t)
flickerstreak@30: assert(debug.num == 0)
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: -- test :GetUID()
flickerstreak@30: local t = {}
flickerstreak@30: for i = 1, 10000 do
flickerstreak@30: local uid = Rock:GetUID()
flickerstreak@30: if t[i] then
flickerstreak@30: error(("UID match for iteration %d, UID %s"):format(i, uid))
flickerstreak@30: end
flickerstreak@30: t[i] = true
flickerstreak@30: end
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: -- test basic creation and deletion
flickerstreak@30: assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30: assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30: local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30: lib = nil
flickerstreak@30: assert(LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30: assert(Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30: local good = false
flickerstreak@30: for _, lib in pairs(libraries) do
flickerstreak@30: if lib.name == "LibRockFakeLib-1.0" then
flickerstreak@30: good = true
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: assert(good)
flickerstreak@30: __removeLibrary("LibRockFakeLib-1.0")
flickerstreak@30: for _, lib in pairs(libraries) do
flickerstreak@30: assert(lib.name ~= "LibRockFakeLib-1.0")
flickerstreak@30: end
flickerstreak@30: assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30: assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: -- test library creation and the like
flickerstreak@30: assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30: for name in Rock:IterateLibraries() do
flickerstreak@30: assert(name ~= "LibRockFakeLib-1.0")
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local myLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30: assert(myLib)
flickerstreak@30: assert(myLib.name == "LibRockFakeLib-1.0")
flickerstreak@30: assert(not oldLib)
flickerstreak@30:
flickerstreak@30: assert(myLib:GetLibraryVersion() == "LibRockFakeLib-1.0")
flickerstreak@30: assert(select(2, myLib:GetLibraryVersion()) == 1)
flickerstreak@30:
flickerstreak@30: local good = false
flickerstreak@30: for name in Rock:IterateLibraries() do
flickerstreak@30: if name == "LibRockFakeLib-1.0" then
flickerstreak@30: good = true
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: assert(good)
flickerstreak@30: assert(Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30: assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30: assert(Rock("LibRockFakeLib-1.0") == myLib)
flickerstreak@30:
flickerstreak@30: assert(not Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30: function myLib:DoSomething()
flickerstreak@30: return "Something"
flickerstreak@30: end
flickerstreak@30: myLib:SetExportedMethods("DoSomething")
flickerstreak@30: assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30: local t = {}
flickerstreak@30: assert(not Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30: assert(not t.DoSomething)
flickerstreak@30: for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30: assert(false)
flickerstreak@30: end
flickerstreak@30: for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30: assert(false)
flickerstreak@30: end
flickerstreak@30: myLib:Embed(t)
flickerstreak@30: assert(t:DoSomething() == "Something")
flickerstreak@30: assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30: for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30: assert(mixin == myLib)
flickerstreak@30: end
flickerstreak@30: for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30: assert(object == t)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30:
flickerstreak@30: local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 2)
flickerstreak@30: assert(myNewLib == myLib)
flickerstreak@30: assert(oldLib)
flickerstreak@30: assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30:
flickerstreak@30: function myLib:DoSomething()
flickerstreak@30: return "Something else"
flickerstreak@30: end
flickerstreak@30: function myLib:TrySomething()
flickerstreak@30: return "Blah"
flickerstreak@30: end
flickerstreak@30: myLib:SetExportedMethods("DoSomething", "TrySomething")
flickerstreak@30: assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30: assert(t:DoSomething() == "Something else")
flickerstreak@30: assert(t:TrySomething() == "Blah")
flickerstreak@30: assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30: for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30: assert(mixin == myLib)
flickerstreak@30: end
flickerstreak@30: for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30: assert(object == t)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30:
flickerstreak@30: local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 3)
flickerstreak@30: assert(myNewLib == myLib)
flickerstreak@30: assert(oldLib)
flickerstreak@30: assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30:
flickerstreak@30: function myLib:DoSomething()
flickerstreak@30: return "Something"
flickerstreak@30: end
flickerstreak@30: myLib:SetExportedMethods("DoSomething")
flickerstreak@30: assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30: assert(t:DoSomething() == "Something")
flickerstreak@30: assert(t.TrySomething == nil)
flickerstreak@30: assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30: for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30: assert(mixin == myLib)
flickerstreak@30: end
flickerstreak@30: for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30: assert(object == t)
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30:
flickerstreak@30: assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 2)) -- out of date
flickerstreak@30: assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 3)) -- same revision
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: assert(not Rock:HasAddon("RockFakeAddon"))
flickerstreak@30: for name in Rock:IterateAddons() do
flickerstreak@30: assert(name ~= "RockFakeAddon")
flickerstreak@30: end
flickerstreak@30:
flickerstreak@30: local myAddon = Rock:NewAddon("RockFakeAddon")
flickerstreak@30:
flickerstreak@30: assert(myAddon)
flickerstreak@30: assert(myAddon.name == "RockFakeAddon")
flickerstreak@30:
flickerstreak@30: local good = false
flickerstreak@30: for name in Rock:IterateAddons() do
flickerstreak@30: if name == "RockFakeAddon" then
flickerstreak@30: good = true
flickerstreak@30: break
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: assert(good)
flickerstreak@30: assert(Rock:HasAddon("RockFakeAddon"))
flickerstreak@30: assert(Rock:GetAddon("RockFakeAddon") == myAddon)
flickerstreak@30: end)
flickerstreak@30:
flickerstreak@30: Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30: -- test :OnLibraryLoad
flickerstreak@30: local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30: local triggered = false
flickerstreak@30: function lib:OnLibraryLoad(major, instance)
flickerstreak@30: if major == "LibRockFakeLib-2.0" then
flickerstreak@30: triggered = true
flickerstreak@30: end
flickerstreak@30: end
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30:
flickerstreak@30: local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 1)
flickerstreak@30: assert(not triggered)
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-2.0")
flickerstreak@30: assert(triggered)
flickerstreak@30: triggered = false
flickerstreak@30: local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 2)
flickerstreak@30: assert(not triggered)
flickerstreak@30: Rock:FinalizeLibrary("LibRockFakeLib-2.0")
flickerstreak@30: assert(not triggered)
flickerstreak@30: end)