Writing a modulescript with a plugin

I currently am working on a plugin that will create a modulescript containing all of the settings you put in to it, this way its readable by another script.

I was wondering using Source = X, does it need to be a string? Writing in a string format is awful.

2 Likes

You can set the source of a Script (and any subclasses) from a plugin with the Script.Source property, which, yes, is a string.

1 Like

Yeah, the Source is a string value so writing to it would have to be with a string.

I think if you use [[ ]] you can support multi-line strings, at least, so it’s not as bad.

On top of this, there’s also [==...=[ ]==...=] strings:

local s1 = [=[
    hello
    [[
        nested multi-line string!
    ]]
]=]

local s2 = [==[
    [=[
        this would be problematic if we used the previous syntax for a multi-line
    ]=]
]==]

local s3 = [====[ and so on... ]====]
1 Like

I had no idea that was a thing. What’s the result of that?

print([=[
    hello
    [[
        nested multi-line string!
    ]]
]=]) --> hello [[ nested multi-line string! ]]
1 Like

Yes, the Source property of a LuaSourceContainer does need to be a string value.

We don’t have any built in tools for manipulating or generating Lua source code. Here’s a function I used in one of my projects:

function Serial.SerializeValue(data, depth)
	local ty = typeof(data)
	local indent = ("  "):rep(depth)

	local str
	if ty == 'number' or ty == 'boolean' then
		str = tostring(data)
	elseif ty == 'string' then
		str = string.format("%q", data)
	elseif ty == 'table' and #data > 0 then
		-- array
		str = { "{" }

		for i = 1, #data do
			str[#str+1] = string.format("%s  %s,", indent, Serial.SerializeValue(data[i], depth + 1))
		end

		str[#str+1] = indent.."}"
	elseif ty == 'table' then
		-- dict
		str = { "{" }

		local ident = "^([%a_][%w_]*)$"
		local keys = {}
		for key, value in pairs(data) do
			keys[#keys+1] = key
		end
		table.sort(keys)
		for i = 1, #keys do
			local key = keys[i]
			local value = data[key]
			local safeKey
			if typeof(key) == 'string' and key:match(ident) then
				safeKey = key
			else
				safeKey = Serial.SerializeValue(key, depth + 1)
			end
			str[#str+1] = string.format("%s  %s = %s,", indent, safeKey, Serial.SerializeValue(value, depth + 1))
		end

		str[#str+1] = indent.."}"
	else
		error("Unexpected type: "..ty)
	end

	if typeof(str) == 'table' then
		str = table.concat(str, '\n')
	end
	return str
end

function Serial.Serialize(data)
	return "return ".. Serial.SerializeValue(data, 0)
end

It doesn’t handle data types like Vector3, so you’d have to extend it with those yourself.

It will produce nicely formatted tables like this:

return {
  Foo = 2,
  SomeTable = {
    "foo",
    "bar",
  },
}
14 Likes