Episode: 4042 Title: HPR4042: Debugging directly in vim Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4042/hpr4042.mp3 Transcribed: 2025-10-25 18:57:45 --- This is Hacker Public Radio episode 4,042 for Tuesday the 30th of January 2024. Today's show is entitled Debugging Directly in Vim. It is hosted by CRVS and is about 33 minutes long. It carries an explicit flag. The summary is Debug Directly in Vim using term Debug bundled with Vim since Vim 8.1. Hello and welcome to another episode of Hacker Public Radio. Today I will talk a bit about term Debug. Now term Debug is Vim extension that has been there since Vim 8.1. So relatively recent but not exactly new tech. It allows you to use GDB from within Vim quite easily. I found out about it a few days ago at work because I needed to do some debugging. I generally hate debugging because it requires a long compiled cycle etc. etc. It's annoying. You ultimately end up having your code in one place in your editor and then you have your... Then you're probing the code ultimately somewhere else. And you have to sort of jockey back and forth between the two windows. And you know there are some features of so-called more advanced studies that you kind of really miss when you're using them. Like the ability to set break points at the current line. And you know have the debugger when you run the debugger jumps back and forth within your current windows. So that you can actually change the code directly and do the recompilation etc. Doing the recompilation is easy enough. Vim supports make. If you just type co-on make it will run make and whatever errors appear. While from your running of make will appear in your quick fix list. And we'll allow you to jump back and forth between different errors. Now when it comes to debugging it's a bit more difficult. I mean it used to be a bit more difficult. And now it's actually pretty simple ultimately. Therm debug was added in Vim 8.1 because I think that's when the terminal interface in Vim was added ultimately. Before if you then run co-on shell for example it would basically just drop you onto a shell that you can do whatever you're doing. And then you control the exit out of it and you go back to them. Otherwise if you want to just run a line you just do exclamation point. And then exclamation more like co-on exclamation mark and then you run right whatever you want Vim to run and it runs it directly. Therm debug is as I said now the terminal interface allows you to actually use the terminal directly in Vim in a slightly better way. It still has its quirks. It's not 100% like running a native terminal but it is pretty good. Anyway but enough of an introduction there. I'm gonna now switch to telling you a bit more about term debug. So as I said running gdb is generally slightly painful because again you need to compile everything with debug symbols. That's easy enough. Provided you know how your compiler works or your compilation system works. But once you actually done the compilation running it that you run under debugger and then you would like to have a bit more of an integration of that with your editor because that's when you're actually gonna change your variables. Change your code basically. So when you are in Vim here I'm using new Vim because it's slightly better at term debug work slightly better in new Vim but not substantially so. So I'm gonna write a small C file change. I just do some hashtag include. To the U.Age, just a normal hello world, int main, you know, no arguments, open braces, int main, so empty brackets, braces, and then print it. Hello world, and then I'm gonna eventually need to write a bug here. And then return 0, how of course it is. Save it for the C and we have our own hello world that we can work with. Now to compile it, we can just do colon, exclamation.c, minus 0, fill from, fill.c, and that will compile it and fill it in the directory. Okay, so let's call it name instead of fill. Then having a demo effect here. Anyway, once you compile it, you can simply run it by doing information point.slash, main, and it returns hello world, everything is fine. But now let's say that you introduce the error here, and so I'm going to do a signal and start, let's say, just start. Let's say that I want to factor out hello world and put it in your value. And so I put sharp start, green, and equal hello world. And then free depth, I can just do percent s greeting. I can even put the end of line in this greeting. I can just go back there to the here. Say, and I just do that slash, let's see, and now go forward again, sorry about that. Right is fill.c, and right, and free run that constellation, and everything will still work. We're still doing a hello world, that's fantastic. Now, let's say that I want to actually put the greeting in. Let's say that I want to actually factor this out further, so I'm going to just do it. Void and greet, and then it's going to take a sharp start greeting, and it's gone now. Just print f, percent s and greeting. So I can then just do greet, greeting, and actually I can just even put the greeting directly into greet. And everything is fine, still should work. Great, I still have my other world. And I'm setting this, and my makeshift version now is not just appending numbers. And now let's say that once I've done this, I actually realized that sometimes that I don't want to know, so I don't want to always put the new line at the end of the greeting, in case there's already a new line there. So in that case, what I can do, or I can do, is just include str string footage, I think. And let's say, let's use str and I take str and all the greeting. So let's call that end, end is equal to str and all the greeting. Let's give us the length of the greeting, end is equal to new line, then I just print f, the greeting. Other wise, I print f, integrating with the new line. This is still compile, and I run it and it's still run. But let's say I made a mistake, I like to notice it there as f, that's 3. Now let's say I made a mistake and I actually put f, 1. Then I think this is still going to work actually, but here we go. I can pull it, and I ran it and it still works. But now it has one line too many. The reason for that is clear enough, because I know it. But it's just because it does not see the new line. Because the last, I'm actually seeing it. I mean it's fine, but now if I put an end of line after Hello World, then I'm guessing I should get two new lines after this. This is trying to create bugs, this is a really annoying. See it should be more like assembly, everything is a bug. Anyway, what does this, if changing is the last one is, I can do it. I can just actually, what? Okay, now I don't know what's happening. I know what's happening. There we go. Okay, accidentally changed files, that explains it. Anyway, but yeah, now that I have the second line, I actually get two new lines. The second, the new line at the end of the grid, I get two new lines, but I expect it to get only one, even though it gets only one, because it should be the last character. Now this is a good reason to use a debugger, even though I already know what the bug is, which is it should probably look at the element before the last element of the string, but here we go. What can you do? You can then just do pack and turn the bug altogether, turn the ERMDEBUG, and I can do them turn debug over the capital T. Coband altogether, but again look up a little C, and I do dot slash main. And what does that do? That opens a GDV window, where I already have my main file loaded now. And from this GDV window, I can run a turn debug. If I wanted to run it directly, I would add an exclamation point at the end. Now turn debug only runs with only one in one session. So you cannot have multiple debug sessions open at the same time, which would be an ambitious thing to have anyway. But the nice thing, the specifically nice thing about turn debug, is that it separates into two separate windows, the debugger interface, where you're allowed to actually put your debug commands, and the output of the program. The output of the program is kept in a separate window, called that it's labeled as GDV program. And then your source is kept on a third window called source. So if you are in one of these windows, if you are, let's say you're in your GDV window, you can just do colon source with a capital S. And that will move you to the source window. You can do capital colon program with a capital P, and it will move you to the program window. And you can do of course capital GDV with capital G, and you move back to the GDV window. In the GDV window now, this is a terminal window, so if you press I, you go not into insert mode, as you usually would in them, but you go into terminal mode. And in terminal mode, whatever you type here is conceived as a, whatever you, this is just sort of a normal terminal interface. But it has, you know, it has like line numbers, et cetera, et cetera. It's still within bin. So if I press run now, if I write run, again, I would not have to write it if I put an exclamation mark at the end of terminal of term debug command. And if I write run, it will run my program. And it just returns, it just returns me hello world as before. If I run again, it runs me again. And now I can actually see the extra new line is there. Okay. So how can we actually now use this to our advantage? How can we actually take advantage of this interface well? Clearly, we want to know whether or which of the branches we took. So we can just escape from the window, go back to the source. And now we can go to the line where we're checking the last element of the greeting. And we can do a colon break. Let me just do a break. Anyway. Okay. Yeah, anyway. Unless it seems to be a bug with the new of him here, it's having a break point. It seems to actually add some extra characters at the end of the file and then break and then not be able to set a break point, which is weird. I don't have to set my work computer. Anyway, I can just put a break point. I can simulate it by just putting a break point where I want it. Oh. I think I might have compiled the wrong program. I'll just do this again quickly. You see, I'm assuming for the three that see, that is correct. What are you going on about? Another third time is a char. Actually, it is. Let's see. And now I can do the bug. File, name, run, go. Again, everything is running fine. But I can still see it still has the thing that I want to solve, which is I haven't mixed a new one, so I can go now to the source window and there can be a break here. Oh, come on. Okay. I'm getting some problems. I don't know what it is. I don't know what it is. I don't know what it is. Run, okay. And now I can go to the break and it runs again, doesn't work. No source file, name, this. Let's count it. A couple of this. Anyway, for whatever reason, it is not working right now to set a break point in this file. Maybe I actually, no, that is not it. But in the next it works for sure. This is the first time I'm trying it in OpenBSD after getting it to run properly, and that was not possible because then it needs GDP at least 7.12 or 7.6.12, something like that. And that is more modern than the version that OpenBSD comes packaged with. So in order to do that, you need to install it from ports. And that is now named EGDB under OpenBSD once installed from ports. After that, will you just, yeah, you can just normally set the break points, which is not the best, but still beats running it in a separate terminal. So you can use this. This is not. Okay, I figured it out. I did not compile with debug symbols. Wow. That was a stupid thing. Forgive me for the silence here, but this was really positive. Probably someone, some of you noticed that I did not mention to put the minus GDP when I was mentioning the program, the way to compile the compilation. So now that you can just do your run, and yes, now it highlights where in the code the program actually is. So we can, once we go, we put ourselves on top of the if and just write a break with a capital B, and that will introduce a break point on that line. Once that happens, we can just continue. And that we can do by either going to the GDP window and write in continuous count, or just doing colon over because colon over. What is that step? Now that's next. Now you can just do colon continue with capital C and do a continuation. And now we're here greeting and equal equal. And we can evaluate. We can just go to the next line. And we see that we're in the second branch. So now we want maybe this print end. And that we can do by, I think we can do about on top of end and we see it's 13. Now if we go here, hello world, we have 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13. But now 13, since we counted from 1, that's actually 12. That is one past. So that's ultimately telling us what our problem is. So now we can show finally the thing that I said that we should have done since the beginning to subtract 1 from sterland to get the actual end. Once that is done, we can once again compile our code. Go back to the GDP window, the file name that will substitute the file. Notice this substitution of the file is important because it doesn't substitute the arguments. If there were any arguments, which you can just pass by doing when you run GDP on a program with a bunch of arguments of GDP minus minus args and then whatever you feed it. Here you can also write, I think, args in GDP to change the arguments. You can also just write file command on the term deeper command. You can put all your arguments in front. Are you sure you want to change the file? Yes. Load me symbols from main, yes. And now you can run again. Start from the beginning. Now you probably want to do all. Coolier. Coolier, but coolier. Okay, fine. We have to create a one by one. Don't make too many breakpoints. Okay, run again and now it runs a low world with a single new line character. Yeah. So you see, more of the story, debugging is painful. It remains painful after having a better interface to do it. But it's slightly less painful than it was before. Anyway, hope this is useful to anyone. Hope you were entertained or otherwise accompanied by my debugging of a very simple program. And hope that if you use them, you will give term debug a try. It's a very nice extension that comes included with them since version 8.1. And it is also available in NeoVim. I think that NeoVim version is slightly better because it has the line numbers always on the terminal. But maybe those are just different defaults that Vim has. Because it just happens that once you get out from terminal mode, suddenly the line numbers appear and it's annoying. But yeah, hope you give all of us a try. And don't forget to tune in tomorrow for another exciting episode of hacker public radio. And I'm going to get a file and there we go. Close now. Bye bye. This has been CRBS. You have been listening to Hacker Public Radio at Hacker Public Radio does work. Today's show was contributed by a HBR listener like yourself. If you ever thought of recording a podcast, then click on our contribute link to find out how easy it leads. Hosting for HBR has been kindly provided by an honesthost.com, internet archive and our syncs.net. On the Sadois stages, today's show is released under Creative Commons Attribution 4.0 International License.