diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 95c31c2d7..93ab48dca 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -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('') + 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 = 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 .. "") + 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('\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('\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