From a77e650c5fbbaf1c625a2616b7880529648e69b6 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 13 Mar 2016 03:42:57 -0400 Subject: [PATCH] gears.object: Add a new "property fallback" object type --- lib/gears/object.lua | 3 +- lib/gears/object/properties.lua | 103 ++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 lib/gears/object/properties.lua diff --git a/lib/gears/object.lua b/lib/gears/object.lua index 2eb230cd..9c21e681 100644 --- a/lib/gears/object.lua +++ b/lib/gears/object.lua @@ -9,8 +9,9 @@ local setmetatable = setmetatable local pairs = pairs local type = type local error = error +local properties = require("gears.object.properties") -local object = { mt = {} } +local object = { properties = properties, mt = {} } --- Verify that obj is indeed a valid object as returned by new() local function check(obj) diff --git a/lib/gears/object/properties.lua b/lib/gears/object/properties.lua new file mode 100644 index 00000000..7d05ca86 --- /dev/null +++ b/lib/gears/object/properties.lua @@ -0,0 +1,103 @@ +--------------------------------------------------------------------------- +--- An helper module to map userdata __index and __newindex entries to +-- lua classes. +-- +-- @author Emmanuel Lepage-Vallee <elv1313@gmail.com> +-- @copyright 2016 Emmanuel Lepage-Vallee +-- @release @AWESOME_VERSION@ +-- @module gears.object.properties +--------------------------------------------------------------------------- + +local object = {} + +local properties = setmetatable({}, { __mode = 'k' }) + +local function cobj_register(cobj) + local fallback = {} + + function fallback:rawset(_, prop, val) + fallback[prop] = val + end + + function fallback:rawget(_, prop) + return fallback[prop] + end + + properties[cobj] = fallback + return fallback +end + +--- Add the missing properties handler to a CAPI object such as client/tag/screen +-- Valid args: +-- +-- * **getter**: A smart getter (handle property getter itself) +-- * **getter_fallback**: A dumb getter method (don't handle individual property getter) +-- * **getter_class**: A module with individual property getter/setter +-- * **getter_prefix**: A special getter prefix (like "get" or "get_" (default)) +-- * **setter**: A smart setter (handle property setter itself) +-- * **setter_fallback**: A dumb setter method (don't handle individual property setter) +-- * **setter_class**: A module with individual property getter/setter +-- * **setter_prefix**: A special setter prefix (like "set" or "set_" (default)) +-- * **auto_emit**: Emit "property::___" automatically (default: false). This is +-- ignored when setter_fallback is set or a setter is found +-- +-- @param class A standard luaobject derived object +-- @tparam[opt={}] table args A set of accessors configuration parameters +function object.capi_index_fallback(class, args) + args = args or {} + + local getter_prefix = args.getter_prefix or "get_" + local setter_prefix = args.setter_prefix or "set_" + + local getter = args.getter or function(cobj, prop) + -- Look for a getter method + if args.getter_class and args.getter_class[getter_prefix..prop] then + return args.getter_class[getter_prefix..prop](cobj) + end + + -- Make sure something like c:a_mutator() works + if args.getter_class and args.getter_class[prop] then + return args.getter_class[prop] + end + + -- In case there is already a "dumb" getter like `awful.tag.getproperty' + if args.getter_fallback then + return args.getter_fallback(cobj, prop) + end + + local fallback = properties[cobj] or cobj_register(cobj) + + -- Use the fallback property table + return fallback[prop] + end + + local setter = args.setter or function(cobj, prop, value) + -- Look for a setter method + if args.setter_class and args.setter_class[setter_prefix..prop] then + return args.setter_class[setter_prefix..prop](cobj, value) + end + + -- In case there is already a "dumb" setter like `awful.client.property.set' + if args.setter_fallback then + return args.setter_fallback(cobj, prop, value) + end + + local fallback = properties[cobj] or cobj_register(cobj) + + -- Use the fallback property table + fallback[prop] = value + + -- Emit the signal + if args.auto_emit then + cobj:emit_signal("property::"..prop, value) + end + end + + -- Attach the accessor methods + class.set_index_miss_handler(getter) + class.set_newindex_miss_handler(setter) +end + +return setmetatable( object, {__call = function(_,...) object.capi_index_fallback(...) end}) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80