#Complex issue with initial cursor movement in my TUI app

33 messages · Page 1 of 1 (latest)

gilded dock
#

I'm working on a text editor and a TUI library at the same time. As you can see in the gif, if I move the cursor up and down, it's hitting a certain point and moving on a diagonal. I've been chasing this bug for a few weeks and I need a second pair of eyes to work out what the problem is, because I'm out of ideas.

I believe the problem may come down to redrawing the screen on each cursor press. When I press the down key (j), this code is triggered. This moves the cursor down and redraws. The logging for these lines look like this:

[INFO] Action called: MoveCursorDown
[INFO] Pos(6, 6)
[INFO] Pos(6, 6)
[INFO] Action called: MoveCursorDown
[INFO] Pos(7, 6)
[INFO] Pos(7, 7)
[INFO] Action called: MoveCursorDown
[INFO] Pos(8, 7)
[INFO] Pos(8, 8)

As you can see, it moves down on the move_cur_down() call (line 45) and then moves right on the redraw for some reason. Through a chain of functions, the redraw_pane() calls this draw function in the aformentioned library, and part of me is suspicious about the move_cur_out_of_blacklist() call at the end, although that function looks perfectly fine? The while loop shouldn't be triggering, and doesn't seem to be from what testing I've done.

The reason the number 6 stands out, btw, is this line that I'm using to generate the line numbers - the file I'm opening is 100~ lines long, plus 1 trailing box-drawing character, plus the first column should always be empty, so the 6th character in the column is where the file's text is first being drawn, and the cursor shouldn't be able to go into the box-drawing char.

I've been honestly tearing my hair out about all of this for almost two weeks, I'm hoping someone else can spot something I've missed. Thank you

neat loomBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

fickle fiber
#

this is the type of bug where a debugger will show you exactly why/how/where the logic starts pushing the cursor horizontally, have you tried using one yet to try to narrow this down?

gilded dock
#

Yea, I’ve run through it with a debugger a few times and everything appears to be fine - I never am able to get to that one move_cur_out_of_blacklist() function with a debugger because i disable any functions that print actually printing during debugging (the environment variable) - otherwise it makes GDB impossible to work with.

I’ll give offsetting a go, I hadn’t thought of that

fickle fiber
#

it seems to be working ok for me unless the issue only appears when you're working with a file that has text in it other than newlines

#

i was able to break it in a few different ways from resizing the terminal or adjusting the font size while editing, sometimes it would put a character out of reach of the cursor. other times the bottom status bar would start repeating, but I didn't see the cursor start to move horizontally.

you may want to make sure that the cursor's movement steps are in terminal x,y positions and not bytes (multi-byte/variable-sized unicode codepoints will become a pain later on if it's moving it in bytes).

you may also want to experiment with block style cursors and line cursors if what i tried in the screen capture above leads the cursor to start walking horizontally for you. if that ends up being the case it could end up being an off-by-1 logic bug hiding in plain sight.

#

i just tried it out with one of the source files in your project and it also seems to be working ok using a file that contains some text

#

if either of those lead to the horizontal movement for you, it's probably worth checking your terminal settings to see if there's anything in there that could be throwing things off for some reason

gilded dock
#

Looks like you’re on the main branch - checkout cursor-movement. I’m in the middle of rewriting a bunch of stuff because I changed the architecture in it

fickle fiber
#

ok i can give that a try now

fickle fiber
#

hey mb, not sure if you're still around but i got a bit distracted earlier and forgot to look into this. i just checked out that branch and started debugging it a bit. i'm pretty sure the main issue is that you're muting an exception (empty catch), so it's hiding the fact that something went wrong.

#

i was just debugging right and left movement and i'm pretty sure the blacklist region is detected as overlapping for a few iterations longer than it should be. the way you're calling the movement function seems to be fine btw, coordinates come back as expected after that... but the render function does a bunch of its own cursor movement in it. i'm pretty sure that's where things are going wrong at a glance

gilded dock
#

Thank you for taking a look. The empty catches, you’re talking about in iris/src/view.cpp?

