Looking for more active discussion? Join our Discord at https://discord.gg/x2s7fY6

Streamlined String Formatting with Metatables (clean up your display code!)

LinLin BlackbirdThe Moonglade
edited June 2018 in Scripts
Hi! No, I'm not back, but I was scavenging some things from my old system and I come dispensing goodies.

Ever have to write a multi-colored display? It probably looks a little something like this:
cecho("" .. room.name .. ". [" .. room.num .. "] [<" .. getEnvironmentColor(room.env) .. ">" .. getEnvironmentShortName(room.env) .. "] [" .. getCleanAreaName(room.area) .. "]")
Just a complete mess, right? The Lua function string.format() alleviates some of this by using a handy token syntax. It can also be a little bit of a pain though - who wants to wrap every string they write in another nested function?

With a little metatable tweaking, we can create a sort of shorthand for string.format() by hijacking the modulo operator - useful for arithmetic, not so much for strings - and giving it a handler.




Add the following somewhere in a high level script:
getmetatable("").__mod = function(a, b)
if not b then
return a
elseif type(b) == "table" then
return string.format(a, unpack(b))
else
return string.format(a, b)
end
end



Now strings have a new behavior. You can use the following format:

"My string, with various %s, %d, and other tokens" % {"a string", 12345}




Before, you'd write:
local my_name = "Ben"
local my_age = "twenty"
echo("Hello, my name is " .. my_name .. ". I am " .. my_age .. " years old.")
But now you can do:
local my_name = "Ben"
local my_age = 20
echo("Hello, my name is %s. I am %d years old." % {my_name, my_age})
Although a tiny bit tricky to get used to at first, this new method can greatly save writing time and improve readability. It works anywhere you'd use a string. In addition, string.format() is a highly optimized function implemented in ANSI C, and though most users won't notice a difference, it'll be a little easier on your system where memory usage is concerned.
local my_divine = "The Goddess %s" % {"Iosyne"}

enableTrigger("%s" % {my_trigger})

etc. etc.
And thanks to just how chill Lua is with indenting/linebreaking your functions for readability's sake, you can rewrite that monstrosity at the beginning of this post as...
cecho("%s. [%d] [<%s>%s] [%s]" % {
room.name, room.num, getEnvironmentColor(room.env), getEnvironmentShortName(room.env), getCleanAreaName(room.area)
})
Still a lot to track, but damn if it isn't easier to manage.

Enjoy!

Comments

Sign In or Register to comment.