-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
action: Stop processing chained actions/commands in the moment the current Pane
is not a BufPane
(fix crash)
#3261
Conversation
internal/action/tab.go
Outdated
@@ -345,10 +347,16 @@ func (t *Tab) Resize() { | |||
} | |||
|
|||
// CurPane returns the currently active pane | |||
func (t *Tab) CurPane() *BufPane { | |||
p, ok := t.Panes[t.active].(*BufPane) | |||
func (t *Tab) CurPane() Pane { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not keep it returning *BufPane
, and in the callers just check if the returned value is not nil?
The lua-exported function returns Pane
, yes, but according to the documentation it should return *BufPane
. Isn't it better to fix it to be in accordance with the documentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not keep it returning
*BufPane
, and in the callers just check if the returned value is not nil?
This would be the easiest approach, but the function is called CurPane()
and as such it should return the current pane, which might be a BufPane
, RawPane
(derived from BufPane
), InfoPane
(derived from BufPane
) or a TermPane
.
I just imagine the moment we really like to address the current active TermPane
received from CurPane()
, without changing the interface again.
The lua-exported function returns
Pane
, yes, but according to the documentation it should return*BufPane
. Isn't it better to fix it to be in accordance with the documentation?
But we could also correct the documentation, that the function returns a Pane
. Anyway, isn't there a type conversion in Lua to address the BufPane
based on the received value (I'm no Lua expert)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, isn't there a type conversion in Lua to address the
BufPane
based on the received value (I'm no Lua expert)?
I'm afraid there isn't. I don't see https://pkg.go.dev/layeh.com/gopher-luar#New saying anything about Go's type assertion.
So, unless you know a way to do that, keeping the existing (implemented but not documented) polymorphic behavior of lua's CurState()
doesn't seem like a good idea. With the (documented but not implemented) non-polymorphic behavior, a plugin at least would be able to check if the current pane is a bufpane or not.
We may consider generalizing CurPane()
to non-buf panes in the future, but I think that when it comes to non-buf panes, we have more important stuff to generalize anyway. At least the following:
- Lack of support for non-buf panes in chained actions. While this PR will fix the crashes in #2307 and #2288, it will still not make either of the keybindings in #2307 and #2288 actually work, since it just interrupts handling the action once it encounters to a non-buf pane.
- Lack of support for
onAction
andpreAction
callbacks for non-buf panes. See e.g. 2677#issuecomment-1409211651
...In the meantime, when it comes to CurPane()
:
InfoPane
: plugins can useInfoBar().HasPrompt
to check if the infopane is currently active or not (like micro itself does).TermPane
: yes, plugins probably cannot check if the current pane is a term pane (and which of them, if there are multiple term panes), but possibly there will never be a use case for that?RawPane
: it is quite a special type of pane, plugins would hardly want to do anything with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I more or less reverted the most of the stuff. I hope I didn't overlook or brake something in regards of plugin compatibility.
Currently it feels like not moving forward with micro
, since so many functions are exported and can't simply changed or evolved. :/
internal/action/bufpane.go
Outdated
// if the action changed the current BufPane to a BufPane again, update the reference | ||
bp, ok := MainTab().CurPane().(*BufPane) | ||
if !ok { | ||
return innerSuccess |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It always return true otherwise. It returning innerSuccess
here useful? Looks like the return value of this function is never really used.
In other words, can we just break
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But innerSuccess
is modified in the condition...
innerSuccess = innerSuccess && h.execAction(a, names[i], j, te)
...depending on the result of execAction()
or do I oversee something?
In case we break
we return the forced true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, as I said, it doesn't look like this return value is used anywhere anyway. So it doesn't look like it makes sense to return anything else than the forced true
here. (Or, if we still want to return innerSuccess
here, then at least for consistency we should also at line 177 return success
instead of the forced true
, right?)
AFAICS success
and innerSuccess
are only for determining if we should execute the next action, but for determining which value should bufAction
return.
I actually have no idea what is the semantics of this return value. To be precise, I actually see just one place where this return value is used: https://github.com/zyedidia/micro/blob/master/internal/action/infopane.go#L143
and, this particular code path looks VERY confusing to me. Can you explain to me what does this code do and why does it use this return value the way it does? Why doesn't InfoPane's DoKeyEvent()
just do the same thing as BufPane's DoKeyEvent()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading your question again... Yes, innerSuccess
is modified depending on the value returned by execAction()
, but what does it have to do with the value returned by bufAction
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but what does it have to do with the value returned by
bufAction
?
Unfortunately nothing.
[...] return
success
instead of the forcedtrue
, right?
Yes and so I did.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Answering myself:
To be precise, I actually see just one place where this return value is used: https://github.com/zyedidia/micro/blob/master/internal/action/infopane.go#L143
and, this particular code path looks VERY confusing to me. Can you explain to me what does this code do and why does it use this return value the way it does? Why doesn't InfoPane's
DoKeyEvent()
just do the same thing as BufPane'sDoKeyEvent()
?
Ok, I've figured out myself what's up with that logic in InfoPane's DoKeyEvent()
. That logic makes sense, although is quite non-obvious and also somewhat buggy... PR #3267 is the result of my investigations.
[...] return
success
instead of the forcedtrue
, right?Yes and so I did.
And I'm still not sure it's the best idea. I still believe this return value is not really used, and should not really be used. (Please see 8c7f63a and let me know if you disagree with the commit message.)
Well... if we merge #3267, including 8c7f63a, then there will be no more code that (improperly) tries to use this return value. So then I'm ok with either keeping this return true
here or changing it to return success
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a nit though: it's better to do this (change to return success
) in a separate commit, since it is a separate change, not related to the fix for the crash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see 8c7f63a and let me know if you disagree with the commit message.
Hm, then we could drop the return at all. Anyway, I'm fine with that.
9798978
to
ba324c0
Compare
TermPane
as Pane
(fix crash)Pane
is not a BufPane
(fix crash)
ba324c0
to
b94981f
Compare
This will add the capability to address the `TermPane` within the tabs, since the tab list only stores panes.
b94981f
to
07cda68
Compare
Actually the
TermPane
isn't really considered as aPane
, even it really is aPane
.-> In the first version of this PR I added the
Name()
function to theTermPane
to be able to consider theTermPane
as aPane
in the future.The main change to fix the crash is the check the return of
MainTab().CurPane()
againstnil
in theBufMapEvent()
respectivebufAction()
function, becauseCurPane()
will return it in the moment the current pane changes to a pane other than aBufPane
.Fixes #2288
Fixes #2307