mirror of
https://github.com/hyprwm/Hyprland.git
synced 2026-08-18 11:02:10 +00:00
config/lua: display dispatcher names in binds list and when stringifying (#15722)
This commit is contained in:
@ -831,3 +831,17 @@ TEST_CASE(keybinds) {
|
||||
CALL_SUBTEST(perDeviceKeybind);
|
||||
CALL_SUBTEST(unbind);
|
||||
}
|
||||
|
||||
TEST_CASE(luaDispatcherStrings) {
|
||||
OK(getFromSocket("/eval B = hl.bind('SUPER + F24', hl.dsp.exec_cmd('true'))"));
|
||||
EXPECT(getFromSocket("/repl return B.handler"), "HL.Dispatcher(exec_cmd)");
|
||||
OK(getFromSocket("/eval B:unbind()"));
|
||||
|
||||
OK(getFromSocket("/eval B = hl.bind('SUPER + F24', hl.dsp.window.close())"));
|
||||
EXPECT(getFromSocket("/repl return B.handler"), "HL.Dispatcher(close)");
|
||||
OK(getFromSocket("/eval B:unbind()"));
|
||||
|
||||
OK(getFromSocket("/eval B = hl.bind('SUPER + F24', function() hl.exec_cmd('true') end)"));
|
||||
EXPECT_STARTS_WITH(getFromSocket("/repl return B.handler"), "function: ");
|
||||
OK(getFromSocket("/eval B:unbind()"));
|
||||
}
|
||||
|
||||
@ -7,7 +7,8 @@ static char DISPATCHER_TABLES_REGISTRY_KEY;
|
||||
|
||||
namespace {
|
||||
struct SDispatcherRef {
|
||||
int ref = LUA_NOREF;
|
||||
int ref = LUA_NOREF;
|
||||
int nameref = LUA_NOREF;
|
||||
};
|
||||
}
|
||||
|
||||
@ -17,6 +18,10 @@ static int dispatcherGc(lua_State* L) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, dispatcher->ref);
|
||||
dispatcher->ref = LUA_NOREF;
|
||||
}
|
||||
if (dispatcher->nameref != LUA_NOREF) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, dispatcher->nameref);
|
||||
dispatcher->nameref = LUA_NOREF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -26,7 +31,15 @@ static int dispatcherCall(lua_State* L) {
|
||||
}
|
||||
|
||||
static int dispatcherToString(lua_State* L) {
|
||||
lua_pushstring(L, "HL.Dispatcher");
|
||||
auto* dispatcher = sc<SDispatcherRef*>(luaL_checkudata(L, 1, DISPATCHER_MT));
|
||||
std::string str;
|
||||
if (dispatcher->nameref != LUA_NOREF) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, dispatcher->nameref);
|
||||
str = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
} else
|
||||
str = "INVALID";
|
||||
lua_pushstring(L, std::format("HL.Dispatcher({})", str).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -74,8 +87,10 @@ static int dispatcherFactory(lua_State* L) {
|
||||
lua_call(L, nargs, LUA_MULTRET);
|
||||
|
||||
const int nresults = lua_gettop(L);
|
||||
if (nresults == 1 && lua_isfunction(L, -1))
|
||||
if (nresults == 1 && lua_isfunction(L, -1)) {
|
||||
lua_pushvalue(L, lua_upvalueindex(2));
|
||||
return Internal::wrapDispatcher(L);
|
||||
}
|
||||
|
||||
return nresults;
|
||||
}
|
||||
@ -83,7 +98,8 @@ static int dispatcherFactory(lua_State* L) {
|
||||
void Internal::setFn(lua_State* L, const char* name, lua_CFunction fn) {
|
||||
if (isDispatcherTable(L, -1)) {
|
||||
lua_pushcfunction(L, fn);
|
||||
lua_pushcclosure(L, dispatcherFactory, 1);
|
||||
lua_pushstring(L, name);
|
||||
lua_pushcclosure(L, dispatcherFactory, 2);
|
||||
} else
|
||||
lua_pushcfunction(L, fn);
|
||||
|
||||
@ -112,11 +128,13 @@ void Internal::markDispatcherTable(lua_State* L) {
|
||||
}
|
||||
|
||||
int Internal::wrapDispatcher(lua_State* L) {
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
luaL_checktype(L, -1, LUA_TSTRING);
|
||||
const int nameref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
const int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
new (lua_newuserdata(L, sizeof(SDispatcherRef))) SDispatcherRef{.ref = ref};
|
||||
new (lua_newuserdata(L, sizeof(SDispatcherRef))) SDispatcherRef{.ref = ref, .nameref = nameref};
|
||||
|
||||
ensureDispatcherMetatable(L);
|
||||
luaL_getmetatable(L, DISPATCHER_MT);
|
||||
|
||||
@ -25,6 +25,7 @@ using namespace Hyprutils::String;
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
}
|
||||
|
||||
@ -79,6 +80,9 @@ static int hlBind(lua_State* L) {
|
||||
if (!keys)
|
||||
return Internal::configError(L, std::format("hl.bind: failed to parse key string: {}", keys.error()));
|
||||
|
||||
const std::string handler = luaL_tolstring(L, 2, nullptr);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (!Internal::pushDispatcherFunction(L, 2))
|
||||
return Internal::configError(L, "hl.bind: dispatcher must be a dispatcher (e.g. hl.dsp.window.close()) or a lua function");
|
||||
|
||||
@ -94,7 +98,7 @@ static int hlBind(lua_State* L) {
|
||||
.metadata =
|
||||
{
|
||||
.displayKey = std::string{DISPLAY_KEYS},
|
||||
.handler = "__lua",
|
||||
.handler = handler,
|
||||
.argument = std::to_string(LUA_REF->ref()),
|
||||
.submap = mgr->m_currentSubmap,
|
||||
.submapReset = mgr->m_currentSubmapReset,
|
||||
|
||||
@ -146,8 +146,8 @@ TEST(ConfigLuaObjects, keybindExposesMetadataAndRemoveMethods) {
|
||||
{
|
||||
.displayKey = "SUPER + Q",
|
||||
.description = "Close active window",
|
||||
.handler = "exec",
|
||||
.argument = "kitty",
|
||||
.handler = "HL.Dispatcher(close)",
|
||||
.argument = "42",
|
||||
.submap = "default",
|
||||
},
|
||||
});
|
||||
@ -159,13 +159,13 @@ TEST(ConfigLuaObjects, keybindExposesMetadataAndRemoveMethods) {
|
||||
Objects::CLuaKeybind::push(L, keybind);
|
||||
lua_setglobal(L, "kb");
|
||||
|
||||
ASSERT_EQ(luaL_dostring(L, R"(
|
||||
ASSERT_EQ(luaL_dostring(L, R"-(
|
||||
assert(kb.enabled == true)
|
||||
assert(kb.description == "Close active window")
|
||||
assert(kb.display_key == "SUPER + Q")
|
||||
assert(kb.submap == "default")
|
||||
assert(kb.handler == "exec")
|
||||
assert(kb.arg == "kitty")
|
||||
assert(kb.handler == "HL.Dispatcher(close)")
|
||||
assert(kb.arg == "42")
|
||||
assert(kb.modmask ~= nil)
|
||||
assert(kb.key == "Q")
|
||||
assert(kb.keycode == 0)
|
||||
@ -178,7 +178,7 @@ TEST(ConfigLuaObjects, keybindExposesMetadataAndRemoveMethods) {
|
||||
|
||||
kb:remove()
|
||||
kb:unbind()
|
||||
)"),
|
||||
)-"),
|
||||
LUA_OK);
|
||||
|
||||
ASSERT_EQ(Keybinds::mgr()->registry().size(), 1);
|
||||
@ -211,13 +211,15 @@ TEST(ConfigLuaObjects, keybindRemovalDoesNotUnrefCallback) {
|
||||
|
||||
ASSERT_EQ(luaL_dostring(L, "return function() end"), LUA_OK);
|
||||
ASSERT_TRUE(lua_isfunction(L, -1));
|
||||
const std::string HANDLER = luaL_tolstring(L, -1, nullptr);
|
||||
lua_pop(L, 1);
|
||||
const int REF = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
const auto keybind = Keybinds::mgr()->addBind(makeBind({"Q"}, 0,
|
||||
{
|
||||
.metadata =
|
||||
{
|
||||
.handler = "__lua",
|
||||
.handler = HANDLER,
|
||||
.argument = std::to_string(REF),
|
||||
},
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user