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
|
||||||
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
|
end
|
||||||
|
|
||||||
-- Parses arguments according to a specification table, for common building
|
-- Parses arguments according to a specification table, for common building
|
||||||
-- scripts, and returns a table with key-value pairs for each arg.
|
-- scripts, and returns a table with key-value pairs for each arg.
|
||||||
-- The specification table should be formatted like so:
|
-- 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)
|
function buildscript.parseArgs(args, spec)
|
||||||
local idxArgSpecs = {}
|
|
||||||
local namedArgSpecs = {}
|
|
||||||
for name, argSpec in pairs(spec) do
|
for name, argSpec in pairs(spec) do
|
||||||
if argSpec.idx ~= nil then
|
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 then
|
||||||
if type(argSpec.idx) ~= "number" or argSpec.idx < 1 do
|
|
||||||
return false, "Invalid argument specification: " .. name .. " does not have a valid numeric index."
|
return false, "Invalid argument specification: " .. name .. " does not have a valid numeric index."
|
||||||
end
|
end
|
||||||
idxArgSpecs[name] = argSpec
|
|
||||||
elseif argSpec.name ~= nil then
|
elseif argSpec.name ~= nil then
|
||||||
-- Otherwise, ensure that this argSpec has a name.
|
if type(argSpec.name) ~= "string" or #argSpec.name < 3 then
|
||||||
if type(argSpec.name) ~= "string" or #argSpec.name < 3 do
|
|
||||||
return false, "Invalid argument specification: " .. name .. " does not have a valid string name."
|
return false, "Invalid argument specification: " .. name .. " does not have a valid string name."
|
||||||
end
|
end
|
||||||
namedArgSpecs[name] = argSpec
|
|
||||||
else
|
else
|
||||||
return false, "Invalid argument specification: " .. name .. " doesn't have idx or name."
|
return false, "Invalid argument specification: " .. name .. " doesn't have idx or name."
|
||||||
end
|
end
|
||||||
|
if not argSpec.type then argSpec.type = "string" end
|
||||||
end
|
end
|
||||||
|
|
||||||
local results = {}
|
local results = {}
|
||||||
local idx = 1
|
|
||||||
while idx <= #args do
|
-- Iterate over each argument specification, and try and find a value for it.
|
||||||
local parsed = false
|
for name, argSpec in pairs(spec) do
|
||||||
-- Try and see if there's an idx arg spec for this index first.
|
if argSpec.idx then
|
||||||
for name, argSpec in pairs(idxArgSpecs) do
|
-- Parse a positional argument.
|
||||||
if argSpec.idx == idx then
|
if argSpec.idx > #args and argSpec.required then
|
||||||
local success, value = parseArgValue(argSpec, args[idx])
|
return false, "Missing required positional argument " .. name .. " at index " .. argSpec.idx
|
||||||
if success then
|
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
|
results[name] = value
|
||||||
idxArgSpecs[name] = nil
|
valueFound = true
|
||||||
parsed = true
|
|
||||||
break
|
break
|
||||||
elseif not success and argSpec.required then
|
|
||||||
return false, "Failed to parse value for " .. name .. " argument: " .. value
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
if argSpec.required and not valueFound then
|
||||||
|
return false, "Missing argument: " .. name
|
||||||
-- 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
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
idx = idx + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, results
|
return true, results
|
||||||
|
|
|
@ -59,6 +59,12 @@ end
|
||||||
|
|
||||||
Prepending ! will match any item stack whose name does not match.
|
Prepending ! will match any item stack whose name does not match.
|
||||||
Prepending # will do a fuzzy match using string.find.
|
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 function parseItemFilterExpression(expr)
|
||||||
local prefixIdx, prefixIdxEnd = string.find(expr, "^[!#]+")
|
local prefixIdx, prefixIdxEnd = string.find(expr, "^[!#]+")
|
||||||
|
@ -137,11 +143,12 @@ function itemscript.select(filterExpr)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Selects a slot containing at least one of the given item type, or waits for
|
-- Selects a slot containing at least minCount (or 1) of an item type matching
|
||||||
-- the user to add an item otherwise.
|
-- the given filter expression.
|
||||||
function itemscript.selectOrWait(filterExpr)
|
function itemscript.selectOrWait(filterExpr, minCount)
|
||||||
while not itemscript.select(filterExpr) do
|
minCount = minCount or 1
|
||||||
print("Couldn't find at least one item matching the filter expression: \"" .. filterExpr .. "\". Please add it.")
|
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")
|
os.pullEvent("turtle_inventory")
|
||||||
end
|
end
|
||||||
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 '','')
|
table_r(t,name or '__unnamed__',indent or '','')
|
||||||
end
|
end
|
||||||
|
|
||||||
local ms = require("src/movescript")
|
-- 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}))
|
-- 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