commit 53ae053b72850339d1a949d2dad162637c537290 Author: Rokas Puzonas Date: Thu May 11 22:00:44 2023 +0300 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a6c0ab --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Lua file embedder + +Combine multiple lua files into one amalgamation. This works by appending a custom module loader +to `package.loaders`. + +Usage: +```lua +require("module-bundler")("program.lua", "main.lua", { + "utils.lua", + "ui.lua", + "math.lua", +}) +``` +This will create a file called `program.lua` where `utils.lua`, `ui.lua` and `math.lua` have been +embedded into `main.lua`. diff --git a/module-bundler.lua b/module-bundler.lua new file mode 100644 index 0000000..eebaa25 --- /dev/null +++ b/module-bundler.lua @@ -0,0 +1,62 @@ +local function do_indent(code, indent_symbol) + local lines = {} + for line in code:gmatch("([^\n]*)\n?") do + if line:match("%S") then + table.insert(lines, indent_symbol..line) + else + table.insert(lines, line) + end + end + return table.concat(lines, "\n") +end + +local indent_style = "\t" + +return function(result_filename, entry_filename, module_files) + result_filename = fs.combine(shell.dir(), result_filename) + entry_filename = fs.combine(shell.dir(), entry_filename) + + + local injected_code = [[ +local modules = {} + +]] + for _, filename in ipairs(module_files) do + local mod_name = filename:gsub(".lua$", ""):gsub("[/\\]", ".") + + injected_code = injected_code .. "modules[\"" .. mod_name .. "\"] = function(...)\n" + local f = io.open(fs.combine(shell.dir(), filename), "r") + for line in f:lines() do + if line:match("%S") then + injected_code = injected_code .. indent_style .. line .. "\n" + else + injected_code = injected_code .. "\n" + end + end + injected_code = injected_code .. "end\n\n" + end + + injected_code = injected_code .. [[table.insert(package.loaders, 1, function(module_name) + module_name = module_name:gsub("[/\\]", ".") + local module = modules[module_name] + if not module then + return nil, ("no static module '%s'"):format(module_name) + end + return function(...) return module(...) end +end)]] + + injected_code = "do\n" .. do_indent(injected_code, indent_style) .. "\nend\n\n" + + do + local entry_file = io.open(entry_filename, "r") + local result_file = io.open(result_filename, "w") + + result_file:write(injected_code) + result_file:write(entry_file:read("a")) + + entry_file:close() + result_file:close() + end + + return true +end