summaryrefslogtreecommitdiffstats
path: root/MCServer/Plugins/InfoDump.lua
diff options
context:
space:
mode:
Diffstat (limited to 'MCServer/Plugins/InfoDump.lua')
-rw-r--r--MCServer/Plugins/InfoDump.lua449
1 files changed, 397 insertions, 52 deletions
diff --git a/MCServer/Plugins/InfoDump.lua b/MCServer/Plugins/InfoDump.lua
index df47d566b..c61f9c9e6 100644
--- a/MCServer/Plugins/InfoDump.lua
+++ b/MCServer/Plugins/InfoDump.lua
@@ -2,10 +2,17 @@
-- InfoDump.lua
--- Goes through all subfolders, loads Info.lua and dumps its g_PluginInfo into various text formats
--- This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
+--[[
+Loads plugins' Info.lua and dumps its g_PluginInfo into various text formats
+This is used for generating plugin documentation for the forum and for GitHub's INFO.md files
--- This script requires LuaRocks with LFS installed, instructions are printed when this is not present.
+This script can be used in two ways:
+Executing "lua InfoDump.lua" will go through all subfolders and dump each Info.lua file it can find
+ Note that this mode of operation requires LuaRocks with LFS installed; instructions are printed
+ when the prerequisites are not met.
+Executing "lua InfoDump.lua PluginName" will load the Info.lua file from PluginName's folder and dump
+only that one plugin's documentation. This mode of operation doesn't require LuaRocks
+--]]
@@ -17,33 +24,6 @@ if (_VERSION ~= "Lua 5.1") then
return;
end
--- Try to load lfs, do not abort if not found
-local lfs, err = pcall(
- function()
- return require("lfs")
- end
-);
-
--- Rather, print a nice message with instructions:
-if not(lfs) then
- print([[
-Cannot load LuaFileSystem
-Install it through luarocks by executing the following command:
- sudo luarocks install luafilesystem
-
-If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
- sudo apt-get install luarocks
-On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
-]]);
-
- print("Original error text: ", err);
- return;
-end
-
--- We now know that LFS is present, get it normally:
-lfs = require("lfs");
-
-
@@ -89,6 +69,47 @@ end
+--- Replaces generic formatting with forum-specific formatting
+-- Also removes the single line-ends
+local function GithubizeString(a_Str)
+ assert(type(a_Str) == "string");
+
+ -- Remove the indentation, unless in the code tag:
+ -- Only one code or /code tag per line is supported!
+ local IsInCode = false;
+ local function RemoveIndentIfNotInCode(s)
+ if (IsInCode) then
+ -- we're in code section, check if this line terminates it
+ IsInCode = (s:find("{%%/code}") ~= nil);
+ return s .. "\n";
+ else
+ -- we're not in code section, check if this line starts it
+ IsInCode = (s:find("{%%code}") ~= nil);
+ return s:gsub("^%s*", "") .. "\n";
+ end
+ end
+ a_Str = a_Str:gsub("(.-)\n", RemoveIndentIfNotInCode);
+
+ -- Replace multiple line ends with {%p} and single line ends with a space,
+ -- so that manual word-wrap in the Info.lua file doesn't wrap in the forum.
+ a_Str = a_Str:gsub("\n\n", "{%%p}");
+ a_Str = a_Str:gsub("\n", " ");
+
+ -- Replace the generic formatting:
+ a_Str = a_Str:gsub("{%%p}", "\n\n");
+ a_Str = a_Str:gsub("{%%b}", "**"):gsub("{%%/b}", "**");
+ a_Str = a_Str:gsub("{%%i}", "*"):gsub("{%%/i}", "*");
+ a_Str = a_Str:gsub("{%%list}", ""):gsub("{%%/list}", "");
+ a_Str = a_Str:gsub("{%%li}", " - "):gsub("{%%/li}", "");
+ -- TODO: Other formatting
+
+ return a_Str;
+end
+
+
+
+
+
--- Builds an array of categories, each containing all the commands belonging to the category,
-- and the category description, if available.
-- Returns the array table, each item has the following format:
@@ -161,6 +182,43 @@ end
+--- Returns a string specifying the command.
+-- If a_Command is a simple string, returns a_Command colorized to blue
+-- If a_Command is a table, expects members Name (full command name) and Params (command parameters),
+-- colorizes command name blue and params green
+local function GetCommandRefForum(a_Command)
+ if (type(a_Command) == "string") then
+ return "[color=blue]" .. a_Command .. "[/color]";
+ end
+ return "[color=blue]" .. a_Command.Name .. "[/color] [color=green]" .. (a_Command.Params or "") .. "[/color]";
+end
+
+
+
+
+
+--- Returns a string specifying the command.
+-- If a_CommandParams is nil, returns a_CommandName apostrophed
+-- If a_CommandParams is a string, apostrophes a_CommandName with a_CommandParams
+local function GetCommandRefGithub(a_CommandName, a_CommandParams)
+ assert(type(a_CommandName) == "string");
+ if (a_CommandParams == nil) then
+ return "`" .. a_CommandName .. "`";
+ end
+
+ assert(type(a_CommandParams) == "table");
+ if ((a_CommandParams.Params == nil) or (a_CommandParams.Params == "")) then
+ return "`" .. a_CommandName .. "`";
+ end
+
+ assert(type(a_CommandParams.Params) == "string");
+ return "`" .. a_CommandName .. " " .. a_CommandParams.Params .. "`";
+end
+
+
+
+
+
--- Writes the specified command detailed help array to the output file, in the forum dump format
local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCombinations, f)
assert(type(a_CmdString) == "string");
@@ -174,7 +232,7 @@ local function WriteCommandParameterCombinationsForum(a_CmdString, a_ParameterCo
f:write("The following parameter combinations are recognized:\n");
for idx, combination in ipairs(a_ParameterCombinations) do
- f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params, "[/color]");
+ f:write("[color=blue]", a_CmdString, "[/color] [color=green]", combination.Params or "", "[/color]");
if (combination.Help ~= nil) then
f:write(" - ", ForumizeString(combination.Help));
end
@@ -189,6 +247,34 @@ end
+--- Writes the specified command detailed help array to the output file, in the forum dump format
+local function WriteCommandParameterCombinationsGithub(a_CmdString, a_ParameterCombinations, f)
+ assert(type(a_CmdString) == "string");
+ assert(type(a_ParameterCombinations) == "table");
+ assert(f ~= nil);
+
+ if (#a_ParameterCombinations == 0) then
+ -- No explicit parameter combinations to write
+ return;
+ end
+
+ f:write("The following parameter combinations are recognized:\n\n");
+ for idx, combination in ipairs(a_ParameterCombinations) do
+ f:write(GetCommandRefGithub(a_CmdString, combination));
+ if (combination.Help ~= nil) then
+ f:write(" - ", GithubizeString(combination.Help));
+ end
+ if (combination.Permission ~= nil) then
+ f:write(" (Requires permission '**", combination.Permission, "**')");
+ end
+ f:write("\n");
+ end
+end
+
+
+
+
+
--- Writes all commands in the specified category to the output file, in the forum dump format
local function WriteCommandsCategoryForum(a_Category, f)
-- Write category name:
@@ -211,7 +297,7 @@ local function WriteCommandsCategoryForum(a_Category, f)
f:write("Permission required: [color=red]", cmd.Info.Permission, "[/color]\n");
end
if (cmd.Info.DetailedDescription ~= nil) then
- f:write(cmd.Info.DetailedDescription);
+ f:write(ForumizeString(cmd.Info.DetailedDescription));
end
if (cmd.Info.ParameterCombinations ~= nil) then
WriteCommandParameterCombinationsForum(cmd.CommandString, cmd.Info.ParameterCombinations, f);
@@ -224,6 +310,34 @@ end
+--- Writes all commands in the specified category to the output file, in the Github dump format
+local function WriteCommandsCategoryGithub(a_Category, f)
+ -- Write category name:
+ local CategoryName = a_Category.Name;
+ if (CategoryName == "") then
+ CategoryName = "General";
+ end
+ f:write("\n### ", GithubizeString(a_Category.DisplayName or CategoryName), "\n");
+
+ -- Write description:
+ if (a_Category.Description ~= "") then
+ f:write(GithubizeString(a_Category.Description), "\n\n");
+ end
+
+ f:write("| Command | Permission | Description | \n")
+ f:write("| ------- | ---------- | ----------- | \n")
+
+ -- Write commands:
+ for idx2, cmd in ipairs(a_Category.Commands) do
+ f:write("|", cmd.CommandString, " | ", cmd.Info.Permission or "", " | ", GithubizeString(cmd.Info.HelpString or "UNDOCUMENTED"), "| \n")
+ end
+ f:write("\n\n")
+end
+
+
+
+
+
local function DumpCommandsForum(a_PluginInfo, f)
-- Copy all Categories from a dictionary into an array:
local Categories = BuildCategories(a_PluginInfo);
@@ -251,9 +365,36 @@ end
+local function DumpCommandsGithub(a_PluginInfo, f)
+ -- Copy all Categories from a dictionary into an array:
+ local Categories = BuildCategories(a_PluginInfo);
+
+ -- Sort the categories by name:
+ table.sort(Categories,
+ function(cat1, cat2)
+ return (string.lower(cat1.Name) < string.lower(cat2.Name));
+ end
+ );
+
+ if (#Categories == 0) then
+ return;
+ end
+
+ f:write("\n# Commands\n");
+
+ -- Dump per-category commands:
+ for idx, cat in ipairs(Categories) do
+ WriteCommandsCategoryGithub(cat, f);
+ end
+end
+
+
+
+
+
local function DumpAdditionalInfoForum(a_PluginInfo, f)
local AInfo = a_PluginInfo.AdditionalInfo;
- if ((AInfo == nil) or (type(AInfo) ~= "table")) then
+ if (type(AInfo) ~= "table") then
-- There is no AdditionalInfo in a_PluginInfo
return;
end
@@ -270,6 +411,153 @@ end
+local function DumpAdditionalInfoGithub(a_PluginInfo, f)
+ local AInfo = a_PluginInfo.AdditionalInfo;
+ if (type(AInfo) ~= "table") then
+ -- There is no AdditionalInfo in a_PluginInfo
+ return;
+ end
+
+ for idx, info in ipairs(a_PluginInfo.AdditionalInfo) do
+ if ((info.Title ~= nil) and (info.Contents ~= nil)) then
+ f:write("\n# ", GithubizeString(info.Title), "\n");
+ f:write(GithubizeString(info.Contents), "\n");
+ end
+ end
+end
+
+
+
+
+
+--- Collects all permissions mentioned in the info, returns them as a sorted array
+-- Each array item is {Name = "PermissionName", Info = { PermissionInfo }}
+local function BuildPermissions(a_PluginInfo)
+ -- Collect all used permissions from Commands, reference the commands that use the permission:
+ local Permissions = a_PluginInfo.Permissions or {};
+ local function CollectPermissions(a_CmdPrefix, a_Commands)
+ for cmd, info in pairs(a_Commands) do
+ CommandString = a_CmdPrefix .. cmd;
+ if ((info.Permission ~= nil) and (info.Permission ~= "")) then
+ -- Add the permission to the list of permissions:
+ local Permission = Permissions[info.Permission] or {};
+ Permissions[info.Permission] = Permission;
+ -- Add the command to the list of commands using this permission:
+ Permission.CommandsAffected = Permission.CommandsAffected or {};
+ table.insert(Permission.CommandsAffected, CommandString);
+ end
+
+ -- Process the command param combinations for permissions:
+ local ParamCombinations = info.ParameterCombinations or {};
+ for idx, comb in ipairs(ParamCombinations) do
+ if ((comb.Permission ~= nil) and (comb.Permission ~= "")) then
+ -- Add the permission to the list of permissions:
+ local Permission = Permissions[comb.Permission] or {};
+ Permissions[info.Permission] = Permission;
+ -- Add the command to the list of commands using this permission:
+ Permission.CommandsAffected = Permission.CommandsAffected or {};
+ table.insert(Permission.CommandsAffected, {Name = CommandString, Params = comb.Params});
+ end
+ end
+
+ -- Process subcommands:
+ if (info.Subcommands ~= nil) then
+ CollectPermissions(CommandString .. " ", info.Subcommands);
+ end
+ end
+ end
+ CollectPermissions("", a_PluginInfo.Commands);
+
+ -- Copy the list of permissions to an array:
+ local PermArray = {};
+ for name, perm in pairs(Permissions) do
+ table.insert(PermArray, {Name = name, Info = perm});
+ end
+
+ -- Sort the permissions array:
+ table.sort(PermArray,
+ function(p1, p2)
+ return (p1.Name < p2.Name);
+ end
+ );
+ return PermArray;
+end
+
+
+
+
+
+local function DumpPermissionsForum(a_PluginInfo, f)
+ -- Get the processed sorted array of permissions:
+ local Permissions = BuildPermissions(a_PluginInfo);
+ if ((Permissions == nil) or (#Permissions <= 0)) then
+ return;
+ end
+
+ -- Dump the permissions:
+ f:write("\n[size=X-Large]Permissions[/size]\n[list]\n");
+ for idx, perm in ipairs(Permissions) do
+ f:write(" - [color=red]", perm.Name, "[/color] - ");
+ f:write(ForumizeString(perm.Info.Description or ""));
+ local CommandsAffected = perm.Info.CommandsAffected or {};
+ if (#CommandsAffected > 0) then
+ f:write("\n[list] Commands affected:\n- ");
+ local Affects = {};
+ for idx2, cmd in ipairs(CommandsAffected) do
+ table.insert(Affects, GetCommandRefForum(cmd));
+ end
+ f:write(table.concat(Affects, "\n - "));
+ f:write("\n[/list]");
+ end
+ if (perm.Info.RecommendedGroups ~= nil) then
+ f:write("\n[list] Recommended groups: ", perm.Info.RecommendedGroups, "[/list]");
+ end
+ f:write("\n");
+ end
+ f:write("[/list]");
+end
+
+
+
+
+
+local function DumpPermissionsGithub(a_PluginInfo, f)
+ -- Get the processed sorted array of permissions:
+ local Permissions = BuildPermissions(a_PluginInfo);
+ if ((Permissions == nil) or (#Permissions <= 0)) then
+ return;
+ end
+
+ -- Dump the permissions:
+ f:write("\n# Permissions\n");
+ f:write("| Permissions | Description | Commands | Recommended groups |\n")
+ f:write("| ----------- | ----------- | -------- | ------------------ |\n")
+ for idx, perm in ipairs(Permissions) do
+ f:write(perm.Name, " | ");
+ f:write(GithubizeString(perm.Info.Description or ""), " | ");
+ local CommandsAffected = perm.Info.CommandsAffected or {};
+ if (#CommandsAffected > 0) then
+ local Affects = {};
+ for idx2, cmd in ipairs(CommandsAffected) do
+ if (type(cmd) == "string") then
+ table.insert(Affects, GetCommandRefGithub(cmd));
+ else
+ table.insert(Affects, GetCommandRefGithub(cmd.Name, cmd));
+ end
+ end
+ f:write(table.concat(Affects, ", "), " | ");
+ end
+ if (perm.Info.RecommendedGroups ~= nil) then
+ f:write(perm.Info.RecommendedGroups, " |");
+ end
+ f:write("\n");
+ end
+end
+
+
+
+
+
local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
-- Open the output file:
local f, msg = io.open(a_PluginInfo.Name .. "_forum.txt", "w");
@@ -282,7 +570,11 @@ local function DumpPluginInfoForum(a_PluginFolder, a_PluginInfo)
f:write(ForumizeString(a_PluginInfo.Description), "\n");
DumpAdditionalInfoForum(a_PluginInfo, f);
DumpCommandsForum(a_PluginInfo, f);
-
+ DumpPermissionsForum(a_PluginInfo, f);
+ if (a_PluginInfo.SourceLocation ~= nil) then
+ f:write("[b][color=blue]Source:[/color] [url=", a_PluginInfo.SourceLocation, "]Link[/url][/b]");
+ end
+
f:close();
end
@@ -290,8 +582,21 @@ end
-local function DumpPluginInfoGitHub()
- -- TODO
+local function DumpPluginInfoGithub(a_PluginFolder, a_PluginInfo)
+ -- Open the output file:
+ local f, msg = io.open(a_PluginInfo.Name .. ".md", "w"); -- TODO: Save to a_PluginFolder .. "/Readme.md" instead
+ if (f == nil) then
+ print("\tCannot dump github info for plugin " .. a_PluginFolder .. ": " .. msg);
+ return;
+ end
+
+ -- Write the description:
+ f:write(GithubizeString(a_PluginInfo.Description), "\n");
+ DumpAdditionalInfoGithub(a_PluginInfo, f);
+ DumpCommandsGithub(a_PluginInfo, f);
+ DumpPermissionsGithub(a_PluginInfo, f);
+
+ f:close();
end
@@ -301,12 +606,6 @@ end
--- Tries to load the g_PluginInfo from the plugin's Info.lua file
-- Returns the g_PluginInfo table on success, or nil and error message on failure
local function LoadPluginInfo(a_FolderName)
- -- Check if the Info file is present at all:
- local Attribs = lfs.attributes(a_FolderName .. "/Info.lua");
- if ((Attribs == nil) or (Attribs.mode ~= "file")) then
- return nil;
- end
-
-- Load and compile the Info file:
local cfg, err = loadfile(a_FolderName .. "/Info.lua");
if (cfg == nil) then
@@ -332,30 +631,76 @@ local function ProcessPluginFolder(a_FolderName)
local PluginInfo, Msg = LoadPluginInfo(a_FolderName);
if (PluginInfo == nil) then
if (Msg ~= nil) then
- print("\tCannot load Info.lua: " .. Msg);
+ print("\t" .. Msg);
end
return;
end
DumpPluginInfoForum(a_FolderName, PluginInfo);
+ DumpPluginInfoGithub(a_FolderName, PluginInfo);
end
-print("Processing plugin subfolders:");
-for fnam in lfs.dir(".") do
- if ((fnam ~= ".") and (fnam ~= "..")) then
- local Attributes = lfs.attributes(fnam);
- if (Attributes ~= nil) then
- if (Attributes.mode == "directory") then
- print(fnam);
- ProcessPluginFolder(fnam);
- end
+--- Tries to load LFS through LuaRocks, returns the LFS instance, or nil on error
+local function LoadLFS()
+ -- Try to load lfs, do not abort if not found ...
+ local lfs, err = pcall(
+ function()
+ return require("lfs")
end
+ );
+
+ -- ... rather, print a nice message with instructions:
+ if not(lfs) then
+ print([[
+ Cannot load LuaFileSystem
+ Install it through luarocks by executing the following command:
+ luarocks install luafilesystem (Windows)
+ sudo luarocks install luafilesystem (*nix)
+
+ If you don't have luarocks installed, you need to install them using your OS's package manager, usually:
+ sudo apt-get install luarocks (Ubuntu / Debian)
+ On windows, a binary distribution can be downloaded from the LuaRocks homepage, http://luarocks.org/en/Download
+ ]]);
+
+ print("Original error text: ", err);
+ return nil;
end
+
+ -- We now know that LFS is present, get it normally:
+ return require("lfs");
end
+
+local Arg1 = ...;
+if ((Arg1 ~= nil) and (Arg1 ~= "")) then
+ -- Called with a plugin folder name, export only that one
+ ProcessPluginFolder(Arg1)
+else
+ -- Called without any arguments, process all subfolders:
+ local lfs = LoadLFS();
+ if (lfs == nil) then
+ -- LFS not loaded, error has already been printed, just bail out
+ return;
+ end
+ print("Processing plugin subfolders:");
+ for fnam in lfs.dir(".") do
+ if ((fnam ~= ".") and (fnam ~= "..")) then
+ local Attributes = lfs.attributes(fnam);
+ if (Attributes ~= nil) then
+ if (Attributes.mode == "directory") then
+ print(fnam);
+ ProcessPluginFolder(fnam);
+ end
+ end
+ end
+ end
+end
+print("Done.");
+
+