Preserve commit message when quitting while the commit message panel is open (#5524)

This isn't possible with the default quit binding ('q'), but there's an
alternative binding (ctrl-c) that does work while the panel is open;
also, users can rebind quit to something like ctrl-q.

Fixes #5513.
This commit is contained in:
Stefan Haller
2026-04-21 11:30:52 +02:00
committed by GitHub
9 changed files with 48 additions and 4 deletions
+8
View File
@@ -21,6 +21,7 @@ type BaseContext struct {
onRenderToMainFn func()
onFocusFns []onFocusFn
onFocusLostFns []onFocusLostFn
onQuitFns []func()
focusable bool
transient bool
@@ -141,6 +142,7 @@ func (self *BaseContext) ClearAllAttachedControllerFunctions() {
self.mouseKeybindingsFns = nil
self.onFocusFns = nil
self.onFocusLostFns = nil
self.onQuitFns = nil
self.onDoubleClickFn = nil
self.onClickFn = nil
self.onClickFocusedMainViewFn = nil
@@ -207,6 +209,12 @@ func (self *BaseContext) AddOnFocusLostFn(fn onFocusLostFn) {
}
}
func (self *BaseContext) AddOnQuitFn(fn func()) {
if fn != nil {
self.onQuitFns = append(self.onQuitFns, fn)
}
}
func (self *BaseContext) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
bindings := []*gocui.ViewMouseBinding{}
for i := range self.mouseKeybindingsFns {
+6
View File
@@ -54,6 +54,12 @@ func (self *SimpleContext) HandleFocusLost(opts types.OnFocusLostOpts) {
}
}
func (self *SimpleContext) HandleQuit() {
for _, fn := range self.onQuitFns {
fn()
}
}
func (self *SimpleContext) FocusLine(scrollIntoView bool) {
}
+1
View File
@@ -12,5 +12,6 @@ func AttachControllers(context types.Context, controllers ...types.IController)
context.AddOnRenderToMainFn(controller.GetOnRenderToMain())
context.AddOnFocusFn(controller.GetOnFocus())
context.AddOnFocusLostFn(controller.GetOnFocusLost())
context.AddOnQuitFn(controller.GetOnQuit())
}
}
+4
View File
@@ -38,3 +38,7 @@ func (self *baseController) GetOnFocus() func(types.OnFocusOpts) {
func (self *baseController) GetOnFocusLost() func(types.OnFocusLostOpts) {
return nil
}
func (self *baseController) GetOnQuit() func() {
return nil
}
@@ -91,6 +91,12 @@ func (self *CommitDescriptionController) GetOnFocus() func(types.OnFocusOpts) {
}
}
func (self *CommitDescriptionController) GetOnQuit() func() {
return func() {
self.c.Helpers().Commits.PreserveCommitMessage()
}
}
func (self *CommitDescriptionController) switchToCommitMessage() error {
self.c.Context().Replace(self.c.Contexts().CommitMessage)
return nil
@@ -82,6 +82,12 @@ func (self *CommitMessageController) GetOnFocusLost() func(types.OnFocusLostOpts
}
}
func (self *CommitMessageController) GetOnQuit() func() {
return func() {
self.c.Helpers().Commits.PreserveCommitMessage()
}
}
func (self *CommitMessageController) Context() types.Context {
return self.context()
}
@@ -173,15 +173,17 @@ func (self *CommitsHelper) HandleCommitConfirm() error {
return nil
}
func (self *CommitsHelper) CloseCommitMessagePanel() {
func (self *CommitsHelper) PreserveCommitMessage() {
if self.c.Contexts().CommitMessage.GetPreserveMessage() {
message := self.JoinCommitMessageAndUnwrappedDescription()
if message != self.c.Contexts().CommitMessage.GetInitialMessage() {
self.c.Contexts().CommitMessage.SetPreservedMessageAndLogError(message)
}
} else {
self.SetMessageAndDescriptionInView("")
}
}
func (self *CommitsHelper) CloseCommitMessagePanel() {
self.PreserveCommitMessage()
self.c.Contexts().CommitMessage.SetHistoryMessage("")
+6 -1
View File
@@ -935,7 +935,12 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
// setting here so we can use it in layout.go
gui.integrationTest = startArgs.IntegrationTest
return gui.g.MainLoop()
err = gui.g.MainLoop()
if errors.Is(err, gocui.ErrQuit) {
// Give the focused context a chance to clean up before we tear down the app.
gui.c.Context().Current().HandleQuit()
}
return err
}
func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error {
+6
View File
@@ -105,6 +105,7 @@ type IBaseContext interface {
AddOnRenderToMainFn(func())
AddOnFocusFn(func(OnFocusOpts))
AddOnFocusLostFn(func(OnFocusLostOpts))
AddOnQuitFn(func())
}
type Context interface {
@@ -112,6 +113,7 @@ type Context interface {
HandleFocus(opts OnFocusOpts)
HandleFocusLost(opts OnFocusLostOpts)
HandleQuit()
FocusLine(scrollIntoView bool)
HandleRender()
HandleRenderToMain()
@@ -273,6 +275,10 @@ type IController interface {
GetOnRenderToMain() func()
GetOnFocus() func(OnFocusOpts)
GetOnFocusLost() func(OnFocusLostOpts)
// Implement this to get called when the app quits, and the controller's context has the focus.
// Useful for saving state on quit.
GetOnQuit() func()
}
type IList interface {