Merge pull request #2277 from lethosor/fix-lua-df-expr-to-ref

Rewrite utils.df_expr_to_ref() for consistency, add tests
develop
Myk 2022-09-07 09:14:26 -07:00 committed by GitHub
commit 3cb890ee2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 7 deletions

@ -78,6 +78,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- History: added ``dfhack.getCommandHistory(history_id, history_filename)`` and ``dfhack.addCommandToHistory(history_id, history_filename, command)`` so gui scripts can access a commandline history without requiring a terminal. - History: added ``dfhack.getCommandHistory(history_id, history_filename)`` and ``dfhack.addCommandToHistory(history_id, history_filename, command)`` so gui scripts can access a commandline history without requiring a terminal.
- ``helpdb``: database and query interface for DFHack tool help text - ``helpdb``: database and query interface for DFHack tool help text
- ``tile-material``: fix the order of declarations. The ``GetTileMat`` function now returns the material as intended (always returned nil before). Also changed the license info, with permission of the original author. - ``tile-material``: fix the order of declarations. The ``GetTileMat`` function now returns the material as intended (always returned nil before). Also changed the license info, with permission of the original author.
- ``utils.df_expr_to_ref()``: fixed some errors that could occur when navigating tables
- ``widgets.EditField``: new ``onsubmit2`` callback attribute is called when the user hits Shift-Enter. - ``widgets.EditField``: new ``onsubmit2`` callback attribute is called when the user hits Shift-Enter.
- ``widgets.EditField``: new function: ``setCursor(position)`` sets the input cursor. - ``widgets.EditField``: new function: ``setCursor(position)`` sets the input cursor.
- ``widgets.EditField``: new attribute: ``ignore_keys`` lets you ignore specified characters if you want to use them as hotkeys - ``widgets.EditField``: new attribute: ``ignore_keys`` lets you ignore specified characters if you want to use them as hotkeys

@ -608,18 +608,20 @@ df_env = df_shortcut_env()
function df_expr_to_ref(expr) function df_expr_to_ref(expr)
expr = expr:gsub('%["(.-)"%]', function(field) return '.' .. field end) expr = expr:gsub('%["(.-)"%]', function(field) return '.' .. field end)
:gsub('%[\'(.-)\'%]', function(field) return '.' .. field end) :gsub('%[\'(.-)\'%]', function(field) return '.' .. field end)
:gsub('%[(%d+)]', function(field) return '.' .. field end) :gsub('%[(%-?%d+)%]', function(field) return '.' .. field end)
local parts = expr:split('.', true) local parts = expr:split('.', true)
local obj = df_env[parts[1]] local obj = df_env[parts[1]]
for i = 2, #parts do for i = 2, #parts do
local key = tonumber(parts[i]) or parts[i] local key = tonumber(parts[i]) or parts[i]
local cur = obj[key] if i == #parts then
if i == #parts and ((type(cur) ~= 'userdata') or local ok, ret = pcall(function()
type(cur) == 'userdata' and getmetatable(cur) == nil) then return obj:_field(key)
obj = obj:_field(key) end)
else if ok then
obj = obj[key] return ret
end
end end
obj = obj[key]
end end
return obj return obj
end end

@ -54,3 +54,62 @@ function test.invert_overwrite()
expect.eq(i.b, 2) expect.eq(i.b, 2)
expect.eq(i.a, 3) expect.eq(i.a, 3)
end end
function test.df_expr_to_ref()
-- userdata field
expect.eq(utils.df_expr_to_ref('df.global.world.engravings'), df.global.world.engravings)
expect.eq(utils.df_expr_to_ref('df.global.world.engravings'), df.global.world:_field('engravings'))
-- primitive field
expect.eq(utils.df_expr_to_ref('df.global.world.original_save_version'), df.global.world:_field('original_save_version'))
-- table field
expect.eq(utils.df_expr_to_ref('df.global.world'), df.global.world)
expect.eq(utils.df_expr_to_ref('df.global'), df.global)
-- table
expect.eq(utils.df_expr_to_ref('df'), df)
-- userdata object
expect.eq(utils.df_expr_to_ref('scr'), dfhack.gui.getCurViewscreen())
local fake_unit
mock.patch(dfhack.gui, 'getSelectedUnit', function() return fake_unit end, function()
-- lightuserdata field
fake_unit = {
null_field=df.NULL,
}
expect.eq(utils.df_expr_to_ref('unit'), fake_unit)
expect.eq(utils.df_expr_to_ref('unit.null_field'), fake_unit.null_field)
dfhack.with_temp_object(df.unit:new(), function(u)
fake_unit = u
-- userdata field
expect.eq(utils.df_expr_to_ref('unit.name'), fake_unit.name)
expect.eq(utils.df_expr_to_ref('unit.name'), fake_unit:_field('name'))
-- primitive field
expect.eq(utils.df_expr_to_ref('unit.profession'), fake_unit:_field('profession'))
end)
-- vector items
dfhack.with_temp_object(df.new('ptr-vector'), function(vec)
fake_unit = vec
vec:insert('#', df.global.world)
vec:insert('#', df.global.ui)
expect.eq(utils.df_expr_to_ref('unit'), vec)
expect.eq(utils.df_expr_to_ref('unit[0]'), utils.df_expr_to_ref('unit.0'))
expect.eq(df.reinterpret_cast(df.world, utils.df_expr_to_ref('unit[0]').value), df.global.world)
expect.eq(utils.df_expr_to_ref('unit[1]'), utils.df_expr_to_ref('unit.1'))
expect.eq(df.reinterpret_cast(df.ui, utils.df_expr_to_ref('unit[1]').value), df.global.ui)
expect.error_match('index out of bounds', function() utils.df_expr_to_ref('unit.2') end)
expect.error_match('index out of bounds', function() utils.df_expr_to_ref('unit[2]') end)
expect.error_match('index out of bounds', function() utils.df_expr_to_ref('unit.-1') end)
expect.error_match('index out of bounds', function() utils.df_expr_to_ref('unit[-1]') end)
expect.error_match('not found', function() utils.df_expr_to_ref('unit.a') end)
end)
end)
end