Include Blizzard_APIDocumentation and Search API Button to Code Editor with Wrath Classic Data (#57)
This commit is contained in:
@@ -0,0 +1,404 @@
|
||||
local addonName, Private = ...
|
||||
|
||||
APIDocumentationMixin = {};
|
||||
|
||||
-- "public"
|
||||
function APIDocumentationMixin:OnLoad()
|
||||
self.tables = {};
|
||||
self.functions = {};
|
||||
self.systems = {};
|
||||
self.fields = {};
|
||||
self.events = {};
|
||||
self.callbacks = {};
|
||||
|
||||
self.Commands = {
|
||||
Default = 1,
|
||||
CopyAPI = 2,
|
||||
OpenDump = 3,
|
||||
};
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:HandleSlashCommand(command)
|
||||
local commands = { (" "):split(command) };
|
||||
|
||||
if commands[1] == "?" or commands[1] == "help" or commands[1] == "" then
|
||||
self:OutputUsage();
|
||||
elseif commands[1] == "stats" then
|
||||
self:OutputStats();
|
||||
elseif commands[1] == "system" then
|
||||
if commands[2] == "list" then
|
||||
self:OutputAllSystems();
|
||||
else
|
||||
self:OutputUsage();
|
||||
end
|
||||
elseif commands[1] == "s" or commands[1] == "search" then
|
||||
self:OutputAllAPIMatches(unpack(commands, 2));
|
||||
elseif commands[1] then
|
||||
self:TryHandlingSystemSearchCommand(unpack(commands));
|
||||
else
|
||||
self:OutputUsage();
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:HandleAPILink(link, command)
|
||||
local _, type, name, parentName = (":"):split(link);
|
||||
local apiInfo = self:FindAPIByName(type, name, parentName);
|
||||
if apiInfo then
|
||||
if command == self.Commands.CopyAPI then
|
||||
self:HandleCopyAPI(apiInfo);
|
||||
elseif command == self.Commands.OpenDump then
|
||||
self:HandleOpenDump(apiInfo);
|
||||
else
|
||||
self:HandleDefaultCommand(apiInfo);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:HandleDefaultCommand(apiInfo)
|
||||
self:WriteLine(" ");
|
||||
self:WriteAllLines(apiInfo:GetDetailedOutputLines());
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:HandleCopyAPI(apiInfo)
|
||||
local clipboardString = apiInfo:GetClipboardString();
|
||||
if CopyToClipboard then
|
||||
CopyToClipboard(clipboardString);
|
||||
end
|
||||
self:WriteLineF("Copied to clipboard: %s", clipboardString);
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:HandleOpenDump(apiInfo)
|
||||
if apiInfo.Type == "Function" then
|
||||
local dumpString;
|
||||
local systemNamespace = apiInfo.System and apiInfo.System:GetNamespaceName() or nil;
|
||||
if systemNamespace and systemNamespace ~= "" then
|
||||
dumpString = ("/dump %s.%s()"):format(systemNamespace, apiInfo.Name);
|
||||
else
|
||||
dumpString = ("/dump %s()"):format(apiInfo.Name);
|
||||
end
|
||||
|
||||
local desiredCursorPosition = #dumpString - 1;
|
||||
ChatFrame_OpenChat(dumpString, nil, desiredCursorPosition);
|
||||
else
|
||||
self:WriteLine("Can only /dump functions");
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:FindAPIByName(apiType, name, parentName)
|
||||
local apiTable = self:GetAPITableByTypeName(apiType);
|
||||
if apiTable then
|
||||
for i, apiInfo in ipairs(apiTable) do
|
||||
if apiInfo:MatchesName(name, parentName) then
|
||||
return apiInfo;
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:GetAPITableByTypeName(apiType)
|
||||
if apiType == "function" then
|
||||
return self.functions;
|
||||
elseif apiType == "table" then
|
||||
return self.tables;
|
||||
elseif apiType == "system" then
|
||||
return self.systems;
|
||||
elseif apiType == "field" then
|
||||
return self.fields;
|
||||
elseif apiType == "event" then
|
||||
return self.events;
|
||||
elseif apiType == "callback" then
|
||||
return self.callbacks;
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputUsage()
|
||||
self:WriteLine("Usage:");
|
||||
|
||||
self:WriteLine("Search for API");
|
||||
self:WriteLine(self:GetIndentString() .. "/api search <api name>");
|
||||
self:WriteLine(self:GetIndentString() .. "or");
|
||||
self:WriteLine(self:GetIndentString() .. "/api s <api name>");
|
||||
self:WriteLine(self:GetIndentString() .. "Example: /api search item");
|
||||
self:WriteLine(" ");
|
||||
|
||||
self:WriteLine("List all systems");
|
||||
self:WriteLine(self:GetIndentString() .. "/api system list");
|
||||
self:WriteLine(" ");
|
||||
|
||||
self:WriteLine("Search system for API");
|
||||
self:WriteLine(self:GetIndentString() .. "/api <system name> search <api name>");
|
||||
self:WriteLine(self:GetIndentString() .. "or");
|
||||
self:WriteLine(self:GetIndentString() .. "/api <system name> s <api name>");
|
||||
self:WriteLine(self:GetIndentString() .. "Example: /api artifactui search relic");
|
||||
self:WriteLine(" ");
|
||||
|
||||
self:WriteLine("List all API in a system");
|
||||
self:WriteLine(self:GetIndentString() .. "/api <system name> list");
|
||||
self:WriteLine(self:GetIndentString() .. "Example: /api artifactui list");
|
||||
self:WriteLine(" ");
|
||||
self:WriteLine("All searches support Lua patterns.");
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputStats()
|
||||
self:WriteLine("Stats:");
|
||||
self:WriteLineF("Total systems: %d", #self.systems);
|
||||
local totalFunctions = 0;
|
||||
local totalEvents = 0;
|
||||
local totalTables = 0;
|
||||
|
||||
for i, systemInfo in ipairs(self.systems) do
|
||||
totalFunctions = totalFunctions + systemInfo:GetNumFunctions();
|
||||
totalEvents = totalEvents + systemInfo:GetNumEvents();
|
||||
totalTables = totalTables + systemInfo:GetNumTables();
|
||||
end
|
||||
|
||||
self:WriteLineF("Total functions: %d", totalFunctions);
|
||||
self:WriteLineF("Total events: %d", totalEvents);
|
||||
self:WriteLineF("Total tables: %d", totalTables);
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputAllSystems()
|
||||
self:WriteLineF("All systems (%d):", #self.systems);
|
||||
for i, systemInfo in ipairs(self.systems) do
|
||||
self:WriteLine(systemInfo:GetSingleOutputLine());
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:TryHandlingSystemSearchCommand(systemName, subCommand, apiToSearchFor)
|
||||
local system = self:FindSystemByName(systemName);
|
||||
if system then
|
||||
if subCommand == nil then
|
||||
self:WriteLine(system:GetSingleOutputLine());
|
||||
elseif subCommand == "s" or subCommand == "search" and apiToSearchFor then
|
||||
self:OutputAllSystemAPIMatches(system, apiToSearchFor);
|
||||
elseif subCommand == "list" then
|
||||
self:OutputAllSystemAPI(system);
|
||||
else
|
||||
self:OutputUsage();
|
||||
end
|
||||
else
|
||||
self:WriteLineF("No system found (%s)", tostring(systemName));
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputAPIMatches(apiMatches, headerName)
|
||||
if apiMatches and #apiMatches > 0 then
|
||||
self:WriteLineF("Found %d %s", #apiMatches, headerName);
|
||||
for i, api in ipairs(apiMatches) do
|
||||
self:WriteLine(self:GetIndentString() .. api:GetSingleOutputLine());
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputAllAPIMatches(apiToSearchFor)
|
||||
if not apiToSearchFor or apiToSearchFor == "" then
|
||||
self:OutputUsage();
|
||||
return;
|
||||
end
|
||||
self:WriteLine(" ");
|
||||
|
||||
local apiMatches = self:FindAllAPIMatches(apiToSearchFor);
|
||||
if apiMatches then
|
||||
local total = #apiMatches.tables + #apiMatches.functions + #apiMatches.events + #apiMatches.systems + #apiMatches.callbacks;
|
||||
assert(total > 0);
|
||||
self:WriteLineF("Found %d API that matches %q", total, apiToSearchFor);
|
||||
|
||||
self:OutputAPIMatches(apiMatches.systems, "system(s)");
|
||||
self:OutputAPIMatches(apiMatches.functions, "function(s)");
|
||||
self:OutputAPIMatches(apiMatches.events, "events(s)");
|
||||
self:OutputAPIMatches(apiMatches.tables, "table(s)");
|
||||
self:OutputAPIMatches(apiMatches.callbacks, "callback(s)");
|
||||
else
|
||||
self:WriteLineF("No API found that matches %q", apiToSearchFor);
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputAllSystemAPIMatches(system, apiToSearchFor)
|
||||
local apiMatches = system:FindAllAPIMatches(apiToSearchFor);
|
||||
if apiMatches then
|
||||
local total = #apiMatches.tables + #apiMatches.functions + #apiMatches.events;
|
||||
assert(total > 0);
|
||||
self:WriteLineF("Found %d API that matches %q", total, apiToSearchFor);
|
||||
|
||||
self:OutputAPIMatches(apiMatches.functions, "function(s)");
|
||||
self:OutputAPIMatches(apiMatches.events, "events(s)");
|
||||
self:OutputAPIMatches(apiMatches.tables, "table(s)");
|
||||
else
|
||||
self:WriteLineF("No API found that matches %q in %s", apiToSearchFor, system:GenerateAPILink());
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:OutputAllSystemAPI(system)
|
||||
local apiMatches = system:ListAllAPI();
|
||||
if apiMatches then
|
||||
self:WriteLineF("All API in %s", system:GenerateAPILink());
|
||||
|
||||
self:OutputAPIMatches(apiMatches.functions, "function(s)");
|
||||
self:OutputAPIMatches(apiMatches.events, "events(s)");
|
||||
self:OutputAPIMatches(apiMatches.tables, "table(s)");
|
||||
else
|
||||
self:WriteLineF("No API found in %s", system:GenerateAPILink());
|
||||
end
|
||||
end
|
||||
|
||||
--[[static]] function APIDocumentationMixin:AddAllMatches(apiContainer, matchesContainer, apiToSearchFor)
|
||||
for i, apiInfo in ipairs(apiContainer) do
|
||||
if apiInfo:MatchesSearchString(apiToSearchFor) then
|
||||
table.insert(matchesContainer, apiInfo);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:FindAllAPIMatches(apiToSearchFor)
|
||||
apiToSearchFor = apiToSearchFor:lower();
|
||||
|
||||
local matches = {
|
||||
tables = {},
|
||||
functions = {},
|
||||
events = {},
|
||||
systems = {},
|
||||
callbacks = {},
|
||||
};
|
||||
|
||||
self:AddAllMatches(self.tables, matches.tables, apiToSearchFor);
|
||||
self:AddAllMatches(self.functions, matches.functions, apiToSearchFor);
|
||||
self:AddAllMatches(self.systems, matches.systems, apiToSearchFor);
|
||||
self:AddAllMatches(self.events, matches.events, apiToSearchFor);
|
||||
self:AddAllMatches(self.callbacks, matches.callbacks, apiToSearchFor);
|
||||
|
||||
-- Only return something if we matched anything
|
||||
for name, subTable in pairs(matches) do
|
||||
if #subTable > 0 then
|
||||
return matches;
|
||||
end
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:FindSystemByName(systemName)
|
||||
systemName = systemName:lower();
|
||||
for i, systemInfo in ipairs(self.systems) do
|
||||
if systemInfo:MatchesNameCaseInsenstive(systemName) then
|
||||
return systemInfo;
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
local j = 1
|
||||
function APIDocumentationMixin:AddDocumentationTable(documentationInfo)
|
||||
j = j + 1
|
||||
if documentationInfo.Name then
|
||||
self:AddSystem(documentationInfo);
|
||||
else
|
||||
for i, tableInfo in ipairs(documentationInfo.Tables) do
|
||||
self:AddTable(tableInfo);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:WriteLine(message)
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
local info = ChatTypeInfo["SYSTEM"];
|
||||
DEFAULT_CHAT_FRAME:AddMessage(message, info.r, info.g, info.b, info.id);
|
||||
else
|
||||
print(message);
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:WriteLineF(format, ...)
|
||||
self:WriteLine(format:format(...));
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:WriteAllLines(lines)
|
||||
for i, line in ipairs(lines) do
|
||||
self:WriteLine(line);
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:GetIndentString(numIndent)
|
||||
return (" "):rep(numIndent or 1);
|
||||
end
|
||||
|
||||
-- "private"
|
||||
function APIDocumentationMixin:AddTable(documentationInfo)
|
||||
Private.Mixin(documentationInfo, TablesAPIMixin);
|
||||
|
||||
table.insert(self.tables, documentationInfo);
|
||||
|
||||
if documentationInfo.Fields then
|
||||
for i, field in ipairs(documentationInfo.Fields) do
|
||||
field.Table = documentationInfo;
|
||||
self:AddField(field);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:AddFunction(documentationInfo)
|
||||
Private.Mixin(documentationInfo, FunctionsAPIMixin);
|
||||
|
||||
table.insert(self.functions, documentationInfo);
|
||||
|
||||
if documentationInfo.Arguments then
|
||||
for i, field in ipairs(documentationInfo.Arguments) do
|
||||
field.Function = documentationInfo;
|
||||
self:AddField(field);
|
||||
end
|
||||
end
|
||||
|
||||
if documentationInfo.Returns then
|
||||
for i, field in ipairs(documentationInfo.Returns) do
|
||||
field.Function = documentationInfo;
|
||||
self:AddField(field);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:AddEvent(documentationInfo)
|
||||
Private.Mixin(documentationInfo, EventsAPIMixin);
|
||||
|
||||
table.insert(self.events, documentationInfo);
|
||||
|
||||
if documentationInfo.Payload then
|
||||
for i, field in ipairs(documentationInfo.Payload) do
|
||||
field.Event = documentationInfo;
|
||||
self:AddField(field);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:AddField(documentationInfo)
|
||||
Private.Mixin(documentationInfo, FieldsAPIMixin);
|
||||
|
||||
table.insert(self.fields, documentationInfo);
|
||||
end
|
||||
|
||||
function APIDocumentationMixin:AddSystem(documentationInfo)
|
||||
Private.Mixin(documentationInfo, SystemsAPIMixin);
|
||||
|
||||
table.insert(self.systems, documentationInfo);
|
||||
|
||||
for i, functionInfo in ipairs(documentationInfo.Functions) do
|
||||
functionInfo.System = documentationInfo;
|
||||
self:AddFunction(functionInfo);
|
||||
end
|
||||
|
||||
for i, eventInfo in ipairs(documentationInfo.Events) do
|
||||
eventInfo.System = documentationInfo;
|
||||
self:AddEvent(eventInfo);
|
||||
end
|
||||
|
||||
for i, tableInfo in ipairs(documentationInfo.Tables) do
|
||||
tableInfo.System = documentationInfo;
|
||||
self:AddTable(tableInfo);
|
||||
end
|
||||
end
|
||||
|
||||
APIDocumentation = Private.CreateFromMixins(APIDocumentationMixin);
|
||||
APIDocumentation:OnLoad();
|
||||
|
||||
SLASH_API1 = '/api'
|
||||
SlashCmdList["API"] = function(msg) APIDocumentation:HandleSlashCommand(msg) end
|
||||
Reference in New Issue
Block a user