movescript/src/buildscript.lua

119 lines
4.4 KiB
Lua

--[[
Buildscript - A unified set of tools that make repetitive building tasks easier
with ComputerCraft robots.
Author: Andrew Lalis <andrewlalisofficial@gmail.com>
This module depends upon both Movescript and Itemscript.
]]--
local movescript = require("movescript")
local itemscript = require("itemscript")
-- The buildscript module.
local buildscript = {}
buildscript.VERSION = "0.0.1"
-- Runs a movescript script, while ensuring that a given item is always selected.
function buildscript.runWithItem(ms_script, filterExpr)
local instructions = movescript.parse(ms_script)
for idx, instruction in pairs(instructions) do
itemscript.selectOrWait(filterExpr)
movescript.executeInstruction(instruction)
end
end
-- Parses a value for an argument specification from a raw value.
local function parseArgValue(argSpec, arg)
if argSpec.required and (not arg or #arg < 1) then
return false, "Missing required value."
end
if argSpec.type == "string" then
return true, arg
elseif argSpec.type == "number" then
local num = tonumber(arg)
if not num and argSpec.required then
return false, "Invalid number."
end
return true, num
elseif argSpec.type == "bool" then
local txt = string.lower(arg)
if txt == "true" or txt == "t" or txt == "yes" or txt == "y" then
return true, true
else
return true, false
end
else
return false, "Unknown type: " .. argSpec.type
end
end
-- Parses arguments according to a specification table, for common building
-- scripts, and returns a table with key-value pairs for each arg.
-- The specification table should be formatted like so:
-- {
-- argName = { type = "string", required = true, idx = 1 },
-- namedArg = { name = "-f", required = true, type = "bool" }
-- }
-- Supported types: string, number, bool
function buildscript.parseArgs(args, spec)
for name, argSpec in pairs(spec) do
if argSpec.idx ~= nil then
if type(argSpec.idx) ~= "number" or argSpec.idx < 1 then
return false, "Invalid argument specification: " .. name .. " does not have a valid numeric index."
end
elseif argSpec.name ~= nil then
if type(argSpec.name) ~= "string" or #argSpec.name < 3 then
return false, "Invalid argument specification: " .. name .. " does not have a valid string name."
end
else
return false, "Invalid argument specification: " .. name .. " doesn't have idx or name."
end
if not argSpec.type then argSpec.type = "string" end
end
local results = {}
-- Iterate over each argument specification, and try and find a value for it.
for name, argSpec in pairs(spec) do
if argSpec.idx then
-- Parse a positional argument.
if argSpec.idx > #args and argSpec.required then
return false, "Missing required positional argument " .. name .. " at index " .. argSpec.idx
end
if argSpec.idx > #args then
results[name] = nil
else
local success, value = parseArgValue(argSpec, args[argSpec.idx])
if not success then
return false, "Failed to parse value for argument " .. name .. ": " .. value
end
results[name] = value
end
else
-- Parse a named argument by iterating over all args until we find one matching the name.
local valueFound = false
for idx, arg in pairs(args) do
if arg == argSpec.name then
if idx >= #args and argSpec.required then
return false, "Missing value for required argument " .. name
end
local success, value = parseArgValue(argSpec, args[idx + 1])
if not success then
return false, "Failed to parse value for argument " .. name .. ": " .. value
end
results[name] = value
valueFound = true
break
end
end
if argSpec.required and not valueFound then
return false, "Missing argument: " .. name
end
end
end
return true, results
end
return buildscript