diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2e6bd4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +doc/ diff --git a/.luacheckrc b/.luacheckrc index 2b56b86..2761cd2 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -2,6 +2,7 @@ std = "min" files[".luacheckrc"].ignore = { "111", "112", "131" } +files["config.ld"].ignore = { "111", "113" } -- Global objects defined by the C code read_globals = { diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a29472 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Awesome WM - Slot + +A declarative API to connect signals for the AwesomeWM. + +It completes the native `gears.signal` module to make signal connection easier +to manage. diff --git a/config.ld b/config.ld new file mode 100644 index 0000000..3fd0526 --- /dev/null +++ b/config.ld @@ -0,0 +1,25 @@ +project = "awesome-slot" +title = "A declarative API to connect signals for the AwesomeWM" + +all = false +dir = "doc" +format = "markdown" +pretty = "lua" +prettify_files = true +backtick_references = true +merge = true +use_markdown_titles = true +wrap = true +sort_modules = true +not_luadoc = true + +file = { + "init.lua", + exclude = { + "slots", + }, +} + +-- Define some new ldoc tags from the AwesomeWM doc +new_type("constructorfct", "Constructor", false, "Parameters") +new_type("staticfct", "Static functions", false, "Parameters") diff --git a/doc/.gitkeep b/doc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/init.lua b/init.lua index 7a145a4..f6ba980 100644 --- a/init.lua +++ b/init.lua @@ -4,11 +4,47 @@ -- A declarative API to connect signals for the AwesomeWM. -- It completes the native `gears.signal` module to make signal connection -- easier to manage. +-- +-- Usage example +-- --- +-- +-- Tis module allows to create Slot objects. These object can connect to any +-- signals from Awesome WM's `gears.object`s and module level signals. +-- +-- In the following example, we create a slot that connects to the `client` +-- global `"request::default_keybindings"` signal to attach keybindings to +-- clients. +-- +-- The `slot.slots.client.append_keybindings` function is part of this module +-- and is defined as a function iterating over the `keybindings` parameter to +-- register all defined keybindings with the `awful.keyboard.append_client_keybindings` +-- function. +-- +-- local client_keybinding = slot { +-- id = "CLIENT_KEY_BINDINGS", +-- connect = true, +-- target = capi.client, +-- signal = "request::default_keybindings", +-- slot = slot.slots.client.append_keybindings, +-- slot_params = { +-- keybindings = { +-- awful.key({ "Mod4" }, "f", +-- function(client) +-- client.fullscreen = not client.fullscreen +-- client:raise() +-- end, +-- { description = "toggle fullscreen", group = "client" }), +-- }, +-- -- ... +-- }, +-- } +-- +-- @author Aire-One +-- @copyright 2021 Aire-One ----- local gtable = require "gears.table" --- Load global awesome components from the C API local capi = { client = _G.client, screen = _G.screen, @@ -17,7 +53,13 @@ local capi = { local awesome_slot = { mt = {}, + + --- Slots defined by this module. + -- @table awesome_slot.slots slots = require "awesome-slot.slots", + + --- Special objects that require a static connection instead of object level connection. + -- @table awesome_slot.static_connect static_connect = { client = capi.client, screen = capi.screen, @@ -25,6 +67,7 @@ local awesome_slot = { ruled_client = require "ruled.client", ruled_notification = require "ruled.notification", }, + _private = { registered_slots = {}, }, @@ -42,6 +85,13 @@ local function generate_id(base_id) return id end +--- Find a previously registered slot. +-- +-- If the slot asked doesn't exist, the function will fail and throw an error. +-- +-- @tparam string|Slot slot The slot id or instance to find. +-- @treturn Slot The slot. +-- @staticfct awesome_slot.get_slot function awesome_slot.get_slot(slot) assert(slot) local id = type(slot) == "string" and slot or slot.id @@ -50,6 +100,19 @@ function awesome_slot.get_slot(slot) return awesome_slot._private.registered_slots[id] end +--- Create a new Slot instance. +-- +-- @tparam table params +-- @tparam[opt] string params.id The slot ID. +-- @tparam any params.target The slot target object. +-- @tparam string params.signal The signal the slot connects to. +-- @tparam function params.slot The callback function to connect to the signal. +-- @tparam table params.slot_params The parameters to pass to the callback +-- function. (The signal will invok the callback function with this table as +-- parameter) +-- @tparam[opt=false] boolean params.connect Connect the slot now. +-- @treturn Slot The created Slot instance. +-- @constructorfct awesome_slot function awesome_slot.create(params) local slot = {} @@ -77,48 +140,60 @@ function awesome_slot.create(params) return slot end -function awesome_slot.remove(params) - local slot = awesome_slot.get_slot(params) +--- Remove a registered slot and disconnect it. +-- +-- @tparam Slot slot The slot to remove. +-- @staticfct awesome_slot.remove +function awesome_slot.remove(slot) + local s = awesome_slot.get_slot(slot) - if slot.connected then - awesome_slot.disconnect_slot(slot) + if s.connected then + awesome_slot.disconnect_slot(s) end - awesome_slot._private.registered_slots[slot.id] = nil - - return true + awesome_slot._private.registered_slots[s.id] = nil end -function awesome_slot.connect(params) - local slot = awesome_slot.get_slot(params) +--- Connect a slot to its signal. +-- +-- @tparam Slot slot The slot to connect. +-- @treturn Slot The slot. +-- @staticfct awesome_slot.connect +function awesome_slot.connect(slot) + local s = awesome_slot.get_slot(slot) -- Some modules expose a static connect_signals function -- at the module level, while other tables/objects inheriting from -- gears.object implement the signal connection API at the instance level. - if gtable.hasitem(awesome_slot.static_connect, slot.target) then - slot.target.connect_signal(slot.signal, slot.callback) + if gtable.hasitem(awesome_slot.static_connect, s.target) then + s.target.connect_signal(s.signal, s.callback) else - slot.target:connect_signal(slot.signal, slot.callback) + s.target:connect_signal(s.signal, s.callback) end - slot.connected = true + s.connected = true - return slot + return s end -function awesome_slot.disconnect(params) - local slot = awesome_slot.get_slot(params) +--- Disconnect a slot from its signal. +-- +-- @tparam Slot slot The slot to disconnect. +-- @treturn Slot The slot. +-- @staticfct awesome_slot.disconnect +function awesome_slot.disconnect(slot) + local s = awesome_slot.get_slot(slot) -- Please check the `:connect_slot` method to understand why we do this. - if gtable.hasitem(awesome_slot.static_connect, slot.target) then - slot.target.disconnect_slot(slot.signal, slot.callback) + if gtable.hasitem(awesome_slot.static_connect, s.target) then + s.target.disconnect_slot(s.signal, s.callback) else - slot.target:disconnect_slot(slot.signal, slot.callback) + s.target:disconnect_slot(s.signal, s.callback) end - slot.connected = false + s.connected = false - return slot + return s end function awesome_slot.mt:__call(...) -- luacheck: ignore unused argument self