diff options
author | Remko Tronçon <git@el-tramo.be> | 2013-12-30 11:21:45 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2014-01-03 11:09:06 (GMT) |
commit | 26bb5aa9e2f520c3c943797e6143c32e5b16806b (patch) | |
tree | 0caa41938acf53da946847f8803c62e579525af9 /Sluift/Lua | |
parent | 0b19dc7292b7672c9fbb711a411c392bc5b2bb34 (diff) | |
download | swift-26bb5aa9e2f520c3c943797e6143c32e5b16806b.zip swift-26bb5aa9e2f520c3c943797e6143c32e5b16806b.tar.bz2 |
Sluift: Add help support
Provide a 'help' function that takes a table/function, and prints help
for it. A structured representation can be retrieved through 'get_help'.
Change-Id: I2b3ce8992943ef30cee2604fba9200feed263fa5
Diffstat (limited to 'Sluift/Lua')
-rw-r--r-- | Sluift/Lua/Check.cpp | 8 | ||||
-rw-r--r-- | Sluift/Lua/Check.h | 6 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.cpp | 4 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.h | 13 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.cpp | 27 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.h | 9 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.cpp | 101 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.h | 4 |
8 files changed, 142 insertions, 30 deletions
diff --git a/Sluift/Lua/Check.cpp b/Sluift/Lua/Check.cpp index cfb726a..65ada7b 100644 --- a/Sluift/Lua/Check.cpp +++ b/Sluift/Lua/Check.cpp @@ -43,7 +43,7 @@ std::string Lua::checkString(lua_State* L, int arg) { return std::string(s); } -void* Lua::checkUserDataRaw(lua_State* L, int arg, const char* tableName) { +void* Lua::checkUserDataRaw(lua_State* L, int arg) { void* userData = lua_touserdata(L, arg); if (!userData) { throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); @@ -51,10 +51,6 @@ void* Lua::checkUserDataRaw(lua_State* L, int arg, const char* tableName) { if (!lua_getmetatable(L, arg)) { throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); } - lua_getfield(L, LUA_REGISTRYINDEX, tableName); - if (!lua_rawequal(L, -1, -2)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - lua_pop(L, 2); + lua_pop(L, 1); return userData; } diff --git a/Sluift/Lua/Check.h b/Sluift/Lua/Check.h index a569826..8a8b64a 100644 --- a/Sluift/Lua/Check.h +++ b/Sluift/Lua/Check.h @@ -16,11 +16,11 @@ namespace Swift { int checkIntNumber(lua_State* L, int arg); std::string checkString(lua_State* L, int arg); - void* checkUserDataRaw(lua_State* L, int arg, const char* tableName); + void* checkUserDataRaw(lua_State* L, int arg); template<typename T> - T** checkUserData(lua_State* L, int arg, const char* tableName) { - return reinterpret_cast<T**>(checkUserDataRaw(L, arg, tableName)); + T** checkUserData(lua_State* L, int arg) { + return reinterpret_cast<T**>(checkUserDataRaw(L, arg)); } } } diff --git a/Sluift/Lua/FunctionRegistration.cpp b/Sluift/Lua/FunctionRegistration.cpp index b773952..ddfa1f0 100644 --- a/Sluift/Lua/FunctionRegistration.cpp +++ b/Sluift/Lua/FunctionRegistration.cpp @@ -8,8 +8,8 @@ using namespace Swift::Lua; -FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type) { - FunctionRegistry::getInstance().addFunction(name, function, type); +FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type, const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + FunctionRegistry::getInstance().addFunction(name, function, type, helpDescription, helpParameters, helpOptions); } FunctionRegistration::~FunctionRegistration() { diff --git a/Sluift/Lua/FunctionRegistration.h b/Sluift/Lua/FunctionRegistration.h index 0df1da1..74269e2 100644 --- a/Sluift/Lua/FunctionRegistration.h +++ b/Sluift/Lua/FunctionRegistration.h @@ -16,15 +16,19 @@ namespace Swift { namespace Lua { class FunctionRegistration { public: - FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type); + FunctionRegistration( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); ~FunctionRegistration(); }; } } -#define SLUIFT_LUA_FUNCTION(TYPE, NAME) \ + + +#define SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS) \ static int TYPE##_##NAME(lua_State* L); \ static int TYPE##_##NAME##_wrapper(lua_State* L); \ - static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE); \ + static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS); \ static int TYPE##_##NAME##_wrapper(lua_State* L) { \ try { \ return TYPE ## _ ## NAME (L); \ @@ -34,3 +38,6 @@ namespace Swift { } \ } \ static int TYPE ## _ ## NAME (lua_State* L) + +#define SLUIFT_LUA_FUNCTION(TYPE, NAME) \ + SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, "", "", "") diff --git a/Sluift/Lua/FunctionRegistry.cpp b/Sluift/Lua/FunctionRegistry.cpp index 99ea096..df24d9c 100644 --- a/Sluift/Lua/FunctionRegistry.cpp +++ b/Sluift/Lua/FunctionRegistry.cpp @@ -7,6 +7,9 @@ #include <Sluift/Lua/FunctionRegistry.h> #include <Swiften/Base/foreach.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/globals.h> using namespace Swift::Lua; @@ -21,25 +24,19 @@ FunctionRegistry& FunctionRegistry::getInstance() { return instance; } -void FunctionRegistry::addFunction(const std::string& name, lua_CFunction function, const std::string& type) { +void FunctionRegistry::addFunction( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { Registration registration; registration.name = name; registration.function = function; registration.type = type; + registration.helpDescription = helpDescription; + registration.helpParameters = helpParameters; + registration.helpOptions = helpOptions; registrations.push_back(registration); } -std::string FunctionRegistry::getMetaTableNameForType(const std::string& type) { - return "Sluift_" + type; -} - -void FunctionRegistry::registerTypeMetaTable(lua_State* L, const std::string& type) { - luaL_newmetatable(L, getMetaTableNameForType(type).c_str()); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - addFunctionsToTable(L, type); -} - void FunctionRegistry::createFunctionTable(lua_State* L, const std::string& type) { lua_newtable(L); addFunctionsToTable(L, type); @@ -49,6 +46,12 @@ void FunctionRegistry::addFunctionsToTable(lua_State* L, const std::string& type foreach(const Registration& registration, registrations) { if (registration.type == type) { lua_pushcclosure(L, registration.function, 0); + if (!registration.helpDescription.empty()) { + Lua::registerHelp(L, -1, registration.helpDescription, registration.helpParameters, registration.helpOptions); + } + else { + Lua::registerExtraHelp(L, -1, registration.type + "." + registration.name); + } lua_setfield(L, -2, registration.name.c_str()); } } diff --git a/Sluift/Lua/FunctionRegistry.h b/Sluift/Lua/FunctionRegistry.h index e3ad620..b20108d 100644 --- a/Sluift/Lua/FunctionRegistry.h +++ b/Sluift/Lua/FunctionRegistry.h @@ -18,10 +18,8 @@ namespace Swift { ~FunctionRegistry(); static FunctionRegistry& getInstance(); - void addFunction(const std::string& name, lua_CFunction function, const std::string& type); - - static std::string getMetaTableNameForType(const std::string& type); - void registerTypeMetaTable(lua_State* L, const std::string& type); + void addFunction(const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); void createFunctionTable(lua_State* L, const std::string& type); @@ -39,6 +37,9 @@ namespace Swift { std::string name; lua_CFunction function; std::string type; + std::string helpDescription; + std::string helpParameters; + std::string helpOptions; }; std::vector<Registration> registrations; }; diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp index b00ab56..2192689 100644 --- a/Sluift/Lua/LuaUtils.cpp +++ b/Sluift/Lua/LuaUtils.cpp @@ -14,6 +14,7 @@ #include <cassert> #include <sstream> #include <boost/numeric/conversion/cast.hpp> +#include <boost/algorithm/string/trim.hpp> #include <Sluift/globals.h> using namespace Swift::Lua; @@ -77,3 +78,103 @@ boost::optional<int> Swift::Lua::getIntField(lua_State* L, int index, const std: lua_pop(L, 1); return result; } + +void Swift::Lua::registerHelp(lua_State* L, int index, const std::string& description, const std::string& parameters, const std::string& options) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_help"); + lua_pushvalue(L, index); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (!parameters.empty()) { + std::istringstream s(parameters); + lua_newtable(L); + int i = 1; + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_createtable(L, 2, 0); + lua_pushstring(L, key.c_str()); + lua_rawseti(L, -2, 1); + lua_pushstring(L, value.c_str()); + lua_rawseti(L, -2, 2); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "parameters"); + } + if (!options.empty()) { + std::istringstream s(options); + lua_newtable(L); + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_pushstring(L, value.c_str()); + lua_setfield(L, -2, key.c_str()); + } + lua_setfield(L, -2, "options"); + } + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerClassHelp(lua_State* L, const std::string& name, const std::string& description) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_class_help"); + lua_pushstring(L, name.c_str()); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerExtraHelp(lua_State* L, int index, const std::string& name) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "extra_help"); + lua_getfield(L, -1, name.c_str()); + if (!lua_isnil(L, -1)) { + lua_getfield(L, -3, "register_help"); + lua_pushvalue(L, index); + lua_pushvalue(L, -3); + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + } + lua_pop(L, 3); +} diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h index f677307..19ab74e 100644 --- a/Sluift/Lua/LuaUtils.h +++ b/Sluift/Lua/LuaUtils.h @@ -24,6 +24,10 @@ namespace Swift { void registerTableToString(lua_State* L, int index); void registerGetByTypeIndex(lua_State* L, int index); + void registerHelp(lua_State* L, int index, + const std::string& description, const std::string& parameters, const std::string& options); + void registerClassHelp(lua_State* L, const std::string& name, const std::string& description); + void registerExtraHelp(lua_State* L, int index, const std::string& name); inline int absoluteOffset(lua_State* L, int index) { return index > 0 ? index : lua_gettop(L) + index + 1; |