Difference between revisions of "love.errorhandler"

m (fixed newin.)
 
(4 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{newin|[[11.0]]|110|type=function|text=It has been renamed from [[love.errhand]]}}
 
{{newin|[[11.0]]|110|type=function|text=It has been renamed from [[love.errhand]]}}
 
The error handler, used to display error messages.
 
The error handler, used to display error messages.
{{notice|Note that if the error handler itself throws error, LÖVE only prints the error in the console and exit immediately!}}
+
{{notice|Note that if there's an error in the error handler function, LÖVE will exit immediately!}}
 +
 
 
== Function ==
 
== Function ==
 
=== Synopsis ===
 
=== Synopsis ===
Line 10: Line 11:
 
{{param|string|msg|The error message.}}
 
{{param|string|msg|The error message.}}
 
=== Returns ===
 
=== Returns ===
{{param|function|mainLoop|Function which handles one frame, including events and rendering, when called.}}
+
{{param|function|mainLoop|Function which handles one frame, including events and rendering, when called. If this is nil then LÖVE exits immediately.}}
 +
 
 
== Examples ==
 
== Examples ==
 +
=== The default function used if you don't supply your own. ===
 +
{{newin|[[11.4]]|114|type=variant}}
 +
<source lang="Lua">
 +
local utf8 = require("utf8")
 +
 +
local function error_printer(msg, layer)
 +
print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
 +
end
 +
 +
function love.errorhandler(msg)
 +
msg = tostring(msg)
 +
 +
error_printer(msg, 2)
 +
 +
if not love.window or not love.graphics or not love.event then
 +
return
 +
end
 +
 +
if not love.graphics.isCreated() or not love.window.isOpen() then
 +
local success, status = pcall(love.window.setMode, 800, 600)
 +
if not success or not status then
 +
return
 +
end
 +
end
 +
 +
-- Reset state.
 +
if love.mouse then
 +
love.mouse.setVisible(true)
 +
love.mouse.setGrabbed(false)
 +
love.mouse.setRelativeMode(false)
 +
if love.mouse.isCursorSupported() then
 +
love.mouse.setCursor()
 +
end
 +
end
 +
if love.joystick then
 +
-- Stop all joystick vibrations.
 +
for i,v in ipairs(love.joystick.getJoysticks()) do
 +
v:setVibration()
 +
end
 +
end
 +
if love.audio then love.audio.stop() end
 +
 +
love.graphics.reset()
 +
local font = love.graphics.setNewFont(14)
 +
 +
love.graphics.setColor(1, 1, 1)
 +
 +
local trace = debug.traceback()
 +
 +
love.graphics.origin()
 +
 +
local sanitizedmsg = {}
 +
for char in msg:gmatch(utf8.charpattern) do
 +
table.insert(sanitizedmsg, char)
 +
end
 +
sanitizedmsg = table.concat(sanitizedmsg)
 +
 +
local err = {}
 +
 +
table.insert(err, "Error\n")
 +
table.insert(err, sanitizedmsg)
 +
 +
if #sanitizedmsg ~= #msg then
 +
table.insert(err, "Invalid UTF-8 string in error message.")
 +
end
 +
 +
table.insert(err, "\n")
 +
 +
for l in trace:gmatch("(.-)\n") do
 +
if not l:match("boot.lua") then
 +
l = l:gsub("stack traceback:", "Traceback\n")
 +
table.insert(err, l)
 +
end
 +
end
 +
 +
local p = table.concat(err, "\n")
 +
 +
p = p:gsub("\t", "")
 +
p = p:gsub("%[string \"(.-)\"%]", "%1")
 +
 +
local function draw()
 +
if not love.graphics.isActive() then return end
 +
local pos = 70
 +
love.graphics.clear(89/255, 157/255, 220/255)
 +
love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
 +
love.graphics.present()
 +
end
 +
 +
local fullErrorText = p
 +
local function copyToClipboard()
 +
if not love.system then return end
 +
love.system.setClipboardText(fullErrorText)
 +
p = p .. "\nCopied to clipboard!"
 +
end
 +
 +
if love.system then
 +
p = p .. "\n\nPress Ctrl+C or tap to copy this error"
 +
end
 +
 +
return function()
 +
love.event.pump()
 +
 +
for e, a, b, c in love.event.poll() do
 +
if e == "quit" then
 +
return 1
 +
elseif e == "keypressed" and a == "escape" then
 +
return 1
 +
elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
 +
copyToClipboard()
 +
elseif e == "touchpressed" then
 +
local name = love.window.getTitle()
 +
if #name == 0 or name == "Untitled" then name = "Game" end
 +
local buttons = {"OK", "Cancel"}
 +
if love.system then
 +
buttons[3] = "Copy to clipboard"
 +
end
 +
local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
 +
if pressed == 1 then
 +
return 1
 +
elseif pressed == 3 then
 +
copyToClipboard()
 +
end
 +
end
 +
end
 +
 +
draw()
 +
 +
if love.timer then
 +
love.timer.sleep(0.1)
 +
end
 +
end
 +
 +
end
 +
</source>
 +
----
 +
{{newinoldin|[[11.0]]|110|[[11.4]]|114|type=variant}}
 
=== The default function used if you don't supply your own. ===
 
=== The default function used if you don't supply your own. ===
 
<source lang="Lua">
 
<source lang="Lua">
Line 148: Line 286:
 
== See Also ==
 
== See Also ==
 
* [[parent::love]]
 
* [[parent::love]]
 +
* [[love.run]]
 +
 +
== Other Languages ==
 +
{{i18n|love.errorhandler}}
 +
 
[[Category:Callbacks]]
 
[[Category:Callbacks]]
 
{{#set:Description=The error handler, used to display error messages.}}
 
{{#set:Description=The error handler, used to display error messages.}}
 
{{#set:Subcategory=General}}
 
{{#set:Subcategory=General}}
== Other Languages ==
 
{{i18n|love.errorhandler}}
 

Latest revision as of 12:24, 8 July 2023

Available since LÖVE 11.0
It has been renamed from love.errhand.

The error handler, used to display error messages.

O.png Note that if there's an error in the error handler function, LÖVE will exit immediately!  


Function

Synopsis

mainLoop = love.errorhandler( msg )

Arguments

string msg
The error message.

Returns

function mainLoop
Function which handles one frame, including events and rendering, when called. If this is nil then LÖVE exits immediately.

Examples

The default function used if you don't supply your own.

Available since LÖVE 11.4
This variant is not supported in earlier versions.
local utf8 = require("utf8")

local function error_printer(msg, layer)
	print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end

function love.errorhandler(msg)
	msg = tostring(msg)

	error_printer(msg, 2)

	if not love.window or not love.graphics or not love.event then
		return
	end

	if not love.graphics.isCreated() or not love.window.isOpen() then
		local success, status = pcall(love.window.setMode, 800, 600)
		if not success or not status then
			return
		end
	end

	-- Reset state.
	if love.mouse then
		love.mouse.setVisible(true)
		love.mouse.setGrabbed(false)
		love.mouse.setRelativeMode(false)
		if love.mouse.isCursorSupported() then
			love.mouse.setCursor()
		end
	end
	if love.joystick then
		-- Stop all joystick vibrations.
		for i,v in ipairs(love.joystick.getJoysticks()) do
			v:setVibration()
		end
	end
	if love.audio then love.audio.stop() end

	love.graphics.reset()
	local font = love.graphics.setNewFont(14)

	love.graphics.setColor(1, 1, 1)

	local trace = debug.traceback()

	love.graphics.origin()

	local sanitizedmsg = {}
	for char in msg:gmatch(utf8.charpattern) do
		table.insert(sanitizedmsg, char)
	end
	sanitizedmsg = table.concat(sanitizedmsg)

	local err = {}

	table.insert(err, "Error\n")
	table.insert(err, sanitizedmsg)

	if #sanitizedmsg ~= #msg then
		table.insert(err, "Invalid UTF-8 string in error message.")
	end

	table.insert(err, "\n")

	for l in trace:gmatch("(.-)\n") do
		if not l:match("boot.lua") then
			l = l:gsub("stack traceback:", "Traceback\n")
			table.insert(err, l)
		end
	end

	local p = table.concat(err, "\n")

	p = p:gsub("\t", "")
	p = p:gsub("%[string \"(.-)\"%]", "%1")

	local function draw()
		if not love.graphics.isActive() then return end
		local pos = 70
		love.graphics.clear(89/255, 157/255, 220/255)
		love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
		love.graphics.present()
	end

	local fullErrorText = p
	local function copyToClipboard()
		if not love.system then return end
		love.system.setClipboardText(fullErrorText)
		p = p .. "\nCopied to clipboard!"
	end

	if love.system then
		p = p .. "\n\nPress Ctrl+C or tap to copy this error"
	end

	return function()
		love.event.pump()

		for e, a, b, c in love.event.poll() do
			if e == "quit" then
				return 1
			elseif e == "keypressed" and a == "escape" then
				return 1
			elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
				copyToClipboard()
			elseif e == "touchpressed" then
				local name = love.window.getTitle()
				if #name == 0 or name == "Untitled" then name = "Game" end
				local buttons = {"OK", "Cancel"}
				if love.system then
					buttons[3] = "Copy to clipboard"
				end
				local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
				if pressed == 1 then
					return 1
				elseif pressed == 3 then
					copyToClipboard()
				end
			end
		end

		draw()

		if love.timer then
			love.timer.sleep(0.1)
		end
	end

end

Available since LÖVE 11.0 and removed in LÖVE 11.4
This variant is not supported in earlier or later versions.

The default function used if you don't supply your own.

local utf8 = require("utf8")

local function error_printer(msg, layer)
	print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
end

function love.errorhandler(msg)
	msg = tostring(msg)

	error_printer(msg, 2)

	if not love.window or not love.graphics or not love.event then
		return
	end

	if not love.graphics.isCreated() or not love.window.isOpen() then
		local success, status = pcall(love.window.setMode, 800, 600)
		if not success or not status then
			return
		end
	end

	-- Reset state.
	if love.mouse then
		love.mouse.setVisible(true)
		love.mouse.setGrabbed(false)
		love.mouse.setRelativeMode(false)
		if love.mouse.isCursorSupported() then
			love.mouse.setCursor()
		end
	end
	if love.joystick then
		-- Stop all joystick vibrations.
		for i,v in ipairs(love.joystick.getJoysticks()) do
			v:setVibration()
		end
	end
	if love.audio then love.audio.stop() end

	love.graphics.reset()
	local font = love.graphics.setNewFont(14)

	love.graphics.setColor(1, 1, 1, 1)

	local trace = debug.traceback()

	love.graphics.origin()

	local sanitizedmsg = {}
	for char in msg:gmatch(utf8.charpattern) do
		table.insert(sanitizedmsg, char)
	end
	sanitizedmsg = table.concat(sanitizedmsg)

	local err = {}

	table.insert(err, "Error\n")
	table.insert(err, sanitizedmsg)

	if #sanitizedmsg ~= #msg then
		table.insert(err, "Invalid UTF-8 string in error message.")
	end

	table.insert(err, "\n")

	for l in trace:gmatch("(.-)\n") do
		if not l:match("boot.lua") then
			l = l:gsub("stack traceback:", "Traceback\n")
			table.insert(err, l)
		end
	end

	local p = table.concat(err, "\n")

	p = p:gsub("\t", "")
	p = p:gsub("%[string \"(.-)\"%]", "%1")

	local function draw()
		local pos = 70
		love.graphics.clear(89/255, 157/255, 220/255)
		love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
		love.graphics.present()
	end

	local fullErrorText = p
	local function copyToClipboard()
		if not love.system then return end
		love.system.setClipboardText(fullErrorText)
		p = p .. "\nCopied to clipboard!"
		draw()
	end

	if love.system then
		p = p .. "\n\nPress Ctrl+C or tap to copy this error"
	end

	return function()
		love.event.pump()

		for e, a, b, c in love.event.poll() do
			if e == "quit" then
				return 1
			elseif e == "keypressed" and a == "escape" then
				return 1
			elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
				copyToClipboard()
			elseif e == "touchpressed" then
				local name = love.window.getTitle()
				if #name == 0 or name == "Untitled" then name = "Game" end
				local buttons = {"OK", "Cancel"}
				if love.system then
					buttons[3] = "Copy to clipboard"
				end
				local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
				if pressed == 1 then
					return 1
				elseif pressed == 3 then
					copyToClipboard()
				end
			end
		end

		draw()

		if love.timer then
			love.timer.sleep(0.1)
		end
	end

end

See Also

Other Languages