aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcitrons <citrons@mondecitronne.com>2024-04-10 18:16:41 -0500
committercitrons <citrons@mondecitronne.com>2024-04-10 18:24:14 -0500
commit86425c8c93c8529cd2c88db1d0303fe980048896 (patch)
tree87d160b058ba0990d8c66631f3b776a6d2deb82f
initial commit
-rw-r--r--README.md5
-rw-r--r--bundler/init.lua81
-rw-r--r--bundler/platform.lua69
-rw-r--r--main.lua18
-rw-r--r--makefile4
5 files changed, 177 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ba83255
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# lua bundling tool
+
+a bundler for lua programs. works inside and outside of computercraft.
+
+[public domain](https://creativecommons.org/publicdomain/zero/1.0/).
diff --git a/bundler/init.lua b/bundler/init.lua
new file mode 100644
index 0000000..799a398
--- /dev/null
+++ b/bundler/init.lua
@@ -0,0 +1,81 @@
+-- bundler. public domain.
+-- https://citrons.xyz/git/cc-bundler.git
+
+local platform = require "bundler.platform"
+
+local function stringize(str, multiline)
+ local equal_signs = "="
+ for e in string.gmatch(str, "](=*)]") do
+ if #e > #equal_signs then
+ equal_signs = e .. "="
+ end
+ end
+ if multiline then
+ str = "\n"..str.."\n"
+ end
+ return ("[%s[%s]%s]"):format(equal_signs, str, equal_signs)
+end
+
+local function module_name(path)
+ path = path:match "^(.*).lua$" or path
+ path = path:match "^%./(.*)$" or path
+ path = path:gsub("/+", ".")
+ path = path:gsub("^%.+", "")
+ path = path:gsub("%.+$", "")
+ path = path:match "^(.*)%.init$" or path
+ return path
+end
+
+local function bundle_module(path)
+ if platform.is_dir(path) then
+ local modules = {}
+ for f in platform.list_dir(path) do
+ if f ~= "." and f ~= ".." then
+ table.insert(
+ modules, bundle_module(path.."/"..f))
+ end
+ end
+ return table.concat(modules, "\n")
+ else
+ local name = module_name(path)
+ local content = platform.read(path)
+ return ("modules[ %s ] = %s"):format(
+ stringize(name), stringize(content, true))
+ end
+end
+
+local loader = [[
+
+-- https://citrons.xyz/git/cc-bundler.git
+
+local load = loadstring or load
+
+local function loader(name)
+ if modules[name] then
+ local f = load(modules[name], name)
+ if setfenv then
+ setfenv(f, getfenv())
+ end
+ return f
+ end
+end
+table.insert(package.loaders or package.searchers, 1, loader)
+
+return loader( %s )(...)
+
+]]
+
+local function bundle(main_module, other_modules)
+ local output = {"local modules = {}"}
+
+ table.insert(output, bundle_module(main_module))
+ for _, m in ipairs(other_modules) do
+ table.insert(output, bundle_module(m))
+ end
+
+ local loader = loader:format(stringize(module_name(main_module)))
+
+ return table.concat(output, "\n")..loader
+end
+
+return {bundle = bundle}
diff --git a/bundler/platform.lua b/bundler/platform.lua
new file mode 100644
index 0000000..2a69653
--- /dev/null
+++ b/bundler/platform.lua
@@ -0,0 +1,69 @@
+-- bundler. public domain.
+-- https://citrons.xyz/git/cc-bundler.git
+
+local cc_host = {}
+
+function cc_host.error(msg)
+ printError(msg)
+end
+
+function cc_host.list_dir(path)
+ local list = fs.list(shell.resolve(path))
+ local i = 0
+ return function()
+ i = i + 1
+ return list[i]
+ end
+end
+
+function cc_host.is_dir(path)
+ return fs.isDir(shell.resolve(path))
+end
+
+function cc_host.read(path)
+ local file = assert(fs.open(shell.resolve(path), "r"))
+ local data = assert(file.readAll())
+ file.close()
+ return data
+end
+
+function cc_host.write(path, content)
+ local file = assert(fs.open(shell.resolve(path), "w"))
+ file.write(content)
+ file.close()
+end
+
+local normal_host = {}
+
+function normal_host.error(msg)
+ io.stderr:write(tostring(msg).."\n")
+ os.exit(-1)
+end
+
+function normal_host.list_dir(path)
+ return require "lfs".dir(path)
+end
+
+function normal_host.is_dir(path)
+ return require "lfs".attributes(path).mode == "directory"
+end
+
+function normal_host.read(path)
+ local file = assert(io.open(path, "r"))
+ local data = assert(file:read "a")
+ file:close()
+ return data
+end
+
+function normal_host.write(path, content)
+ local file = assert(io.open(path, "w"))
+ assert(file:write(content))
+ file:close()
+end
+
+if _HOST and _HOST:match "ComputerCraft" then
+ return cc_host
+else
+ return normal_host
+end
+
diff --git a/main.lua b/main.lua
new file mode 100644
index 0000000..ac380c4
--- /dev/null
+++ b/main.lua
@@ -0,0 +1,18 @@
+-- bundler. public domain.
+-- https://citrons.xyz/git/cc-bundler.git
+
+local bundler = require "bundler"
+local platform = require "bundler.platform"
+
+local out, main_module = ...
+local other_modules = {}
+for i = 3, select("#", ...) do
+ table.insert(other_modules, (select(i, ...)))
+end
+
+if not out or not main_module then
+ platform.error "usage: [output file] [main module] [other modules]..."
+ return
+end
+
+platform.write(out, bundler.bundle(main_module, other_modules))
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..f85cddb
--- /dev/null
+++ b/makefile
@@ -0,0 +1,4 @@
+out/bundler.lua: main.lua bundler/*
+ mkdir -p out
+ lua main.lua out/bundler.lua main.lua bundler
+ chmod +x out/bundler.lua