Jump to content

Recommended Posts

Posted

This code will retrieve the entire Lua API and process it, outputting some interesting data into a JSON file. What can this be used for? I am glad you asked. Soon you will learn the answer. From start to finish, it took me 45 minutes to write this code.

#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

void Load(table& j3, table& info)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    table t = {};
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    if (p > -1 and p < p2)
                    {                        
                        String rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();
                        s = rvalue + " " + s.Trim();
                    }
                    s = s.Trim();
                    t["syntax"] = s;
                    break;
                }
            }
            info[std::string(j3["title"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            Load(t.second, info);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info);
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Lua.json");

    return 0;
}

The output looks like this:

{
	"ACos":
	{
		"page": "ACos",
		"syntax": "number ACos(number value)"
	},
	"ASin":
	{
		"page": "ASin",
		"syntax": "number ASin(number value)"
	},
	"ASyncDownloadFile":
	{
		"page": "ASyncDownloadFile",
		"syntax": "ASyncDownloadFileInfo AsyncDownloadFile(string url, string localpath)"
	},
	"ATan":
	{
		"page": "ATan",
		"syntax": "number ATan(number value)"
	},
	"Aabb":
	{
		"page": "Aabb"
	},

 

Let's build cool stuff and have fun. :)

Posted

Updated to fetch the command description:
 

#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

void Load(table& j3, table& info)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    table t = {};
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            String description;
            bool descactive = true;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (descactive)
                {
                    if (s.StartsWith("Base class:")) continue;
                    if (s.StartsWith("# ")) continue;
                    if (s.StartsWith("|") or s.StartsWith("##"))
                    {
                        descactive = false;
                    }
                    else
                    {
                        if (not s.empty()) description += s;
                    }
                }
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    if (p > -1 and p < p2)
                    {                        
                        String rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();
                        s = rvalue + " " + s.Trim();
                    }
                    s = s.Trim();
                    t["syntax"] = s;
                    break;
                }
            }
            if (not description.empty())
            {
                int p = description.Find(".");
                if (p != -1) description = description.Left(p + 1);
                t["description"] = description;
            }
            info[std::string(j3["title"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            Load(t.second, info);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info);
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Lua.json");

    return 0;
}

 

Let's build cool stuff and have fun. :)

Posted

This version will separate out class names, return values, function arguments, and default parameters.

#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

void Load(table& j3, table& info)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    table t = {};
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    String s = t["page"];
    auto sarr = s.Split("_");
    if (sarr.size() > 1) t["class"] = sarr[0];
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            String description;
            bool descactive = true;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (descactive)
                {
                    if (s.StartsWith("Base class:")) continue;
                    if (s.StartsWith("# ")) continue;
                    if (s.StartsWith("|") or s.StartsWith("##"))
                    {
                        descactive = false;
                    }
                    else
                    {
                        if (not s.empty()) description += s;
                    }
                }
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (s.Find("PeekShort") > -1)
                    {
                        int g = 3;
                    }
                    if (s.StartsWith("#")) break;
                    if (s.StartsWith("|")) break;
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("dFloat", "number");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    if (std::string(j3["filename"]) == "Entity_SetPosition")
                    {
                        int a = 3;
                    }

                    String rvalue;
                    if (p > -1 and p < p2)
                    {                        
                        rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();                        
                        s = rvalue + " " + s.Trim();
                    }
                    s = s.Trim();

                    table syntax = {};

                    {
                        int p0 = s.Find(" ");
                        int p1 = s.Find("(");
                        if (p1 > -1)
                        {
                            s = s.Right(s.size() - p1 - 1);
                        }
                        int p2 = s.Find(")");
                        if (not rvalue.empty()) syntax["return"] = rvalue;
                        if (p1 > p0)
                        {
                            //syntax["return"] = s.Left(p0);
                        }
                        //s = s.Right(s.size() - p1 - 1);
                        s = s.Replace(")", "");
                    }

                    auto sarr = s.Split(",");
                    if (not sarr.empty())
                    {
                        for (int n = 0; n < sarr.size(); ++n)
                        {
                            auto ss = sarr[n].Trim().Split("");
                            if (ss.size() > 1)
                            {
                                for (int n = 2; n < ss.size(); ++n) ss[1] += ss[n];
                                if (not syntax["arguments"].is_object()) syntax["arguments"] = {};
                                table arg = {};
                                arg["type"] = ss[0];
                                String name = ss[1];
                                auto sarrr = name.Split("=");
                                if (sarrr.size() > 1)
                                {
                                    name = sarrr[0].Trim();
                                    arg["default"] = sarrr[1].Trim();
                                }
                                else
                                {
                                    name = sarrr[0].Trim();
                                }
                                arg["name"] = name;
                                if (std::string(arg["type"]) == "extra")
                                {
                                    int g = 3;
                                }
                                if (std::string(arg["name"]) == "")
                                {
                                    arg["name"] = arg["type"];
                                    arg["type"] = nullptr;
                                    if (std::string(arg["default"]) == "true" or std::string(arg["default"]) == "false")
                                    {
                                        arg["type"] = "boolean";
                                    }
                                }
                                syntax["arguments"].push_back(arg);
                            }
                        }
                    }
                    if (not t["syntax"].is_array())
                    {
                        t["syntax"] = {};
                    }
                    t["syntax"].push_back(syntax);
                    //t["syntax"] = s;
                    //break;
                }
            }
            if (not description.empty())
            {
                int p = description.Find(".");
                if (p != -1) description = description.Left(p + 1);
                t["description"] = description;
            }
            info[std::string(j3["filename"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            Load(t.second, info);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info);
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Commands.json");

    table classtable = {};
    for (auto& t : info)
    {
        if (t.second["class"].is_string())
        {
            String classname = t.second["class"];
            auto it = t.second.find("class");
            t.second.erase(it);
            if (not classtable[classname].is_object())
            {
                classtable[classname] = {};
                classtable[classname]["methods"] = {};
            }
            classtable[classname]["methods"].push_back(t.second);
        }
    }
    SaveTable(classtable, GetPath(PATH_DESKTOP) + "/Classes.json");

    return 0;
}

 

Let's build cool stuff and have fun. :)

Posted
#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

void Load(table& j3, table& info, const String& parentname)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    table t = {};
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    String s = t["page"];
    auto sarr = s.Split("_");
    t["class"] = parentname;
    if (sarr.size() > 1) t["class"] = sarr[0];
    t["type"] = "function";
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        if (String(t["page"]).Find("_") > -1) t["type"] = "method";
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            String description;
            bool descactive = true;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (descactive)
                {
                    if (s.StartsWith("Base class:"))
                    {
                        //t["type"] = "method";
                        continue;
                    }
                    if (s.StartsWith("# ")) continue;
                    if (s.StartsWith("|") or s.StartsWith("##"))
                    {
                        descactive = false;
                    }
                    else
                    {
                        if (not s.empty()) description += s;
                    }
                }
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (s.Find("PeekShort") > -1)
                    {
                        int g = 3;
                    }
                    if (s.StartsWith("#")) break;
                    if (s.StartsWith("|")) break;
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("dFloat", "number");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    if (std::string(j3["filename"]) == "Entity_SetPosition")
                    {
                        int a = 3;
                    }

                    String rvalue;
                    if (p > -1 and p < p2)
                    {                        
                        rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();                        
                        s = rvalue + " " + s.Trim();
                        if (not rvalue.empty())
                        {
                        }
                    }
                    s = s.Trim();

                    table syntax = {};

                    {
                        int p0 = s.Find(" ");
                        int p1 = s.Find("(");
                        if (p1 > -1)
                        {
                            s = s.Right(s.size() - p1 - 1);
                        }
                        int p2 = s.Find(")");
                        if (not rvalue.empty()) syntax["return"] = rvalue;
                        if (p1 > p0)
                        {
                            //syntax["return"] = s.Left(p0);
                        }
                        //s = s.Right(s.size() - p1 - 1);
                        s = s.Replace(")", "");
                    }

                    auto sarr = s.Split(",");
                    if (not sarr.empty())
                    {
                        for (int n = 0; n < sarr.size(); ++n)
                        {
                            auto ss = sarr[n].Trim().Split("");
                            if (ss.size() > 1)
                            {
                                for (int n = 2; n < ss.size(); ++n) ss[1] += ss[n];
                                if (not syntax["arguments"].is_object()) syntax["arguments"] = {};
                                table arg = {};
                                arg["type"] = ss[0];
                                String name = ss[1];
                                auto sarrr = name.Split("=");
                                if (sarrr.size() > 1)
                                {
                                    name = sarrr[0].Trim();
                                    arg["default"] = sarrr[1].Trim();
                                }
                                else
                                {
                                    name = sarrr[0].Trim();
                                }
                                arg["name"] = name;
                                if (std::string(arg["type"]) == "extra")
                                {
                                    int g = 3;
                                }
                                if (std::string(arg["name"]) == "")
                                {
                                    arg["name"] = arg["type"];
                                    arg["type"] = nullptr;
                                    if (std::string(arg["default"]) == "true" or std::string(arg["default"]) == "false")
                                    {
                                        arg["type"] = "boolean";
                                    }
                                }
                                syntax["arguments"].push_back(arg);
                            }
                        }
                    }
                    if (not t["syntax"].is_array())
                    {
                        t["syntax"] = {};
                    }
                    t["syntax"].push_back(syntax);
                    //t["syntax"] = s;
                    //break;
                }
            }
            if (not description.empty())
            {
                int p = description.Find(".");
                if (p != -1) description = description.Left(p + 1);
                t["description"] = description;
            }
            info[std::string(j3["filename"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            String name = j3["filename"];
            //if (name.empty())
            {
                name = j3["title"];
            }
            Load(t.second, info, name);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info, "Functions");
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Commands.json");

    table classtable = {};
    for (auto& t : info)
    {
        if (t.second["class"].is_string())
        {
            String classname = t.second["class"];
            auto it = t.second.find("class");
            t.second.erase(it);
            if (not classtable[classname].is_object()) classtable[classname] = {};
            if (t.second["type"] == "method")
            {
                if (not classtable[classname]["methods"].is_object()) classtable[classname]["methods"] = {};
                classtable[classname]["methods"].push_back(t.second);
            }
            else
            {
                if (not classtable[classname]["functions"].is_object()) classtable[classname]["functions"] = {};
                classtable[classname]["functions"].push_back(t.second);
            }
        }
    }
    SaveTable(classtable, GetPath(PATH_DESKTOP) + "/Classes.json");

    return 0;
}

 

Let's build cool stuff and have fun. :)

Posted

Now it writes the Lua definition files:

#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

extern void WriteLuaDefs(table& t, const WString& path);

void Load(table& j3, table& info, const String& parentname, const String& grandparentname)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    table t = {};
    t["baseclass"] = grandparentname;
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    String s = t["page"];
    auto sarr = s.Split("_");
    t["class"] = parentname;    
    if (sarr.size() > 1) t["class"] = sarr[0];
    t["type"] = "function";
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        if (String(t["page"]).Find("_") > -1) t["type"] = "method";
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            String description;
            bool descactive = true;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (descactive)
                {
                    if (s.StartsWith("Base class:"))
                    {
                        s = s.Right(s.size() - 11);
                        s = s.Trim();

                        // Regex to match [word](word.md) pattern
                        std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                        // Replace matched pattern with just the captured 'word'
                        s = std::regex_replace(s, pattern, "$1");
                        s = s.Trim();

                        t["baseclass"] = s;
                        //t["type"] = "method";
                        continue;
                    }
                    if (s.StartsWith("# ")) continue;
                    if (s.StartsWith("|") or s.StartsWith("##"))
                    {
                        descactive = false;
                    }
                    else
                    {
                        if (not s.empty()) description += s;
                    }
                }
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (s.Find("PeekShort") > -1)
                    {
                        int g = 3;
                    }
                    if (s.StartsWith("#")) break;
                    if (s.StartsWith("|")) break;
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("dFloat", "number");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    if (std::string(j3["filename"]) == "Entity_SetPosition")
                    {
                        int a = 3;
                    }

                    String rvalue;
                    if (p > -1 and p < p2)
                    {                        
                        rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();                        
                        s = rvalue + " " + s.Trim();
                        if (not rvalue.empty())
                        {
                        }
                    }
                    s = s.Trim();

                    table syntax = {};

                    {
                        int p0 = s.Find(" ");
                        int p1 = s.Find("(");
                        if (p1 > -1)
                        {
                            s = s.Right(s.size() - p1 - 1);
                        }
                        int p2 = s.Find(")");
                        if (not rvalue.empty()) syntax["return"] = rvalue;
                        if (p1 > p0)
                        {
                            //syntax["return"] = s.Left(p0);
                        }
                        //s = s.Right(s.size() - p1 - 1);
                        s = s.Replace(")", "");
                    }

                    auto sarr = s.Split(",");
                    if (not sarr.empty())
                    {
                        for (int n = 0; n < sarr.size(); ++n)
                        {
                            auto ss = sarr[n].Trim().Split("");
                            if (ss.size() > 1)
                            {
                                for (int n = 2; n < ss.size(); ++n) ss[1] += ss[n];
                                if (not syntax["arguments"].is_object()) syntax["arguments"] = {};
                                table arg = {};
                                arg["type"] = ss[0];
                                String name = ss[1];
                                auto sarrr = name.Split("=");
                                if (sarrr.size() > 1)
                                {
                                    name = sarrr[0].Trim();
                                    arg["default"] = sarrr[1].Trim();
                                }
                                else
                                {
                                    name = sarrr[0].Trim();
                                }
                                arg["name"] = name;
                                if (std::string(arg["type"]) == "extra")
                                {
                                    int g = 3;
                                }
                                if (std::string(arg["name"]) == "")
                                {
                                    arg["name"] = arg["type"];
                                    arg["type"] = nullptr;
                                    if (std::string(arg["default"]) == "true" or std::string(arg["default"]) == "false")
                                    {
                                        arg["type"] = "boolean";
                                    }
                                }
                                syntax["arguments"].push_back(arg);
                            }
                        }
                    }
                    if (not t["syntax"].is_array())
                    {
                        t["syntax"] = {};
                    }
                    t["syntax"].push_back(syntax);
                    //t["syntax"] = s;
                    //break;
                }
            }
            if (not description.empty())
            {
                int p = description.Find(".");
                if (p != -1) description = description.Left(p + 1);
                t["description"] = description;
            }
            info[std::string(j3["filename"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            String name = j3["filename"];
            //if (name.empty())
            {
                name = j3["title"];
            }
            Load(t.second, info, name, parentname);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info, "Functions", "");
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Commands.json");

    table classtable = {};
    for (auto& t : info)
    {
        if (t.second["class"].is_string())
        {
            String classname = t.second["class"];
            auto it = t.second.find("class");
            t.second.erase(it);
            if (not classtable[classname].is_object()) classtable[classname] = {};
            if (std::string(t.second["type"]) == "method")
            {
                if (not classtable[classname]["methods"].is_object()) classtable[classname]["methods"] = {};
                classtable[classname]["methods"].push_back(t.second);
            }
            else
            {
                if (not classtable[classname]["functions"].is_object()) classtable[classname]["functions"] = {};
                classtable[classname]["functions"].push_back(t.second);
            }
            if (t.second["baseclass"].is_string())
            {
                std::string base = t.second["baseclass"];
                classtable[classname]["baseclass"] = base;
                t.second["baseclass"] = nullptr;
            }
        }
    }
    SaveTable(classtable, GetPath(PATH_DESKTOP) + "/Classes.json");

    CreateDir(GetPath(PATH_DESKTOP) + "/LuaDefs");
    WriteLuaDefs(classtable, GetPath(PATH_DESKTOP) + "/LuaDefs");

    return 0;
}

void WriteLuaDefs(table& t, const WString& path)
{
    for (auto& pair : t)
    {
        String name = pair.first;
        auto& c = pair.second;
        auto stream = WriteFile(path + "/" + name + ".lua");
        stream->WriteLine("---@meta");
        stream->WriteString("---@class " + name, false);
        if (c["baseclass"].is_string())
        {
            stream->WriteString(":" + String(c["baseclass"]), false);
        }
        stream->WriteLine("");
        if (c["methods"].is_array())
        {
            stream->WriteLine(name + " = {}\n\n----------------------------\n-- Methods\n----------------------------\n");

            for (auto& p2 : c["methods"])
            {
                auto& m = p2.second;
                String mname = String(m["page"]);
                int p = mname.Find("_");
                if (p > -1) mname = mname.Right(mname.size() - p - 1);
                for (auto& syntaxpair : m["syntax"])
                {
                    String argstring;
                    auto& args = syntaxpair.second["arguments"];
                    if (args.is_array())
                    {
                        for (int n = 0; n < args.size(); ++n)
                        {
                            if (n > 0) argstring += ", ";
                            argstring += String(args[n]["name"]);
                            if (args[n]["type"].is_string())
                            {
                                stream->WriteLine("---@param " + String(args[n]["name"]) + " " + String(args[n]["type"]));
                            }
                        }
                        if (syntaxpair.second["return"].is_string())
                        {
                            stream->WriteLine("---@return " + String(syntaxpair.second["return"]) );
                        }
                    }
                    stream->WriteString("function " + name + ":" + mname + "(", false);
                    if (not argstring.empty()) stream->WriteString(argstring, false);
                    stream->WriteLine(") end\n");
                }
            }
        }
        else
        {
            stream->WriteLine("");
        }
        if (c["functions"].is_array())
        {
            stream->WriteLine("----------------------------\n-- Functions\n----------------------------\n");
            for (auto& p2 : c["functions"])
            {
                auto& m = p2.second;
                String mname = String(m["page"]);
                for (auto& syntaxpair : m["syntax"])
                {
                    String argstring;
                    auto& args = syntaxpair.second["arguments"];
                    if (args.is_array())
                    {
                        for (int n = 0; n < args.size(); ++n)
                        {
                            if (n > 0) argstring += ", ";
                            argstring += String(args[n]["name"]);
                            if (args[n]["type"].is_string())
                            {
                                stream->WriteLine("---@param " + String(args[n]["name"]) + " " + String(args[n]["type"]));
                            }
                        }
                        if (syntaxpair.second["return"].is_string())
                        {
                            stream->WriteLine("---@return " + String(syntaxpair.second["return"]));
                        }
                    }
                    stream->WriteString("function " + mname + "(", false);
                    if (not argstring.empty()) stream->WriteString(argstring, false);
                    stream->WriteLine(") end\n");
                }
                //stream->WriteString("function " + String(m["page"]) + "(", false);
                //stream->WriteLine(") end");
            }
        }
    }
}

Let's build cool stuff and have fun. :)

Posted

Now handles class members:

#include "Leadwerks.h"
#include <regex>

using namespace Leadwerks;

extern void WriteLuaDefs(table& t, const WString& path);

std::map<String, String> classbaseclass;
std::map<String, table> classparams;

void Load(table& j3, table& info, const String& parentname, const String& grandparentname)
{
    if (j3["hideFromLua"] == true) return;
    Print(j3["title"]);
    Print(j3["filename"]);

    bool isclasspage = false;
    table t = {};
    if (grandparentname != "Functions")
    {
        //t["baseclass"] = grandparentname;
    }
    //t["name"] = j3["title"];
    t["page"] = j3["filename"];
    String name = t["page"];
    if (name == "Vec3" or name == "Vec2" or name == "Vec4" or name == "Quat" or name == "Plane" or name == "Mat4" or name == "Nat3" or name == "Aabb") isclasspage = true;

    String s = t["page"];
    auto sarr = s.Split("_");
    t["class"] = parentname;    
    if (sarr.size() > 1) t["class"] = sarr[0];
    t["type"] = "function";
    if (j3["filename"].is_string())
    {
        std::string s = j3["filename"];
        if (String(t["page"]).Find("_") > -1) t["type"] = "method";
        //if (s == "Abs") DebugBreak();
        auto stream = ReadFile("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/Lua/" + s + ".md");
        if (stream)
        {
            //if (s == "Entity_Move") DebugBreak();
            bool start = false;
            String description;
            bool descactive = true;
            while (not stream->Eof())
            {
                auto s = stream->ReadLine();
                s = s.Trim();
                if (descactive)
                {
                    if (s.StartsWith("Base class:"))
                    {
                        s = s.Right(s.size() - 11);
                        s = s.Trim();

                        // Regex to match [word](word.md) pattern
                        std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                        // Replace matched pattern with just the captured 'word'
                        s = std::regex_replace(s, pattern, "$1");
                        s = s.Trim();

                        classbaseclass[name] = s;

                        //t["baseclass"] = s;
                        //t["type"] = "method";
                        isclasspage = true;
                        continue;
                    }
                    if (s.StartsWith("# ")) continue;
                    if (s.StartsWith("|") or s.StartsWith("##"))
                    {
                        descactive = false;
                    }
                    else
                    {
                        if (not s.empty()) description += s;
                    }
                }
                if (s == "| Property | Type | Description |")
                {
                    start = true;
                    continue;
                }
                if (s == "## Syntax")
                {
                    start = true;
                    continue;
                }
                if (start)
                {
                    if (isclasspage)
                    {
                        if (s.StartsWith("| "))
                        {
                            auto sarr = s.Mid(1, s.size() - 2).Split("|");
                            if (sarr.size() == 3)
                            {
                                String cname = sarr[0].Trim();
                                String type = sarr[1].Trim();
                                
                                cname = cname.Replace("-", "");

                                if (cname.Find(",") > -1)
                                {
                                    auto sarr = cname.Split(",");
                                    cname = sarr[0];
                                }

                                if (type == "Method" or type == "Function" or type == "Constructor") continue;
                                
                                // Regex to match [word](word.md) pattern
                                std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");
                                //std::regex pattern2(R"(\[([^\]]+)\]\([^\)]+\\))");

                                // Replace matched pattern with just the captured 'word'
                                type = std::regex_replace(type, pattern, "$1");
                                //type = std::regex_replace(type, pattern2, "$1");

                                type = type.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                                type = type.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");

                                type = type.Replace("xMat4", "Mat4");
                                type = type.Replace("xMat3", "Mat3");
                                type = type.Replace("xQuat", "Quat");
                                type = type.Replace("xPlane", "Plane");
                                type = type.Replace("xVec4", "Vec4");
                                type = type.Replace("xVec3", "Vec3");
                                type = type.Replace("xVec2", "Vec2");
                                type = type.Replace("dFloat", "number");
                                type = type.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                                type = type.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");

                                cname = std::regex_replace(cname, pattern, "$1");
                                //name = std::regex_replace(name, pattern2, "$1");

                                if (cname.empty()) continue;

                                String desc = sarr[2].Trim();
                                Print(cname);
                                Print(type);
                                Print("");

                                if (not classparams[name].is_array()) classparams[name] = {};
                                table p = {};
                                p["name"] = cname;
                                p["type"] = type;
                                p["description"] = desc;
                                classparams[name].push_back(p);
                            }
                        }
                        continue;
                    }

                    if (s.Find("PeekShort") > -1)
                    {
                        int g = 3;
                    }
                    if (s.StartsWith("#")) break;
                    if (s.StartsWith("|")) break;
                    if (s.empty()) continue;
                    if (s.StartsWith("-"))
                    {
                        s = s.Right(s.size() - 1);
                    }
                    s = s.Trim();
                    s = s.Replace("xMat4", "Mat4");
                    s = s.Replace("xMat3", "Mat3");
                    s = s.Replace("xQuat", "Quat");
                    s = s.Replace("xPlane", "Plane");
                    s = s.Replace("xVec4", "Vec4");
                    s = s.Replace("xVec3", "Vec3");
                    s = s.Replace("xVec2", "Vec2");
                    s = s.Replace("dFloat", "number");
                    s = s.Replace("[string](https://www.lua.org/manual/5.4/manual.html#6.4)", "string");
                    s = s.Replace("[table](https://www.lua.org/manual/5.4/manual.html#6.6)", "table");
                    s = s.Replace("*", "");

                    // Regex to match [word](word.md) pattern
                    std::regex pattern(R"(\[([^\]]+)\]\([^\)]+\.md\))");

                    // Replace matched pattern with just the captured 'word'
                    s = std::regex_replace(s, pattern, "$1");

                    int p = s.Find(" ");
                    int p2 = s.Find("(");

                    if (std::string(j3["filename"]) == "Entity_SetPosition")
                    {
                        int a = 3;
                    }

                    String rvalue;
                    if (p > -1 and p < p2)
                    {                        
                        rvalue = s.Left(p);
                        s = s.Right(s.size() - p);
                        p = rvalue.Find("(");
                        if (p > -1)
                        { 
                            rvalue = rvalue.Left(p);
                        //    rvalue = rvalue.Replace("[", "");
                         //   rvalue = rvalue.Replace("]", "");
                        }
                        rvalue = rvalue.Trim();                        
                        s = rvalue + " " + s.Trim();
                        if (not rvalue.empty())
                        {
                        }
                    }
                    s = s.Trim();

                    table syntax = {};

                    {
                        int p0 = s.Find(" ");
                        int p1 = s.Find("(");
                        if (p1 > -1)
                        {
                            s = s.Right(s.size() - p1 - 1);
                        }
                        int p2 = s.Find(")");
                        if (not rvalue.empty()) syntax["return"] = rvalue;
                        if (p1 > p0)
                        {
                            //syntax["return"] = s.Left(p0);
                        }
                        //s = s.Right(s.size() - p1 - 1);
                        s = s.Replace(")", "");
                    }

                    auto sarr = s.Split(",");
                    if (not sarr.empty())
                    {
                        for (int n = 0; n < sarr.size(); ++n)
                        {
                            auto ss = sarr[n].Trim().Split("");
                            if (ss.size() > 1)
                            {
                                for (int n = 2; n < ss.size(); ++n) ss[1] += ss[n];
                                if (not syntax["arguments"].is_object()) syntax["arguments"] = {};
                                table arg = {};
                                arg["type"] = ss[0];
                                String name = ss[1];
                                auto sarrr = name.Split("=");
                                if (sarrr.size() > 1)
                                {
                                    name = sarrr[0].Trim();
                                    arg["default"] = sarrr[1].Trim();
                                }
                                else
                                {
                                    name = sarrr[0].Trim();
                                }
                                arg["name"] = name;
                                if (std::string(arg["type"]) == "extra")
                                {
                                    int g = 3;
                                }
                                if (std::string(arg["name"]) == "")
                                {
                                    arg["name"] = arg["type"];
                                    arg["type"] = nullptr;
                                    if (std::string(arg["default"]) == "true" or std::string(arg["default"]) == "false")
                                    {
                                        arg["type"] = "boolean";
                                    }
                                }
                                syntax["arguments"].push_back(arg);
                            }
                        }
                    }
                    if (not t["syntax"].is_array())
                    {
                        t["syntax"] = {};
                    }
                    t["syntax"].push_back(syntax);
                    //t["syntax"] = s;
                    //break;
                }
            }
            if (not description.empty())
            {
                int p = description.Find(".");
                if (p != -1) description = description.Left(p + 1);
                t["description"] = description;
            }
            info[std::string(j3["filename"])] = t;
        }
    }

    if (j3["topics"].is_array())
    {
        for (auto t : j3["topics"])
        {
            String name = j3["filename"];
            //if (name.empty())
            {
                name = j3["title"];
            }
            Load(t.second, info, name, parentname);
        }
    }
}

int main(int argc, const char* argv[])
{
    auto j3 = LoadTable("https://raw.githubusercontent.com/Leadwerks/Documentation/refs/heads/master/toc.json");

    table info;
    
    for (auto t : j3["topics"])
    {
        if (std::string(t.second["title"]) == std::string("Programming Reference"))
        {
            for (auto child : t.second["topics"])
            {
                Load(child.second, info, "Functions", "");
            }
        }
    }

    SaveTable(info, GetPath(PATH_DESKTOP) + "/Commands.json");

    table classtable = {};
    for (auto& t : info)
    {
        if (t.second["class"].is_string())
        {
            String classname = t.second["class"];
            auto it = t.second.find("class");
            t.second.erase(it);
            if (not t.second["syntax"].is_array()) continue;
            if (not classtable[classname].is_object()) classtable[classname] = {};
            classtable[classname]["properties"] = classparams[classname];
            if (std::string(t.second["type"]) == "method")
            {
                if (not classtable[classname]["methods"].is_object()) classtable[classname]["methods"] = {};
                classtable[classname]["methods"].push_back(t.second);
            }
            else
            {
                if (not classtable[classname]["functions"].is_object()) classtable[classname]["functions"] = {};
                classtable[classname]["functions"].push_back(t.second);
            }
            /*if (t.second["baseclass"].is_string())
            {
                std::string base = t.second["baseclass"];
                classtable[classname]["baseclass"] = base;
                t.second["baseclass"] = nullptr;
            }*/
            classtable[classname]["baseclass"] = classbaseclass[classname];
        }
    }
    SaveTable(classtable, GetPath(PATH_DESKTOP) + "/Classes.json");

    CreateDir(GetPath(PATH_DESKTOP) + "/LuaDefs");
    WriteLuaDefs(classtable, GetPath(PATH_DESKTOP) + "/LuaDefs");

    return 0;
}

void WriteLuaDefs(table& t, const WString& path)
{
    for (auto& pair : t)
    {
        String name = pair.first;
        auto& c = pair.second;
        auto stream = WriteFile(path + "/" + name + ".lua");
        stream->WriteLine("---@meta");
        stream->WriteString("---@class " + name, false);
        if (c["baseclass"].is_string())
        {
            String base = c["baseclass"];
            if (not base.empty()) stream->WriteString(":" + base, false);
        }
        stream->WriteLine("");
        for (auto& pair : c["properties"])
        {
            stream->WriteLine("---@field " + String(pair.second["name"]) + " " + String(pair.second["type"]));
        }
        if (c["methods"].is_array() and not c["methods"].empty())
        {
            stream->WriteLine(name + " = {}\n\n----------------------------\n-- Methods\n----------------------------\n");

            for (auto& p2 : c["methods"])
            {
                auto& m = p2.second;
                String mname = String(m["page"]);
                int p = mname.Find("_");
                if (p > -1) mname = mname.Right(mname.size() - p - 1);
                for (auto& syntaxpair : m["syntax"])
                {
                    String argstring;
                    auto& args = syntaxpair.second["arguments"];
                    if (args.is_array())
                    {
                        for (int n = 0; n < args.size(); ++n)
                        {
                            if (n > 0) argstring += ", ";
                            argstring += String(args[n]["name"]);
                            if (args[n]["type"].is_string())
                            {
                                stream->WriteLine("---@param " + String(args[n]["name"]) + " " + String(args[n]["type"]));
                            }
                        }
                    }
                    if (syntaxpair.second["return"].is_string())
                    {
                        stream->WriteLine("---@return " + String(syntaxpair.second["return"]));
                    }
                    stream->WriteString("function " + name + ":" + mname + "(", false);
                    if (not argstring.empty()) stream->WriteString(argstring, false);
                    stream->WriteLine(") end\n");
                }
            }
        }
        else
        {
            stream->WriteLine("");
        }
        if (c["functions"].is_array() and not c["functions"].empty())
        {
            stream->WriteLine("----------------------------\n-- Functions\n----------------------------\n");
            for (auto& p2 : c["functions"])
            {
                auto& m = p2.second;
                String mname = String(m["page"]);
                for (auto& syntaxpair : m["syntax"])
                {
                    String argstring;
                    auto& args = syntaxpair.second["arguments"];
                    if (args.is_array())
                    {
                        for (int n = 0; n < args.size(); ++n)
                        {
                            if (n > 0) argstring += ", ";
                            argstring += String(args[n]["name"]);
                            if (args[n]["type"].is_string())
                            {
                                stream->WriteLine("---@param " + String(args[n]["name"]) + " " + String(args[n]["type"]));
                            }
                        }
                    }
                    if (syntaxpair.second["return"].is_string())
                    {
                        stream->WriteLine("---@return " + String(syntaxpair.second["return"]));
                    }
                    stream->WriteString("function " + mname + "(", false);
                    if (not argstring.empty()) stream->WriteString(argstring, false);
                    stream->WriteLine(") end\n");
                }
                //stream->WriteString("function " + String(m["page"]) + "(", false);
                //stream->WriteLine(") end");
            }
        }
    }
}

 

Let's build cool stuff and have fun. :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...