Improved buildscript and itemscript. Still thinking about itemscript filters...
This commit is contained in:
parent
a1dd7a850a
commit
cfe8cc8a20
|
@ -22,67 +22,94 @@ function buildscript.runWithItem(ms_script, filterExpr)
|
|||
end
|
||||
end
|
||||
|
||||
local function parseArgValue(argSpec, str)
|
||||
|
||||
-- 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 }
|
||||
-- argName = { type = "string", required = true, idx = 1 },
|
||||
-- namedArg = { name = "-f", required = true, type = "bool" }
|
||||
-- }
|
||||
-- Supported types: string, number, bool
|
||||
function buildscript.parseArgs(args, spec)
|
||||
local idxArgSpecs = {}
|
||||
local namedArgSpecs = {}
|
||||
for name, argSpec in pairs(spec) do
|
||||
if argSpec.idx ~= nil then
|
||||
-- Add this argSpec to the list of indexed arg specs for parsing first.
|
||||
if type(argSpec.idx) ~= "number" or argSpec.idx < 1 do
|
||||
if type(argSpec.idx) ~= "number" or argSpec.idx < 1 then
|
||||
return false, "Invalid argument specification: " .. name .. " does not have a valid numeric index."
|
||||
end
|
||||
idxArgSpecs[name] = argSpec
|
||||
elseif argSpec.name ~= nil then
|
||||
-- Otherwise, ensure that this argSpec has a name.
|
||||
if type(argSpec.name) ~= "string" or #argSpec.name < 3 do
|
||||
if type(argSpec.name) ~= "string" or #argSpec.name < 3 then
|
||||
return false, "Invalid argument specification: " .. name .. " does not have a valid string name."
|
||||
end
|
||||
namedArgSpecs[name] = argSpec
|
||||
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 = {}
|
||||
local idx = 1
|
||||
while idx <= #args do
|
||||
local parsed = false
|
||||
-- Try and see if there's an idx arg spec for this index first.
|
||||
for name, argSpec in pairs(idxArgSpecs) do
|
||||
if argSpec.idx == idx then
|
||||
local success, value = parseArgValue(argSpec, args[idx])
|
||||
if success then
|
||||
|
||||
-- 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
|
||||
idxArgSpecs[name] = nil
|
||||
parsed = true
|
||||
valueFound = true
|
||||
break
|
||||
elseif not success and argSpec.required then
|
||||
return false, "Failed to parse value for " .. name .. " argument: " .. value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If no idx arg spec could parse the argument, try a named one.
|
||||
if not parsed then
|
||||
if idx == #args then
|
||||
return false, "Missing value for argument " .. args[idx]
|
||||
end
|
||||
for name, argSpec in pairs(idxArgSpecs) do
|
||||
|
||||
if argSpec.required and not valueFound then
|
||||
return false, "Missing argument: " .. name
|
||||
end
|
||||
end
|
||||
|
||||
idx = idx + 1
|
||||
end
|
||||
|
||||
return true, results
|
||||
|
|
|
@ -59,6 +59,12 @@ end
|
|||
|
||||
Prepending ! will match any item stack whose name does not match.
|
||||
Prepending # will do a fuzzy match using string.find.
|
||||
|
||||
Examples:
|
||||
|
||||
"coal" matches only "minecraft:coal" items
|
||||
"!#wood" matches all items except any that contain the phrase "wood"
|
||||
"#iron" matches all items that contain the phrase "iron"
|
||||
]]--
|
||||
local function parseItemFilterExpression(expr)
|
||||
local prefixIdx, prefixIdxEnd = string.find(expr, "^[!#]+")
|
||||
|
@ -137,11 +143,12 @@ function itemscript.select(filterExpr)
|
|||
return false
|
||||
end
|
||||
|
||||
-- Selects a slot containing at least one of the given item type, or waits for
|
||||
-- the user to add an item otherwise.
|
||||
function itemscript.selectOrWait(filterExpr)
|
||||
while not itemscript.select(filterExpr) do
|
||||
print("Couldn't find at least one item matching the filter expression: \"" .. filterExpr .. "\". Please add it.")
|
||||
-- Selects a slot containing at least minCount (or 1) of an item type matching
|
||||
-- the given filter expression.
|
||||
function itemscript.selectOrWait(filterExpr, minCount)
|
||||
minCount = minCount or 1
|
||||
while itemscript.totalCount(filterExpr) < minCount do
|
||||
print("Couldn't find at least " .. minCount .. " item(s) matching the filter expression: \"" .. filterExpr .. "\". Please add it.")
|
||||
os.pullEvent("turtle_inventory")
|
||||
end
|
||||
end
|
||||
|
|
14
tester.lua
14
tester.lua
|
@ -21,5 +21,15 @@ function print_r (t, name, indent)
|
|||
table_r(t,name or '__unnamed__',indent or '','')
|
||||
end
|
||||
|
||||
local ms = require("src/movescript")
|
||||
print_r(ms.parse("35(2F(safe=false)R 3(L(delay=0.25, file=file.txt)UB))", {debug=true}))
|
||||
-- local ms = require("src/movescript")
|
||||
-- print_r(ms.parse("35(2F(safe=false)R 3(L(delay=0.25, file=file.txt)UB))", {debug=true}))
|
||||
|
||||
local bs = require("src/buildscript")
|
||||
local args = {...}
|
||||
local spec = {
|
||||
num = { type = "number", required = true, idx = 1 },
|
||||
name = { name = "name", type = "bool", required = true }
|
||||
}
|
||||
local success, result = bs.parseArgs(args, spec)
|
||||
print(success)
|
||||
print_r(result)
|
||||
|
|
Loading…
Reference in New Issue