orbitalquark / textadept

Textadept is a fast, minimalist, and remarkably extensible cross-platform text editor for programmers.
https://orbitalquark.github.io/textadept
MIT License
636 stars 38 forks source link

Hard Crash when Unsplitting View with Focus with v12 #452

Closed eric1234 closed 1 year ago

eric1234 commented 1 year ago

I have a module that helps me manage split screens better on wide-screen monitors. With v12, my module started crashing Textadept when I unsplit sometimes. I've been working on trying to get to simple reproducible steps. I have confirmed this happens on both Linux and OSX.

While most of the details of the module are not important, the key thing is when it needs to add a new split it always adds to the last view like this:

_VIEWS[#_VIEWS]:split(true)

When it needs to remove a split it always removes the last one by unsplitting the second to last one:

_VIEWS[#_VIEWS-1]:unsplit()

What I finally figured out was that if the last view had the focus that lead to the crash. Therefore reproducible steps are:

  1. Split the window by hitting Ctrl-E to get the Lua command prompt and typing _VIEWS[#_VIEWS]:split(true) and nil (the and nil is just to prevent output).
  2. Focus on the split on the right.
  3. Hit Ctrl-E to get the Lua command prompt again and type _VIEWS[#_VIEWS-1]:unsplit() and nil. At this point it will do a hard crash.

If you change "Step 2" to focus on the original view on the left it executes the unsplit without a problem.

I've also confirmed this happens on the stock .textadept config so it's not related to my other modifications. If I use the built-in split and unsplit functions I get no crash regardless of the window focus but I suspect that is because it's calling unsplit on the last one not the second to last one.

I might be able to work around this by updating the focus to to a different view if the focus is on the view being closed but I've search the API docs and haven't been able to figure out how to programmatically change the view focus yet.

eric1234 commented 1 year ago

I might be able to work around this by updating the focus to to a different view if the focus is on the view being closed but I've search the API docs and haven't been able to figure out how to programmatically change the view focus yet.

I'm an idiot as another piece of code in that same module does change the view focus. The function I was looking for was ui.goto_view. If I prepend ui.goto_view(_VIEWS[#_VIEWS-1]) prior to my unsplit no more crashing. Therefore is the answer to maybe handle this within Lua and have unsplit automatically move the focus if the item being removed is focused?

orbitalquark commented 1 year ago

Thanks for the detailed report. It seems that calling unsplit on a non-focused view resulted in undefined behavior. This should be fixed via https://github.com/orbitalquark/textadept/commit/c659b31645c64c79db10d14aada80303a1561705.

Regardless, if you want control over which view has focus after a split, it is wise to call ui.goto_view() if you're going to call unsplit() on something other than view.

orbitalquark commented 1 year ago

Actually, forget that last bit of my comment. You can always call ui.goto_view() after the fact since Textadept hasn't crashed :)