errhand.lua 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. local utf8 = require("utf8")
  2. local function error_printer(msg, layer)
  3. print((debug.traceback("Error: " .. tostring(msg), 1+(layer or 1)):gsub("\n[^\n]+$", "")))
  4. end
  5. function love.errorhandler(msg)
  6. msg = tostring(msg)
  7. error_printer(msg, 2)
  8. if not love.window or not love.graphics or not love.event then
  9. return
  10. end
  11. if not love.graphics.isCreated() or not love.window.isOpen() then
  12. local success, status = pcall(love.window.setMode, 800, 600)
  13. if not success or not status then
  14. return
  15. end
  16. end
  17. -- Reset state.
  18. if love.mouse then
  19. love.mouse.setVisible(true)
  20. love.mouse.setGrabbed(false)
  21. love.mouse.setRelativeMode(false)
  22. if love.mouse.isCursorSupported() then
  23. love.mouse.setCursor()
  24. end
  25. end
  26. if love.joystick then
  27. -- Stop all joystick vibrations.
  28. for i,v in ipairs(love.joystick.getJoysticks()) do
  29. v:setVibration()
  30. end
  31. end
  32. if love.audio then love.audio.stop() end
  33. love.graphics.reset()
  34. local font = love.graphics.setNewFont(14)
  35. love.graphics.setColor(1, 1, 1, 1)
  36. local trace = debug.traceback()
  37. love.graphics.origin()
  38. local sanitizedmsg = {}
  39. for char in msg:gmatch(utf8.charpattern) do
  40. table.insert(sanitizedmsg, char)
  41. end
  42. sanitizedmsg = table.concat(sanitizedmsg)
  43. local err = {}
  44. table.insert(err, "Error\n")
  45. table.insert(err, sanitizedmsg)
  46. if #sanitizedmsg ~= #msg then
  47. table.insert(err, "Invalid UTF-8 string in error message.")
  48. end
  49. table.insert(err, "\n")
  50. for l in trace:gmatch("(.-)\n") do
  51. if not l:match("boot.lua") then
  52. l = l:gsub("stack traceback:", "Traceback\n")
  53. table.insert(err, l)
  54. end
  55. end
  56. local p = table.concat(err, "\n")
  57. p = p:gsub("\t", "")
  58. p = p:gsub("%[string \"(.-)\"%]", "%1")
  59. local function draw()
  60. local pos = 70
  61. love.graphics.clear(89/255, 157/255, 220/255)
  62. love.graphics.printf(p, pos, pos, love.graphics.getWidth() - pos)
  63. love.graphics.present()
  64. end
  65. local fullErrorText = p
  66. local function copyToClipboard()
  67. if not love.system then return end
  68. love.system.setClipboardText(fullErrorText)
  69. p = p .. "\nCopied to clipboard!"
  70. draw()
  71. end
  72. if love.system then
  73. p = p .. "\n\nPress Ctrl+C or tap to copy this error"
  74. end
  75. return function()
  76. love.event.pump()
  77. for e, a, b, c in love.event.poll() do
  78. if e == "quit" then
  79. return 1
  80. elseif e == "keypressed" and a == "escape" then
  81. return 1
  82. elseif e == "keypressed" and a == "c" and love.keyboard.isDown("lctrl", "rctrl") then
  83. copyToClipboard()
  84. elseif e == "touchpressed" then
  85. local name = love.window.getTitle()
  86. if #name == 0 or name == "Untitled" then name = "Game" end
  87. local buttons = {"OK", "Cancel"}
  88. if love.system then
  89. buttons[3] = "Copy to clipboard"
  90. end
  91. local pressed = love.window.showMessageBox("Quit "..name.."?", "", buttons)
  92. if pressed == 1 then
  93. return 1
  94. elseif pressed == 3 then
  95. copyToClipboard()
  96. end
  97. end
  98. end
  99. draw()
  100. if love.timer then
  101. love.timer.sleep(0.1)
  102. end
  103. end
  104. end