Lua API: Add a mechanism for userdata to declare that they are "table-like" for the purpose of the __dir metamethod

This can serve as a hint that you can dig down into them.

Use the mechanism for wesnoth.colors, wesnoth.game_config, and wesnoth.current.
This commit is contained in:
Celtic Minstrel 2024-09-13 00:00:25 -04:00 committed by Celtic Minstrel
parent a690d780cb
commit b977496dcb
4 changed files with 21 additions and 0 deletions

View File

@ -5288,6 +5288,8 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, &dispatch<&game_lua_kernel::impl_current_dir>);
lua_setfield(L, -2, "__dir");
lua_pushboolean(L, true);
lua_setfield(L, -2, "__dir_tablelike");
lua_pushstring(L, "current config");
lua_setfield(L, -2, "__metatable");
lua_setmetatable(L, -2);

View File

@ -67,6 +67,9 @@ int luaW_Registry::set(lua_State* L) {
int luaW_Registry::dir(lua_State *L) {
std::vector<std::string> keys;
if(lua_istable(L, 2)) {
keys = lua_check<std::vector<std::string>>(L, 2);
}
// Check for inactive keys
std::set<std::string> inactive;
for(const auto& [key, func] : validators) {

View File

@ -188,6 +188,8 @@ namespace lua_colors {
lua_setfield(L, -2, "__dir");
lua_pushstring(L, "colors table");
lua_setfield(L, -2, "__metatable");
lua_pushboolean(L, true);
lua_setfield(L, -2, "__dir_tablelike");
lua_setmetatable(L, -2);
lua_setfield(L, -2, "colors");
lua_pop(L, 1);

View File

@ -583,6 +583,18 @@ static int impl_get_dir_suffix(lua_State*L)
suffix = "ƒ";
}
}
lua_pop(L, 1);
if(suffix.size() == 1) {
// ie, the above block didn't identify it as a function
if(auto t = luaL_getmetafield(L, -1, "__dir_tablelike"); t == LUA_TBOOLEAN) {
if(luaW_toboolean(L, -1)) {
suffix = "";
}
lua_pop(L, 1);
} else if(t != LUA_TNIL) {
lua_pop(L, 1);
}
}
}
suffix = " " + suffix;
lua_pushlstring(L, suffix.c_str(), suffix.size());
@ -911,6 +923,8 @@ lua_kernel_base::lua_kernel_base()
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, &dispatch<&lua_kernel_base::impl_game_config_dir>);
lua_setfield(L, -2, "__dir");
lua_pushboolean(L, true);
lua_setfield(L, -2, "__dir_tablelike");
lua_pushstring(L, "game config");
lua_setfield(L, -2, "__metatable");
lua_setmetatable(L, -2);