feat: slot are always HOF

The slot's`slot` function callback needs to be a Higher-Order function
to manage correctly and consistently the signal parameters. Before this
change, the API was broken when the user wanted to pass `slot_params` to
a signal with parameters. (e.g., the `screen`
`"request::desktop_decoration"` signal passes the screen instance as a
parameter; when used in combination with `slot_params`, `slot_param`
overwrites the parameter.)

Bonus point: every slot is by default a pseudo constructor function that
has to return the actual signal callback. It makes it obvious to the
user how to use the `slot_params` to manage external dependencies and
configurations for the actual signal callback implementation.
This commit is contained in:
Aire-One 2024-11-26 01:46:41 +01:00
parent d4add4fb8a
commit d0dda9399e
2 changed files with 55 additions and 10 deletions

View File

@ -2,8 +2,16 @@ local slot = require "awesome-slot"
local function new_target() local function new_target()
return { return {
connect_signal = spy.new(function() end), signal = nil, -- Only need to bind 1 signal in the tests
disconnect_signal = spy.new(function() end), connect_signal = function(self, _signal_name, signal_callback)
self.signal = signal_callback
end,
disconnect_signal = function()
-- Unimplemented
end,
emit_signal = function(self, _signal_name, ...)
self.signal(...)
end,
} }
end end
@ -121,4 +129,47 @@ describe("Awesome-slot", function()
assert.is_not_nil(s.id) assert.is_not_nil(s.id)
end) end)
it("should manage slot parameters", function()
local target = new_target()
local signal_name = "signal"
local params = { key = "value" }
local callback = spy.new(function(p)
return function()
assert.same(params, p)
end
end)
slot {
target = target,
signal = signal_name,
slot = callback,
slot_params = params,
connect = true,
}
target:emit_signal(signal_name)
assert.spy(callback).called()
end)
it("should retrieve signal parameters", function()
local target = new_target()
local signal_name = "signal"
local callback = spy.new(function()
return function(a, b, c)
assert.equal(a, 1)
assert.equal(b, 2)
assert.equal(c, 3)
end
end)
slot {
target = target,
signal = signal_name,
slot = callback,
connect = true,
}
target:emit_signal(signal_name, 1, 2, 3)
end)
end) end)

View File

@ -120,14 +120,8 @@ function awesome_slot.create(params)
slot.target = params.target slot.target = params.target
slot.signal = params.signal slot.signal = params.signal
slot.connected = false slot.connected = false
slot.callback = function(...)
if params.slot_params then params.slot(params.slot_params)(...)
slot.params = params.slot_params
slot.callback = function()
params.slot(slot.params)
end
else
slot.callback = params.slot
end end
-- Insert the new slot into the slots list -- Insert the new slot into the slots list