Merge remote-tracking branch 'suokko/lua_printall_recurse' into develop

develop
lethosor 2018-07-06 14:25:35 -04:00
commit c006df561e
3 changed files with 121 additions and 0 deletions

@ -2404,6 +2404,10 @@ environment by the mandatory init file dfhack.lua:
If the argument is a lua table or DF object reference, prints all fields.
* ``printall_recurse(obj)``
If the argument is a lua table or DF object reference, prints all fields recursively.
* ``copyall(obj)``
Returns a shallow copy of the table or reference as a lua table.

@ -62,6 +62,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Lua
- ``gui.widgets``: ``List:setChoices`` clones ``choices`` for internal table changes
## Lua
- Add ``printall_recurse`` to print tables and DF references recursively. It can be also used with ``^`` from lua interpreter.
## Internals
- jsoncpp: updated to version 1.8.4 and switched to using a git submodule

@ -180,6 +180,116 @@ function printall_ipairs(table)
end
end
local do_print_recurse
local function print_string(printfn, v, seen, indent)
local str = tostring(v)
printfn(str)
return #str;
end
local fill_chars = {
__index = function(table, key, value)
local rv = string.rep(' ', 23 - key) .. ' = '
rawset(table, key, rv)
return rv
end,
}
setmetatable(fill_chars, fill_chars)
local function print_fields(value, seen, indent, prefix)
local ok,f,t,k = pcall(pairs,value)
if not ok then
dfhack.print(prefix)
dfhack.println('<Type doesn\'t support iteration with pairs>')
return 0
end
local prev_value = "not a value"
local repeated = 0
for k, v in f,t,k do
-- Only show set values of bitfields
if value._kind ~= "bitfield" or v then
local continue = false
if type(k) == "number" then
if prev_value == v then
repeated = repeated + 1
continue = true
else
prev_value = v
end
else
prev_value = "not a value"
end
if not continue then
if repeated > 0 then
dfhack.println(prefix .. "<Repeated " .. repeated .. " times>")
repeated = 0
end
dfhack.print(prefix)
local len = do_print_recurse(dfhack.print, k, seen, indent + 1)
dfhack.print(fill_chars[len <= 23 and len or 23])
do_print_recurse(dfhack.println, v, seen, indent + 1)
end
end
end
if repeated > 0 then
dfhack.println(prefix .. "<Repeated " .. repeated .. " times>")
end
return 0
end
-- This should be same as print_array but userdata doesn't compare equal even if
-- they hold same pointer.
local function print_userdata(printfn, value, seen, indent)
local prefix = string.rep(' ', indent)
local strvalue = tostring(value)
dfhack.println(strvalue)
if seen[strvalue] then
dfhack.print(prefix)
dfhack.println('<Cyclic reference! Skipping fields>\n')
return 0
end
seen[strvalue] = true
return print_fields(value, seen, indent, prefix)
end
local function print_array(printfn, value, seen, indent)
local prefix = string.rep(' ', indent)
dfhack.println(tostring(value))
if seen[value] then
dfhack.print(prefix)
dfhack.println('<Cyclic reference! skipping fields>\n')
return 0
end
seen[value] = true
return print_fields(value, seen, indent, prefix)
end
local recurse_type_map = {
number = print_string,
string = print_string,
boolean = print_string,
['function'] = print_string,
['nil'] = print_string,
userdata = print_userdata,
table = print_array,
}
do_print_recurse = function(printfn, value, seen, indent)
local t = type(value)
if not recurse_type_map[t] then
printfn("Unknown type " .. t .. " " .. tostring(value))
return
end
return recurse_type_map[t](printfn, value, seen, indent)
end
function printall_recurse(value)
local seen = {}
do_print_recurse(dfhack.println, value, seen, 0)
end
function copyall(table)
local rv = {}
for k,v in pairs(table) do rv[k] = v end
@ -334,6 +444,7 @@ function dfhack.interpreter(prompt,hfile,env)
" '= foo' => '_1,_2,... = foo'\n"..
" '! foo' => 'print(foo)'\n"..
" '~ foo' => 'printall(foo)'\n"..
" '^ foo' => 'printall_recurse(foo)'\n"..
" '@ foo' => 'printall_ipairs(foo)'\n"..
"All of these save the first result as '_'.")
print_banner = false
@ -358,6 +469,9 @@ function dfhack.interpreter(prompt,hfile,env)
print(table.unpack(data,2,data.n))
printall_ipairs(data[2])
end,
['^'] = function(data)
printall_recurse(data[2])
end,
['='] = function(data)
for i=2,data.n do
local varname = '_'..vcnt