I was suspicious of the rawterm/rawterm/extras/pane.h draw function’s cursor movement, but i don’t entirely know how I could replace it without breaking the background colour rendering per cell. I’ll have a think around it and see what I can come up with — got a busy day of work ahead of me first. :p

neat loomBOT
#

@gilded dock Has your question been resolved? If so, type !solved :)

fickle fiber
#

it was a bug in the library

#

i'm guessing that's why you had those exceptions muted (still a bad idea, always log them and/or just assert(false) at the very least)

#

i have ended up making minor adjustments/improvements to random code as i was debugging things in your cursor-movement branch btw... did you want me to push a branch with that stuff into your repo?

gilded dock
#

Oh god, if that’s all it is…

Sure, the PR is appreciated, please do. And terminal indexing starts at 1, not 0 (but the terminal itself doesn’t complain if you go to 0,0 - however moving from 0,0 to 0,1 using absolute values won’t do anything).

The try catches aren’t meant to be empty - I’ve just not written anything in them yet. I don’t want the error to be silent

fickle fiber
#

haha yeah i'm pretty sure it is... it seemed to be working ok after making that library edit locally, but i didn't really test it too much

#

i'd really think about making it use 0-based indexing for the screen buffer btw... i started second guessing every +1 or -1 anywhere in both codebases haha

#

the only part of the pane that needs to be 1-based are the line numbers and line column offsets that you'll be displaying, and that stuff is way easier to calculate when you're drawing it rather than having retraining yourself to use 1 based indexing for the screen buffer itself

#

i'd also be pretty tempted to pull in fmt to handle the coloring and special characters since std::cout will get painful (plus you won't have to worry about the regex part if you can just use fmt to apply the coloring. it can even print blinking text). not sure if you were planning on keeping it all pure or if you were open to that type of thing, but it'll really simplify certain parts.

#

oh, yeah, also... i wasn't sure if this part wasn't fully implemented yet (or just in the middle of being changed around), but it seems like you're using the Model object for some rendering and View for other parts. i don't know too much about all of those different GUI programming patterns but I want to say if you just use those two the model should hold the state/data and then the view uses that to decide how/when/where to display the changes. keeping the design consistent will always help avoid mistakes.

gilded dock
#

I’d like to keep everything in-house, (kinda a NIH thing) so I’d rather not switch to fmt, at least for this project, but I’ll keep it in mind for the future.

Regarding the model/view. I knew I’d need a conversion between a way the gap buffer stored the data and the way the pane_manager would display it - I thought this order would make more sense, to render out the model in a manner useful for the pane_manager (especially the state includes elements displayed on the status bar). The interchange between the two i wasn’t too sure about.

fickle fiber
#

std::format / std::print also handles that stuff better than cout, i think i replaced some string concatenation code with std::format just to control how the info in the bottom bar was aligned in an easier way (i also might have changed the original layout you had for that)... i forget why i messed with it though haha. i think something was indexing out of bounds or something so i just made sure it would keep that bottom text clamped to the screen size and truncate each section as needed.

gilded dock
#

Yea, I’m vaguely trying to replicate MVC, but I’m not too familiar with it so I’m mostly going off the names and a single go TUI I write before that used MVC arch. I think I read the wiki page at first, but there wasn’t much on the interplay between the two? I’ll take another look

#

Btw, if you want to throw up a quick PR to show the changes you made, feel free to. 🙂 I believe you mentioned it before

fickle fiber
#

the MS docs might also help give you another source of info about those design patterns with code examples btw. i'm pretty sure some of their UI library designs are based on MVVM, but nowadays most of it seems to be MVC. The actual code they show probably won't matter too much, but the attributes/properties/behavior of each component should be clarified by seeing what they require for each of them. A lot of their stuff works through binding XML fields to callbacks/event listeners in the C# layer to communicate between components... i've been working on a VS extension recently so i've been dealing with plenty of their frameworks and documentation for this stuff:
https://learn.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-8.0&WT.mc_id=dotnet-35129-website#mvc-pattern
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-8.0&tabs=visual-studio