[DEBUG] Useful Scripts and Functions

[DEBUG] Useful Scripts and Functions

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
Tribulex
A.N.T.S. Developer
Posts: 1894
Joined: 26 Sep 2009, 21:26

[DEBUG] Useful Scripts and Functions

Post by Tribulex »

I have been teaching people Spring lua and I have been doing extensive programming myself recently as I work on ANTS, and I think a thread with useful debug functions would be nice. Here is something I found on the internet when I was too lazy to write it myself if anyone is interested:

Code: Select all

function to_string(data, indent)
    local str = ""

    if(indent == nil) then
        indent = 0
    end

    -- Check the type
    if(type(data) == "string") then
        str = str .. (" "):rep(indent) .. data .. "\n"
    elseif(type(data) == "number") then
        str = str .. (" "):rep(indent) .. data .. "\n"
    elseif(type(data) == "boolean") then
        if(data == true) then
            str = str .. "true"
        else
            str = str .. "false"
        end
    elseif(type(data) == "table") then
        local i, v
        for i, v in pairs(data) do
            -- Check for a table in a table
            if(type(v) == "table") then
                str = str .. (" "):rep(indent) .. i .. ":\n"
                str = str .. to_string(v, indent + 2)
            else
                str = str .. (" "):rep(indent) .. i .. ": " ..
to_string(v, 0)
            end
        end
    else
        print_debug(1, "Error: unknown data type: %s", type(data))
    end

    return str
end
User avatar
SpliFF
Posts: 1224
Joined: 28 Jul 2008, 06:51

Re: [DEBUG] Useful Scripts and Functions

Post by SpliFF »

Code: Select all

--===================================================
-- DEBUGGING
--===================================================

-- Trace function calls (limited to src file)
-- based on code by 'eriatarka' from TA Spring forums
function CreateStackTraceHook(src_limit)
	return function(event)
		local info = debug.getinfo(2, "S")
		--if (info.what == "C") then return end            -- do not Echo C functions
	     
		if (event == "call") then
			local info2 = debug.getinfo(2, "n")
			local src = info.short_src
			local name = info2.name or ""
			local line = info.linedefined
			if type(src_limit) == 'table' then
				for _src in src_limit do
					if src_limit == nil or string.find(src, _src) then
						Echo(src .. "(" .. line .. "): " .. name)
					end
				end
			elseif src_limit == nil or string.find(src, src_limit) then
				Echo(src .. "(" .. line .. "): " .. name)
			end
		end
	end
end
-- USAGE
--debug.sethook(CreateStackTraceHook(), "cr")            -- hook call and return events

-- Debug handler
debugging = true
function Debug( msg )
	if debugging then 
               Echo('Debug: '..tostring(msg))
        end
end

-- Error handler
function Error( msg )
	Echo('ERROR: '..tostring(msg))
	Echo(debug.traceback())
	widgetHandler:RemoveWidget()
end

-- Returns a nested, pretty-printed table or value
function Dump(value,name,indent,max_indent)
	
	local out_str = ''
	-- indent
	local indent_str = ''
	if indent == nil then 
		indent = 0
	else
		indent_str = string.rep('  ',indent)
		out_str = indent_str
	end
	
	-- Don't print numeric keys
	hasKey = type(name) ~= 'number'
	
	if type(value)=='table' then
	
		if name ~= nil and hasKey then
			out_str = out_str .. tostring(name) .. ' = {'
		else
			out_str = out_str .. '{'
		end
		-- Limit recursion
		if max_indent == nil then max_indent = 6 end		
		if max_indent and indent >= max_indent then
			-- Recursion limit reached
			out_str = out_str .. '[RECURSION LIMIT]'
		else
			-- Recursion is allowed
			for k,v in pairs(value) do
				out_str = out_str .. '\n' .. Dump(v,k,indent+1,max_indent) .. ','
			end
		end
		out_str = out_str .. '\n' .. indent_str .. '}'
        elseif type(value)=='string' then
		if name ~= nil and hasKey then out_str = out_str .. tostring(name).. ' = ' end
		out_str = out_str .. '"' .. value .. '"'
	elseif type(value)=='number' then
		if name ~= nil and hasKey then out_str = out_str .. tostring(name) .. ' = ' end
		out_str = out_str .. tostring(value)
	else
		if name ~= nil and hasKey then out_str = out_str .. tostring(name) .. ' = ' end
		out_str = out_str .. tostring(value)
        end
	return out_str
end

-- Works like dump but splits the job up into smaller writes to save memory
-- EchoDump never returns a value, it goes straight to Echo
function EchoDump(value,name,indent,max_indent)
	
	local out_str = ''
	-- indent
	local indent_str = ''
	if indent == nil then 
		indent = 0
	else
		indent_str = string.rep('  ',indent)
		out_str = indent_str
	end
	
	-- Don't print numeric keys
	hasKey = type(name) ~= 'number'
	
	if type(value)=='table' then
	
		if name ~= nil and hasKey then
			out_str = out_str .. tostring(name) .. ' = {'
		else
			out_str = out_str .. '{'
		end
		Echo(out_str)
		-- Limit recursion
		if max_indent == nil then max_indent = 6 end		
		if max_indent and indent >= max_indent then
			-- Recursion limit reached
			Echo('[RECURSION LIMIT]')
		else
			-- Recursion is allowed
			for k,v in pairs(value) do
				EchoDump(v,k,indent+1,max_indent)
			end
		end
		Echo('\n' .. indent_str .. '}')
		
        elseif type(value)=='string' then
		if name ~= nil and hasKey then out_str = out_str .. tostring(name).. ' = ' end
		Echo(out_str .. '"' .. value .. '"')
	elseif type(value)=='number' then
		if name ~= nil and hasKey then out_str = out_str .. tostring(name) .. ' = ' end
		Echo(out_str .. tostring(value))
	else
		if name ~= nil and hasKey then out_str = out_str .. tostring(name) .. ' = ' end
		Echo(out_str .. tostring(value))
        end
end

-- Calls the given function with the given args, catches any error and Echos a warning including the given msg.
-- Returns nil if the function failed, otherwise returns the function's result.
function Safecall(msg, fn, ...)
    local ok, result = pcall(fn, unpack(arg))
    if ok then
        return result
    else
        Debug("Failed: " .. tostring(msg) .. ":\n" .. result)
        return
    end
end

-- Evaluate a Lua statement stored as a string and return its value
function dostring( str )
	return assert(loadstring('return ' .. str))()
end
Knowledge of Luas debug library and pcall / xpcall will also serve you well.
SirMaverick
Posts: 834
Joined: 19 May 2009, 21:10

Re: [DEBUG] Useful Scripts and Functions

Post by SirMaverick »

Spring.Echo(debug.traceback())
Post Reply

Return to “Lua Scripts”