Skip to content

Commit 36b99bf

Browse files
committed
Add interactive debugger.
Adds a new interactive debugger based on [debugger.lua](https://github.com/slembcke/debugger.lua). Premake already contains some remove debugger integration (MobDebug), however this PR introduces an integrated debugger, any call to `dbg()` will launch the user into an interactive GDB-like TUI shell to allow interactive debugging on the spot.
1 parent 28ac93d commit 36b99bf

File tree

7 files changed

+1219
-0
lines changed

7 files changed

+1219
-0
lines changed

Diff for: contrib/debugger.lua/LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2024 Scott Lembcke and Howling Moon Software
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

Diff for: contrib/debugger.lua/README.md

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
🐞 debugger.lua 🌖
2+
=
3+
4+
A simple, embedabble debugger for Lua 5.x, and LuaJIT 2.x.
5+
6+
![ExampleLog](https://raw.githubusercontent.com/slembcke/debugger.lua/ec29cc13224750d109383c949950d7cafd6fcbdf/debugger_lua.png)
7+
8+
debugger.lua is a simple, single file, pure Lua debugger that is easy to integrate with any project. The lua-users wiki lists a [number of debuggers](http://lua-users.org/wiki/DebuggingLuaCode). clidebugger was closest to what I was looking for, but I ran into several compatibility issues, and the rest are pretty big libraries with a whole lot of dependencies. I just wanted something simple to integrate that would work through stdin/stdout. I also decided that it sounded fun to try and make my own!
9+
10+
✅ Features
11+
-
12+
13+
- Trivial to "install". Can be integrated as a single .lua _or_ .h file.
14+
- The regular assortment of commands you'd expect from a debugger: continue, step, next, finish, print/eval expression, move up/down the stack, backtrace, print locals, inline help.
15+
- Evaluate expressions, call functions interactively, and get/set variables.
16+
- Pretty printed output so you see `{1 = 3, "a" = 5}` instead of `table: 0x10010cfa0`
17+
- Speed! The debugger hooks are only set during the step/next/finish commands.
18+
- Conditional, assert-style breakpoints.
19+
- Colored output and line editing support when possible.
20+
- Drop in replacements for Lua's `assert()`, `error()`, and `pcall()` functions that trigger the debugger.
21+
- When using the C API, `dbg_call()` works as a drop-in replacement for `lua_pcall()`.
22+
- IO can easily be remapped to a socket or window by overwriting the `dbg.write()` and `dbg.read()` functions.
23+
- Permissive MIT license.
24+
25+
🙌 Easy to use from C too!
26+
-
27+
28+
debugger.lua can be easily integrated into an embedded project with just a .h file. First though, you'll need to run `lua make_c_header.lua`. This generates debugger_lua.h by inserting the lua code into a template .h file.
29+
30+
```c
31+
// You need to define this in one of your C files. (and only one!)
32+
#define DEBUGGER_LUA_IMPLEMENTATION
33+
#include "debugger_lua.h"
34+
35+
int main(int argc, char **argv){
36+
// Do normal Lua init stuff.
37+
lua_State *lua = luaL_newstate();
38+
luaL_openlibs(lua);
39+
40+
// Load up the debugger module as "debugger".
41+
// Also stores it in a global variable "dbg".
42+
// Use dbg_setup() to change these or use custom I/O.
43+
dbg_setup_default(lua);
44+
45+
// Load some buggy Lua code.
46+
luaL_loadstring(lua,
47+
"local num = 1 \n"
48+
"local str = 'one' \n"
49+
"local res = num + str \n"
50+
);
51+
52+
// Run it in the debugger. This function works just like lua_pcall() otherwise.
53+
// Note that setting your own custom message handler disables the debugger.
54+
if(dbg_pcall(lua, 0, 0, 0)){
55+
fprintf(stderr, "Lua Error: %s\n", lua_tostring(lua, -1));
56+
}
57+
}
58+
```
59+
60+
Now in your Lua code you can access `dbg` or use `require 'debugger'`.
61+
62+
🐝 Debugger Commands:
63+
-
64+
65+
If you have used other CLI debuggers, debugger.lua shouldn't be surprising. I didn't make a fancy parser, so the commands are just single letters. Since the debugger is pretty simple there are only a small handful of commands anwyay.
66+
67+
[return] - re-run last command
68+
c(ontinue) - contiue execution
69+
s(tep) - step forward by one line (into functions)
70+
n(ext) - step forward by one line (skipping over functions)
71+
p(rint) [expression] - execute the expression and print the result
72+
f(inish) - step forward until exiting the current function
73+
u(p) - move up the stack by one frame
74+
d(own) - move down the stack by one frame
75+
w(here) [line count] - print source code around the current line
76+
t(race) - print the stack trace
77+
l(ocals) - print the function arguments, locals and upvalues.
78+
h(elp) - print this message
79+
q(uit) - halt execution
80+
81+
If you've never used a command line debugger before, start a nice warm cozy fire, run tutorial.lua, and open it up in your favorite editor so you can follow along.
82+
83+
🦋 Debugger API
84+
-
85+
86+
There are several overloadable functions you can use to customize debugger.lua.
87+
* `dbg.read(prompt)` - Show the prompt and block for user input. (Defaults to read from stdin)
88+
* `dbg.write(str)` - Write a string to the output. (Defaults to write to stdout)
89+
* `dbg.shorten_path(path)` - Return a shortened version of a path. (Defaults to simply return `path`)
90+
* `dbg.exit(err)` - Stop debugging. (Defaults to `os.exit(err)`)
91+
* `dbg.pretty(obj)` - Output a pretty print string for an object. (Defaults to a reasonable version using __tostring metamethods and such)
92+
93+
Using these you can customize the debugger to work in your environment. For instance, you can divert the I/O over a network socket or to a GUI window.
94+
95+
There are also some goodies you can use to make debugging easier.
96+
* `dbg.writeln(format, ...)` - Basically the same as `dbg.write(string.format(format.."\n", ...))`
97+
* `dbg.pretty_depth = int` - Set how deep `dbg.pretty()` formats tables.
98+
* `dbg.pretty(obj)` - Will return a pretty print string of an object.
99+
* `dbg.pp(obj)` - Basically the same as `dbg.writeln(dbg.pretty(obj))`
100+
* `dbg.auto_where = int_or_false` - Set the where command to run automatically when the active line changes. The value is the number of context lines.
101+
* `dbg.error(error, [level])` - Drop in replacement for `error()` that breaks in the debugger.
102+
* `dbg.assert(error, [message])` - Drop in replacement for `assert()` that breaks in the debugger.
103+
* `dbg.call(f, ...)` - Drop in replacement for `pcall()` that breaks in the debugger.
104+
105+
🪲 Environment Variables:
106+
-
107+
108+
Want to disable ANSI color support or disable GNU readline? Set the `DBG_NOCOLOR` and/or `DBG_NOREADLINE` environment variables.
109+
110+
🕷️ Known Issues:
111+
-
112+
113+
- Lua 5.1 lacks the API to access varargs. The workaround is to do something like `local args = {...}` and then use `unpack(args)` when you want to access them. In Lua 5.2+ and LuaJIT, you can simply use `...` in your expressions with the print command.
114+
- You can't add breakpoints to a running program or remove them. Currently the only way to set them is by explicitly calling the `dbg()` function explicitly in your code. (This is sort of by design and sort of because it's difficult/slow otherwise.)
115+
- Different interpreters (and versions) print out slightly different stack trace information.
116+
- Tail calls are handled silghtly differently in different interpreters. You may find that 1.) stepping into a function that does nothing but a tail call steps you into the tail called function. 2.) The interpreter gives you the wrong name of a tail called function (watch the line numbers). 3.) Stepping out of a tail called function also steps out of the function that performed the tail call. Mostly this is never a problem, but it is a little confusing if you don't know what is going on.
117+
- Coroutine support has not been tested extensively yet, and Lua vs. LuaJIT handle them differently anyway. -_-
118+
119+
🪰 License:
120+
-
121+
122+
Copyright (c) 2024 Scott Lembcke and Howling Moon Software
123+
124+
Permission is hereby granted, free of charge, to any person obtaining a copy
125+
of this software and associated documentation files (the "Software"), to deal
126+
in the Software without restriction, including without limitation the rights
127+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
128+
copies of the Software, and to permit persons to whom the Software is
129+
furnished to do so, subject to the following conditions:
130+
131+
The above copyright notice and this permission notice shall be included in
132+
all copies or substantial portions of the Software.
133+
134+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
135+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
136+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
137+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
138+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
139+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
140+
SOFTWARE.

0 commit comments

Comments
 (0)