Closed aschey closed 1 year ago
Hey @aschey,
one way you could do this is to have your child return the parent model when a specific key is pressed (or some other IO has finished). You can save the state of the parent model to a global variable before changing to the child model if you want to pick up where you left off. Alternatively, you could have it create a new parent model that you return when you want to switch back to the parent model. It just depends on your particular case.
Let me know if this is a viable solution for you!
Hey @bashbunni thanks for the suggestion. In my case, it would be ideal if the consumers of bubbleprompt could supply any arbitrary model without them having to make any changes specific to how bubbleprompt uses it. This is both to make it easier for consumers to use the library and also for what I think will be a common use case - users may want to reuse their models between running inside bubbleprompt and running as a standalone CLI, in which case their models would need to behave normally without running inside of a parent model.
Also added the Slack link where this was originally discussed to the post
As discussed on Slack, I think this makes sense and we should add such a "callback" that lets the program prevent an app shutdown. A common use case for this would be presenting the user with a modal save dialog in case there are unsaved changes in an application.
Oh, that's a use case I hadn't considered. In that case, perhaps it makes sense to pass the model as a parameter to the callback so the user could do some kind of check on it like so:
func onQuit(m tea.Model) tea.QuitBehavior {
appModel := m.(myModel)
if appModel.pendingChanges {
return tea.PreventShutdown
} else {
return tea.Shutdown
}
}
Also related request: https://github.com/charmbracelet/bubbletea/pull/352#pullrequestreview-1109933756
tl;dr: POC of the proposed feature
link to Slack thread where this was originally discussed
I'm working on bubbleprompt, a library very similar to the popular go-prompt. It essentially acts as a REPL where users can run custom actions on submit. In bubbleprompt, I allow consumers of the library to supply an arbitrary
tea.Model
when they submit a command. When this child model sendstea.Quit
, I need to prevent it from terminating the entiretea.Program
and instead return control to the parent model.Currently, I do this using reflection to check if the child model returns
tea.Quit
and prevent it from sending it if so. It looks something like this:However, if the quit command is wrapped in
tea.Batch
or any similar construct, this gets substantially trickier.To solve this problem, I propose adding a
tea.onQuit
event handler with a signature such asonQuit func() QuitBehavior
. If the user supplies it, this function will run whenever the event loop receives atea.quitMsg
. The quit handler will return whether the program should shut down or not.QuitBehavior
is just an enum with two values:tea.Shutdown
andtea.PreventShutdown
. We could just use a bool instead of a custom enum, but I think that would be rather confusing to the user - doestrue
mean shutdown or doesfalse
mean shutdown? IfonQuit
returnstea.Shutdown
, then Bubble Tea will handle the message just as it currently does, but if it returnstea.PreventShutdown
, then we should treat thetea.quitMsg
as a normal message and forward it to the user's update handler for further processing. This would require makingtea.quitMsg
public so that applications could check for it.A minimal usage example would look like this:
I don't love the use of a global variable here, but I think it's the easiest way to handle this without introducing additional complexity by adding something like another special command that bypasses the
onQuit
handler and always shuts the program down. That feels like a heavy solution for this rather niche use case, so I'm trying to keep the proposed changes to Bubble Tea minimal here.The implementation is rather simple, so I went ahead and made a quick POC. Happy to make a PR for this after hearing any feedback. Thanks!