Last active
December 19, 2015 08:00
-
-
Save asmagill/4340576881a774cac721 to your computer and use it in GitHub Desktop.
protect tables of constants in Hammerspoon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
A way to protect tables of constants in Hammerspoon modules from inadvertant changes | |
Updated 2015-12-19: differentiate __tostring output for keyed table vs array | |
recursively descend, making each sub-table a constant table as well | |
weak key for storing original table so can be used with generated data (in testing) | |
notifies if wrong type passed in and returns unchanged value instead | |
]]-- | |
-- This should go somewhere global, perhaps setup.lua | |
local _kMetaTable = {} | |
-- planning to experiment with using this with responses to functional queries... and I | |
-- don't want to keep loose generated data hanging around | |
_kMetaTable._k = setmetatable({}, {__mode = "k"}) | |
_kMetaTable._t = setmetatable({}, {__mode = "k"}) | |
_kMetaTable.__index = function(obj, key) | |
if _kMetaTable._k[obj] then | |
if _kMetaTable._k[obj][key] then | |
return _kMetaTable._k[obj][key] | |
else | |
for k,v in pairs(_kMetaTable._k[obj]) do | |
if v == key then return k end | |
end | |
end | |
end | |
return nil | |
end | |
_kMetaTable.__newindex = function(obj, key, value) | |
error("attempt to modify a table of constants",2) | |
return nil | |
end | |
_kMetaTable.__pairs = function(obj) return pairs(_kMetaTable._k[obj]) end | |
_kMetaTable.__len = function(obj) return #_kMetaTable._k[obj] end | |
_kMetaTable.__tostring = function(obj) | |
local result = "" | |
if _kMetaTable._k[obj] then | |
local width = 0 | |
for k,v in pairs(_kMetaTable._k[obj]) do width = width < #tostring(k) and #tostring(k) or width end | |
for k,v in require("hs.fnutils").sortByKeys(_kMetaTable._k[obj]) do | |
if _kMetaTable._t[obj] == "table" then | |
result = result..string.format("%-"..tostring(width).."s %s\n", tostring(k), | |
((type(v) == "table") and "{ table }" or tostring(v))) | |
else | |
result = result..((type(v) == "table") and "{ table }" or tostring(v)).."\n" | |
end | |
end | |
else | |
result = "constants table missing" | |
end | |
return result | |
end | |
_kMetaTable.__metatable = _kMetaTable -- go ahead and look, but don't unset this | |
local _makeConstantsTable | |
_makeConstantsTable = function(theTable) | |
if type(theTable) ~= "table" then | |
local dbg = debug.getinfo(2) | |
local msg = dbg.short_src..":"..dbg.currentline..": attempting to make a '"..type(theTable).."' into a constant table" | |
print(msg) | |
return theTable | |
end | |
for k,v in pairs(theTable) do | |
if type(v) == "table" then | |
local count = 0 | |
for a,b in pairs(v) do count = count + 1 end | |
local results = _makeConstantsTable(v) | |
if #v > 0 and #v == count then | |
_kMetaTable._t[results] = "array" | |
else | |
_kMetaTable._t[results] = "table" | |
end | |
theTable[k] = results | |
end | |
end | |
local results = setmetatable({}, _kMetaTable) | |
_kMetaTable._k[results] = theTable | |
local count = 0 | |
for a,b in pairs(theTable) do count = count + 1 end | |
if #theTable > 0 and #theTable == count then | |
_kMetaTable._t[results] = "array" | |
else | |
_kMetaTable._t[results] = "table" | |
end | |
return results | |
end | |
-- this should go in your moduals lua (or it's equivalant in internal.m, but haven't worked that out yet...) | |
-- ... some code ... | |
local _moduleConstants = { | |
["kConstant1"] = 5, | |
["kConstant2"] = 6, | |
["kConstant3"] = 7 | |
} | |
module.moduleConstants = hs._makeConstantsTable(_moduleConstants) | |
-- ... more code ... | |
return module |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment