mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-11-01 05:43:01 +00:00
Merge pull request #111 from sbrl/axis-parser-hv-rework
Axis parser hv rework
This commit is contained in:
commit
a772f7ed55
4 changed files with 176 additions and 184 deletions
78
.tests/parse/axes/axes_keyword.test.lua
Normal file
78
.tests/parse/axes/axes_keyword.test.lua
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
local Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||||
|
|
||||||
|
local facing_dirs = dofile("./.tests/parse/axes/include_facing_dirs.lua")
|
||||||
|
|
||||||
|
local parse = require("worldeditadditions_core.utils.parse.axes_parser")
|
||||||
|
local parse_keyword = parse.keyword
|
||||||
|
|
||||||
|
|
||||||
|
describe("parse_keyword", function()
|
||||||
|
|
||||||
|
-- Basic tests
|
||||||
|
it("should work on single axes", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("x")
|
||||||
|
assert.are.equals("axis", ktype)
|
||||||
|
assert.are.same({"x"}, axis)
|
||||||
|
assert.are.equals(1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with axis clumping", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("zx")
|
||||||
|
assert.are.equals("axis", ktype)
|
||||||
|
assert.are.same({"x", "z"}, axis)
|
||||||
|
assert.are.equals(1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with h and v", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("hv")
|
||||||
|
assert.are.equals("axis", ktype)
|
||||||
|
assert.are.same(
|
||||||
|
{"x", "y", "z", rev={"x", "y", "z"}},
|
||||||
|
axis)
|
||||||
|
assert.are.equals(1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with h and v in clumping", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("hyxz")
|
||||||
|
assert.are.equals("axis", ktype)
|
||||||
|
assert.are.same(
|
||||||
|
{"x", "y", "z", rev={"x", "z"}},
|
||||||
|
axis)
|
||||||
|
assert.are.equals(1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with negatives", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("-xv")
|
||||||
|
assert.are.equals("axis", ktype)
|
||||||
|
assert.are.same({"x", "y", rev={"y"}}, axis)
|
||||||
|
assert.are.equals(-1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with dirs", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("left")
|
||||||
|
assert.are.equals("dir", ktype)
|
||||||
|
assert.are.equals("left", axis)
|
||||||
|
assert.are.equals(1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with negative dirs", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("-right")
|
||||||
|
assert.are.equals("dir", ktype)
|
||||||
|
assert.are.equals("right", axis)
|
||||||
|
assert.are.equals(-1, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should work with mirroring", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("m")
|
||||||
|
assert.are.equals("rev", ktype)
|
||||||
|
assert.are.equals("mirroring", axis)
|
||||||
|
assert.are.equals(nil, sign)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Error tests
|
||||||
|
it("should return error for bad axis", function()
|
||||||
|
local ktype, axis, sign = parse_keyword("-axv")
|
||||||
|
assert.are.equals("err", ktype)
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
|
@ -25,14 +25,24 @@ describe("parse_axes", function()
|
||||||
"10",
|
"10",
|
||||||
}, facing_dirs.x_pos)
|
}, facing_dirs.x_pos)
|
||||||
assert.is.truthy(minv)
|
assert.is.truthy(minv)
|
||||||
assert.are.same(Vector3.new(-3, 0, -3), minv)
|
assert.are.same(Vector3.new(-13, -10, -13), minv)
|
||||||
assert.are.same(Vector3.new(10, 10, 10), maxv)
|
assert.are.same(Vector3.new(10, 10, 10), maxv)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("should work for h and v", function()
|
||||||
|
local minv, maxv = parse_axes({
|
||||||
|
"h", "3",
|
||||||
|
"-v", "4",
|
||||||
|
}, facing_dirs.x_pos)
|
||||||
|
assert.is.truthy(minv)
|
||||||
|
assert.are.same(Vector3.new(-3, -4, -3), minv)
|
||||||
|
assert.are.same(Vector3.new(3, 4, 3), maxv)
|
||||||
|
end)
|
||||||
|
|
||||||
it("should work on directions and their abriviations", function()
|
it("should work on directions and their abriviations", function()
|
||||||
local minv, maxv = parse_axes({
|
local minv, maxv = parse_axes({
|
||||||
"l", "3", -- +z
|
"l", "3", -- +z
|
||||||
"-r", "-3", -- +z
|
"-right", "-3", -- +z
|
||||||
"b", "-10", -- -x
|
"b", "-10", -- -x
|
||||||
}, facing_dirs.x_pos)
|
}, facing_dirs.x_pos)
|
||||||
assert.is.truthy(minv)
|
assert.is.truthy(minv)
|
||||||
|
|
|
@ -16,13 +16,10 @@ end
|
||||||
|
|
||||||
local wea_c = worldeditadditions_core or nil
|
local wea_c = worldeditadditions_core or nil
|
||||||
local Vector3
|
local Vector3
|
||||||
local key_instance
|
|
||||||
if worldeditadditions_core then
|
if worldeditadditions_core then
|
||||||
key_instance = dofile(wea_c.modpath.."/utils/parse/key_instance.lua")
|
|
||||||
Vector3 = dofile(wea_c.modpath.."/utils/vector3.lua")
|
Vector3 = dofile(wea_c.modpath.."/utils/vector3.lua")
|
||||||
else
|
else
|
||||||
Vector3 = require("worldeditadditions_core.utils.vector3")
|
Vector3 = require("worldeditadditions_core.utils.vector3")
|
||||||
key_instance = require("worldeditadditions_core.utils.parse.key_instance")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,34 +27,34 @@ end
|
||||||
local keywords = {
|
local keywords = {
|
||||||
-- Compass keywords
|
-- Compass keywords
|
||||||
compass = {
|
compass = {
|
||||||
n = "z", north = "z",
|
["n"] = "z", ["north"] = "z",
|
||||||
["-n"] = "-z", ["-north"] = "-z",
|
["-n"] = "-z", ["-north"] = "-z",
|
||||||
s = "-z", south = "-z",
|
["s"] = "-z", ["south"] = "-z",
|
||||||
["-s"] = "z", ["-south"] = "z",
|
["-s"] = "z", ["-south"] = "z",
|
||||||
e = "x", east = "x",
|
["e"] = "x", ["east"] = "x",
|
||||||
["-e"] = "-x", ["-east"] = "-x",
|
["-e"] = "-x", ["-east"] = "-x",
|
||||||
w = "-x", west = "-x",
|
["w"] = "-x", ["west"] = "-x",
|
||||||
["-w"] = "x", ["-west"] = "x",
|
["-w"] = "x", ["-west"] = "x",
|
||||||
|
["u"] = "y", ["up"] = "y",
|
||||||
|
["d"] = "-y", ["down"] = "-y",
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Direction keywords
|
-- Direction keywords
|
||||||
dir = {
|
dir = {
|
||||||
["?"] = "front", f = "front",
|
["?"] = "front", ["f"] = "front",
|
||||||
facing = "front", front = "front",
|
["facing"] = "front", ["front"] = "front",
|
||||||
b = "back", back = "back",
|
["b"] = "back", ["back"] = "back",
|
||||||
behind = "back", rear = "back",
|
["behind"] = "back", ["rear"] = "back",
|
||||||
l = "left", left = "left",
|
["l"] = "left", ["left"] = "left",
|
||||||
r = "right", right = "right",
|
["r"] = "right", ["right"] = "right",
|
||||||
u = "up", up = "up",
|
|
||||||
d = "down", down = "down",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
-- Mirroring keywords
|
-- Mirroring keywords
|
||||||
mirroring = {
|
mirroring = {
|
||||||
sym = true, symmetrical = true,
|
["sym"] = true, ["symmetrical"] = true,
|
||||||
mirror = true, mir = true,
|
["mirror"] = true, ["mir"] = true,
|
||||||
rev = true, reverse = true,
|
["rev"] = true, ["reverse"] = true,
|
||||||
["true"] = true
|
["m"] = true, ["true"] = true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,17 +66,17 @@ local parse = {}
|
||||||
-- @param: str: String: Axis declaration to parse
|
-- @param: str: String: Axis declaration to parse
|
||||||
-- @returns: Table|Bool: axis | axes | false
|
-- @returns: Table|Bool: axis | axes | false
|
||||||
function parse.axis(str)
|
function parse.axis(str)
|
||||||
local axes, ret = {"x","y","z"}, {}
|
local ret = { rev={} }
|
||||||
for i,v in ipairs(axes) do
|
if str:match("[^hvxyz]") then return false end
|
||||||
if str:match(v) then table.insert(ret,v) end
|
|
||||||
|
for _,v in ipairs({{"x","h"},{"y","v"},{"z","h"}}) do
|
||||||
|
if str:match(v[2]) then table.insert(ret.rev,v[1])
|
||||||
|
str = str..v[1] end
|
||||||
|
if str:match(v[1]) then table.insert(ret,v[1]) end
|
||||||
end
|
end
|
||||||
if #ret > 0 and str:match("^[xyz]+$") then
|
|
||||||
|
if #ret.rev < 1 then ret.rev = nil end
|
||||||
return ret
|
return ret
|
||||||
elseif str == "h" then
|
|
||||||
return {"x", "z"}
|
|
||||||
elseif str == "v" then
|
|
||||||
return {"y"}
|
|
||||||
else return false end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Processes an number from a string.
|
--- Processes an number from a string.
|
||||||
|
@ -98,7 +95,7 @@ end
|
||||||
-- @returns: Key Instance: returns keyword type, processed keyword content and signed number (or nil)
|
-- @returns: Key Instance: returns keyword type, processed keyword content and signed number (or nil)
|
||||||
function parse.keyword(str)
|
function parse.keyword(str)
|
||||||
if type(str) ~= "string" then
|
if type(str) ~= "string" then
|
||||||
return key_instance.new("err", "Error: \""..tostring(str).."\" is not a string.", 404)
|
return "err", "Error: \""..tostring(str).."\" is not a string.", 404
|
||||||
elseif keywords.compass[str] then
|
elseif keywords.compass[str] then
|
||||||
str = keywords.compass[str]
|
str = keywords.compass[str]
|
||||||
end
|
end
|
||||||
|
@ -110,15 +107,17 @@ function parse.keyword(str)
|
||||||
|
|
||||||
local axes = parse.axis(str)
|
local axes = parse.axis(str)
|
||||||
if axes then
|
if axes then
|
||||||
return key_instance.new("axis", axes, sign)
|
return "axis", axes, sign
|
||||||
elseif keywords.dir[str] then
|
elseif keywords.dir[str] then
|
||||||
return key_instance.new("dir", keywords.dir[str], sign)
|
return "dir", keywords.dir[str], sign
|
||||||
elseif keywords.mirroring[str] then
|
elseif keywords.mirroring[str] then
|
||||||
return key_instance.new("rev", "mirroring")
|
return "rev", "mirroring"
|
||||||
else return key_instance.new("err", "Error: \""..str.."\" is not a valid axis, direction or keyword.", 422)
|
else
|
||||||
|
return "err", "Error: \""..str.."\" is not a valid axis, direction or keyword.", 422
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates a vector with a length of (@param: value * @param: sign)
|
--- Creates a vector with a length of (@param: value * @param: sign)
|
||||||
-- on each axis in @param: axes.
|
-- on each axis in @param: axes.
|
||||||
-- @param: axes: Table: List of axes to set
|
-- @param: axes: Table: List of axes to set
|
||||||
|
@ -126,13 +125,16 @@ end
|
||||||
-- @param: sign: Number: sign multiplier for axes
|
-- @param: sign: Number: sign multiplier for axes
|
||||||
-- @returns: Vector3: processed vector
|
-- @returns: Vector3: processed vector
|
||||||
function parse.vectorize(axes,value,sign)
|
function parse.vectorize(axes,value,sign)
|
||||||
|
-- TODO: Add hv compatability
|
||||||
local ret = Vector3.new()
|
local ret = Vector3.new()
|
||||||
for i,v in ipairs(axes) do
|
for _,v in ipairs(axes) do
|
||||||
ret[v] = value * sign
|
ret[v] = value * sign
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Converts Unified Axis Keyword table into Vector3 instances.
|
--- Converts Unified Axis Keyword table into Vector3 instances.
|
||||||
-- @param: tbl: Table: Keyword table to parse
|
-- @param: tbl: Table: Keyword table to parse
|
||||||
-- @param: facing: Table: Output from worldeditadditions_core.player_dir(name)
|
-- @param: facing: Table: Output from worldeditadditions_core.player_dir(name)
|
||||||
|
@ -141,79 +143,72 @@ end
|
||||||
-- if error: @returns: false, String: error message
|
-- if error: @returns: false, String: error message
|
||||||
function parse.keytable(tbl, facing, sum)
|
function parse.keytable(tbl, facing, sum)
|
||||||
local min, max = Vector3.new(), Vector3.new()
|
local min, max = Vector3.new(), Vector3.new()
|
||||||
local expected, tmp = 1, {axes = {}, num = 0, sign = 1, mirror = false}
|
local expected = 1
|
||||||
function tmp:reset() self.axis, self.sign = "", 1 end
|
local tmp = {axes = {}, num = 0, sign = 1, mirror = false}
|
||||||
|
|
||||||
for i,v in ipairs(tbl) do
|
--- Processes a number and adds it to the min and max vectors.
|
||||||
if v:sub(1,1) == "+" then v = v:sub(2) end
|
-- @param num The number to process.
|
||||||
tmp.num = parse.num(v)
|
-- @param axes The axes to apply the number to.
|
||||||
if expected == 1 then -- Mode 1 of state machine
|
-- @param sign The sign of the number.
|
||||||
-- State machine expects string
|
local function parseNumber(num, axes, sign)
|
||||||
if tmp.num then
|
if axes.rev then parseNumber(num, axes.rev, -sign) end
|
||||||
-- If this is a number treat as all axes and add to appropriate vector
|
if num * sign >= 0 then
|
||||||
if tmp.num * tmp.sign >= 0 then
|
max = max:add(parse.vectorize(axes, num, sign))
|
||||||
max = max:add(parse.vectorize({"x","y","z"}, tmp.num, tmp.sign))
|
|
||||||
else
|
else
|
||||||
min = min:add(parse.vectorize({"x","y","z"}, tmp.num, tmp.sign))
|
min = min:add(parse.vectorize(axes, num, sign))
|
||||||
end
|
end
|
||||||
-- We are still looking for axes so the state machine should remain
|
end
|
||||||
-- in Mode 1 for the next iteration
|
|
||||||
|
for i, v in ipairs(tbl) do
|
||||||
|
if v:sub(1, 1) == "+" then
|
||||||
|
v = v:sub(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
tmp.num = parse.num(v)
|
||||||
|
|
||||||
|
if expected == 1 then
|
||||||
|
if tmp.num then
|
||||||
|
parseNumber(tmp.num, {"x", "y", "z", rev={"x", "y", "z"}}, tmp.sign)
|
||||||
else
|
else
|
||||||
-- Else parse.keyword
|
local key_type, key_entry, key_sign = parse.keyword(v)
|
||||||
local key_inst = parse.keyword(v)
|
|
||||||
-- Stop if error and return message
|
if key_type == "axis" then
|
||||||
if key_inst:is_error() then return false, key_inst.entry end
|
tmp.axes = key_entry
|
||||||
-- Check key type and process further
|
tmp.sign = key_sign
|
||||||
if key_inst.type == "axis" then
|
elseif key_type == "dir" then
|
||||||
tmp.axes = key_inst.entry
|
tmp.axes = {facing[key_entry].axis}
|
||||||
tmp.sign = key_inst.sign
|
tmp.sign = facing[key_entry].sign * key_sign
|
||||||
elseif key_inst.type == "dir" then
|
elseif key_type == "rev" then
|
||||||
tmp.axes = {facing[key_inst.entry].axis}
|
|
||||||
tmp.sign = facing[key_inst.entry].sign * key_inst.sign
|
|
||||||
elseif key_inst.type == "rev" then
|
|
||||||
tmp.mirror = true
|
tmp.mirror = true
|
||||||
else
|
else
|
||||||
-- If key type is error or unknown throw error and stop
|
return false, key_entry
|
||||||
if key_inst.type == "err" then
|
|
||||||
return false, key_inst.entry
|
|
||||||
else
|
|
||||||
return false, "Error: Unknown Key Instance type \""..
|
|
||||||
tostring(key_inst.type).."\". Contact the devs!"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
expected = 2 -- Toggle state machine to expect number (Mode 2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else -- Mode 2 of state machine
|
expected = 2
|
||||||
-- State machine expects number
|
end
|
||||||
|
else
|
||||||
if tmp.num then
|
if tmp.num then
|
||||||
-- If this is a number process num and add to appropriate vector
|
parseNumber(tmp.num, tmp.axes, tmp.sign)
|
||||||
if tmp.num * tmp.sign >= 0 then
|
expected = 1
|
||||||
max = max:add(parse.vectorize(tmp.axes, tmp.num, tmp.sign))
|
|
||||||
else
|
else
|
||||||
min = min:add(parse.vectorize(tmp.axes, tmp.num, tmp.sign))
|
return false, "Error: Expected number after \""..tostring(tbl[i-1]).."\". Got \""..tostring(v).."\"."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
expected = 1 -- Toggle state machine to expect string (Mode 1)
|
|
||||||
else
|
|
||||||
-- Else throw an error and stop everything
|
|
||||||
return false, "Error: Expected number after \""..tostring(tbl[i-1])..
|
|
||||||
"\", got \""..tostring(v).."\"."
|
|
||||||
end
|
end
|
||||||
end -- End of state machine
|
|
||||||
|
|
||||||
end -- End of main for loop
|
|
||||||
|
|
||||||
-- Handle Mirroring
|
|
||||||
if tmp.mirror and not sum then
|
if tmp.mirror and not sum then
|
||||||
max = max:max(min:abs())
|
max = max:max(min:abs())
|
||||||
min = max:multiply(-1)
|
min = max:multiply(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if sum then return min:add(max)
|
if sum then
|
||||||
else return min, max end
|
return min:add(max)
|
||||||
|
else
|
||||||
|
return min, max
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
keyword = parse.keyword,
|
keyword = parse.keyword,
|
||||||
keytable = parse.keytable,
|
keytable = parse.keytable,
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
--- A container for transmitting (axis table, sign) or (dir, sign) pairs
|
|
||||||
-- and other data within parsing functions.
|
|
||||||
-- @internal
|
|
||||||
-- @class worldeditadditions_core.parse.key_instance
|
|
||||||
local key_instance = {}
|
|
||||||
key_instance.__index = key_instance
|
|
||||||
key_instance.__name = "Key Instance"
|
|
||||||
|
|
||||||
-- Allowed values for "type" field
|
|
||||||
local types = {
|
|
||||||
err = true, rev = true,
|
|
||||||
axis = true, dir = true,
|
|
||||||
replace = {
|
|
||||||
error = "err",
|
|
||||||
axes = "axis",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Simple function for putting stuff in quotes
|
|
||||||
local function enquote(take)
|
|
||||||
if type(take) == "string" then
|
|
||||||
return '"'..take..'"'
|
|
||||||
else return tostring(take) end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Creates a new Key Instance.
|
|
||||||
-- This is a table with a "type" string, an entry string or table
|
|
||||||
-- and an optional signed integer (or code number in the case of errors)
|
|
||||||
-- @param: type: String: Key type (axis, dir(ection), rev (mirroring) or error).
|
|
||||||
-- @param: entry: String: The main content of the key.
|
|
||||||
-- @param: sign: Int: The signed multiplier of the key (if any).
|
|
||||||
-- @return: Key Instance: The new Key Instance.
|
|
||||||
function key_instance.new(type,entry,sign)
|
|
||||||
if types.replace[type] then
|
|
||||||
type = types.replace[type]
|
|
||||||
elseif not types[type] then
|
|
||||||
return key_instance.new("err",
|
|
||||||
"Key Instance internal error: Invalid type "..enquote(type)..".",
|
|
||||||
500)
|
|
||||||
end
|
|
||||||
local tbl = {type = type, entry = entry}
|
|
||||||
if sign and sign ~= 0 then
|
|
||||||
if type == "err" then tbl.code = sign
|
|
||||||
else tbl.sign = sign end
|
|
||||||
end
|
|
||||||
return setmetatable(tbl, key_instance)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Checks if Key Instance "entry" field is a table.
|
|
||||||
-- @param: tbl: Key Instance: The Key Instance to check.
|
|
||||||
-- @return: Bool: Returns true if Key Instance has a non 0 sign value.
|
|
||||||
function key_instance.entry_table(a)
|
|
||||||
if type(a.entry) == "table" then
|
|
||||||
return true
|
|
||||||
else return false end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Checks if Key Instance has a signed multiplier.
|
|
||||||
-- @param: tbl: Key Instance: The Key Instance to check.
|
|
||||||
-- @return: Bool: Returns true if Key Instance has a non 0 sign value.
|
|
||||||
function key_instance.has_sign(a)
|
|
||||||
if not a.sign or a.sign == 0 then
|
|
||||||
return false
|
|
||||||
else return true end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Checks if Key Instance is an error.
|
|
||||||
-- @param: tbl: Key Instance: The Key Instance to check.
|
|
||||||
-- @return: Bool: Returns true if Key Instance is an error.
|
|
||||||
function key_instance.is_error(a)
|
|
||||||
if a.type == "err" then return true
|
|
||||||
else return false end
|
|
||||||
end
|
|
||||||
|
|
||||||
function key_instance.__tostring(a)
|
|
||||||
local ret = "{type = "..enquote(a.type)..", entry = "
|
|
||||||
if type(a.entry) == "table" and #a.entry <= 3 then
|
|
||||||
ret = ret.."{"
|
|
||||||
for _i,v in ipairs(a.entry) do
|
|
||||||
ret = ret..enquote(v)..", "
|
|
||||||
end
|
|
||||||
ret = ret:sub(1,-3).."}"
|
|
||||||
else ret = ret..enquote(a.entry) end
|
|
||||||
|
|
||||||
if a:is_error() and a.code then ret = ret..", code = "..a.code.."}"
|
|
||||||
elseif a:has_sign() then ret = ret..", sign = "..a.sign.."}"
|
|
||||||
else ret = ret.."}" end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
return key_instance
|
|
Loading…
Reference in a new issue