mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
9d68b287db
When we use the one panel for the entire commit message, its tricky to have a keybinding both for adding a newline and submitting. By having two panels: one for the summary line and one for the description, we allow for 'enter' to submit the message when done from the summary panel, and 'enter' to add a newline when done from the description panel. Alt-enter, for those who can use that key combo, also works for submitting the message from the description panel. For those who can't use that key combo, and don't want to remap the keybinding, they can hit tab to go back to the summary panel and then 'enter' to submit the message. We have some awkwardness in that both contexts (i.e. panels) need to appear and disappear in tandem and we don't have a great way of handling that concept, so we just push both contexts one after the other, and likewise remove both contexts when we escape.
355 lines
12 KiB
Go
355 lines
12 KiB
Go
package gui
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/jesseduffield/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/status"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
func (gui *Gui) Helpers() *helpers.Helpers {
|
|
return gui.helpers
|
|
}
|
|
|
|
func (gui *Gui) resetHelpersAndControllers() {
|
|
helperCommon := gui.c
|
|
refsHelper := helpers.NewRefsHelper(helperCommon)
|
|
|
|
rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, refsHelper)
|
|
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon)
|
|
|
|
setCommitSummary := gui.getCommitMessageSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage })
|
|
setCommitDescription := gui.getCommitMessageSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitDescription })
|
|
getCommitSummary := func() string {
|
|
return strings.TrimSpace(gui.Views.CommitMessage.TextArea.GetContent())
|
|
}
|
|
|
|
getCommitDescription := func() string {
|
|
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetContent())
|
|
}
|
|
commitsHelper := helpers.NewCommitsHelper(helperCommon,
|
|
getCommitSummary,
|
|
setCommitSummary,
|
|
getCommitDescription,
|
|
setCommitDescription,
|
|
)
|
|
|
|
gpgHelper := helpers.NewGpgHelper(helperCommon)
|
|
viewHelper := helpers.NewViewHelper(helperCommon, gui.State.Contexts)
|
|
recordDirectoryHelper := helpers.NewRecordDirectoryHelper(helperCommon)
|
|
patchBuildingHelper := helpers.NewPatchBuildingHelper(helperCommon)
|
|
stagingHelper := helpers.NewStagingHelper(helperCommon)
|
|
mergeConflictsHelper := helpers.NewMergeConflictsHelper(helperCommon)
|
|
refreshHelper := helpers.NewRefreshHelper(helperCommon, refsHelper, rebaseHelper, patchBuildingHelper, stagingHelper, mergeConflictsHelper, gui.fileWatcher)
|
|
diffHelper := helpers.NewDiffHelper(helperCommon)
|
|
cherryPickHelper := helpers.NewCherryPickHelper(
|
|
helperCommon,
|
|
rebaseHelper,
|
|
)
|
|
bisectHelper := helpers.NewBisectHelper(helperCommon)
|
|
windowHelper := helpers.NewWindowHelper(helperCommon, viewHelper)
|
|
modeHelper := helpers.NewModeHelper(
|
|
helperCommon,
|
|
diffHelper,
|
|
patchBuildingHelper,
|
|
cherryPickHelper,
|
|
rebaseHelper,
|
|
bisectHelper,
|
|
)
|
|
appStatusHelper := helpers.NewAppStatusHelper(
|
|
helperCommon,
|
|
func() *status.StatusManager { return gui.statusManager },
|
|
)
|
|
gui.helpers = &helpers.Helpers{
|
|
Refs: refsHelper,
|
|
Host: helpers.NewHostHelper(helperCommon),
|
|
PatchBuilding: patchBuildingHelper,
|
|
Staging: stagingHelper,
|
|
Bisect: bisectHelper,
|
|
Suggestions: suggestionsHelper,
|
|
Files: helpers.NewFilesHelper(helperCommon),
|
|
WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, refsHelper, commitsHelper, gpgHelper),
|
|
Tags: helpers.NewTagsHelper(helperCommon),
|
|
GPG: helpers.NewGpgHelper(helperCommon),
|
|
MergeAndRebase: rebaseHelper,
|
|
MergeConflicts: mergeConflictsHelper,
|
|
CherryPick: cherryPickHelper,
|
|
Upstream: helpers.NewUpstreamHelper(helperCommon, suggestionsHelper.GetRemoteBranchesSuggestionsFunc),
|
|
AmendHelper: helpers.NewAmendHelper(helperCommon, gpgHelper),
|
|
Commits: commitsHelper,
|
|
Snake: helpers.NewSnakeHelper(helperCommon),
|
|
Diff: diffHelper,
|
|
Repos: helpers.NewRecentReposHelper(helperCommon, recordDirectoryHelper, gui.onNewRepo),
|
|
RecordDirectory: recordDirectoryHelper,
|
|
Update: helpers.NewUpdateHelper(helperCommon, gui.Updater),
|
|
Window: windowHelper,
|
|
View: viewHelper,
|
|
Refresh: refreshHelper,
|
|
Confirmation: helpers.NewConfirmationHelper(helperCommon),
|
|
Mode: modeHelper,
|
|
AppStatus: appStatusHelper,
|
|
WindowArrangement: helpers.NewWindowArrangementHelper(
|
|
gui.c,
|
|
windowHelper,
|
|
modeHelper,
|
|
appStatusHelper,
|
|
),
|
|
}
|
|
|
|
gui.CustomCommandsClient = custom_commands.NewClient(
|
|
helperCommon,
|
|
gui.helpers,
|
|
)
|
|
|
|
common := controllers.NewControllerCommon(helperCommon, gui)
|
|
|
|
syncController := controllers.NewSyncController(
|
|
common,
|
|
)
|
|
|
|
submodulesController := controllers.NewSubmodulesController(common)
|
|
|
|
bisectController := controllers.NewBisectController(common)
|
|
|
|
commitMessageController := controllers.NewCommitMessageController(
|
|
common,
|
|
)
|
|
|
|
commitDescriptionController := controllers.NewCommitDescriptionController(
|
|
common,
|
|
)
|
|
|
|
remoteBranchesController := controllers.NewRemoteBranchesController(common)
|
|
|
|
menuController := controllers.NewMenuController(common)
|
|
localCommitsController := controllers.NewLocalCommitsController(common, syncController.HandlePull)
|
|
tagsController := controllers.NewTagsController(common)
|
|
filesController := controllers.NewFilesController(
|
|
common,
|
|
)
|
|
mergeConflictsController := controllers.NewMergeConflictsController(common)
|
|
remotesController := controllers.NewRemotesController(
|
|
common,
|
|
func(branches []*models.RemoteBranch) { gui.State.Model.RemoteBranches = branches },
|
|
)
|
|
undoController := controllers.NewUndoController(common)
|
|
globalController := controllers.NewGlobalController(common)
|
|
contextLinesController := controllers.NewContextLinesController(common)
|
|
verticalScrollControllerFactory := controllers.NewVerticalScrollControllerFactory(common, &gui.viewBufferManagerMap)
|
|
|
|
branchesController := controllers.NewBranchesController(common)
|
|
gitFlowController := controllers.NewGitFlowController(common)
|
|
filesRemoveController := controllers.NewFilesRemoveController(common)
|
|
stashController := controllers.NewStashController(common)
|
|
commitFilesController := controllers.NewCommitFilesController(common)
|
|
patchExplorerControllerFactory := controllers.NewPatchExplorerControllerFactory(common)
|
|
stagingController := controllers.NewStagingController(common, gui.State.Contexts.Staging, gui.State.Contexts.StagingSecondary, false)
|
|
stagingSecondaryController := controllers.NewStagingController(common, gui.State.Contexts.StagingSecondary, gui.State.Contexts.Staging, true)
|
|
patchBuildingController := controllers.NewPatchBuildingController(common)
|
|
snakeController := controllers.NewSnakeController(common)
|
|
reflogCommitsController := controllers.NewReflogCommitsController(common)
|
|
subCommitsController := controllers.NewSubCommitsController(common)
|
|
statusController := controllers.NewStatusController(common)
|
|
commandLogController := controllers.NewCommandLogController(common)
|
|
confirmationController := controllers.NewConfirmationController(common)
|
|
suggestionsController := controllers.NewSuggestionsController(common)
|
|
jumpToSideWindowController := controllers.NewJumpToSideWindowController(common)
|
|
|
|
sideWindowControllerFactory := controllers.NewSideWindowControllerFactory(common)
|
|
|
|
// allow for navigating between side window contexts
|
|
for _, context := range []types.Context{
|
|
gui.State.Contexts.Status,
|
|
gui.State.Contexts.Remotes,
|
|
gui.State.Contexts.Tags,
|
|
gui.State.Contexts.Branches,
|
|
gui.State.Contexts.RemoteBranches,
|
|
gui.State.Contexts.Files,
|
|
gui.State.Contexts.Submodules,
|
|
gui.State.Contexts.ReflogCommits,
|
|
gui.State.Contexts.LocalCommits,
|
|
gui.State.Contexts.CommitFiles,
|
|
gui.State.Contexts.SubCommits,
|
|
gui.State.Contexts.Stash,
|
|
} {
|
|
controllers.AttachControllers(context, sideWindowControllerFactory.Create(context))
|
|
}
|
|
|
|
setSubCommits := func(commits []*models.Commit) {
|
|
gui.Mutexes.SubCommitsMutex.Lock()
|
|
defer gui.Mutexes.SubCommitsMutex.Unlock()
|
|
|
|
gui.State.Model.SubCommits = commits
|
|
}
|
|
|
|
for _, context := range []controllers.CanSwitchToSubCommits{
|
|
gui.State.Contexts.Branches,
|
|
gui.State.Contexts.RemoteBranches,
|
|
gui.State.Contexts.Tags,
|
|
gui.State.Contexts.ReflogCommits,
|
|
} {
|
|
controllers.AttachControllers(context, controllers.NewSwitchToSubCommitsController(
|
|
common, setSubCommits, context,
|
|
))
|
|
}
|
|
|
|
for _, context := range []controllers.CanSwitchToDiffFiles{
|
|
gui.State.Contexts.LocalCommits,
|
|
gui.State.Contexts.SubCommits,
|
|
gui.State.Contexts.Stash,
|
|
} {
|
|
controllers.AttachControllers(context, controllers.NewSwitchToDiffFilesController(
|
|
common, context, gui.State.Contexts.CommitFiles,
|
|
))
|
|
}
|
|
|
|
for _, context := range []controllers.ContainsCommits{
|
|
gui.State.Contexts.LocalCommits,
|
|
gui.State.Contexts.ReflogCommits,
|
|
gui.State.Contexts.SubCommits,
|
|
} {
|
|
controllers.AttachControllers(context, controllers.NewBasicCommitsController(common, context))
|
|
}
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.ReflogCommits,
|
|
reflogCommitsController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.SubCommits,
|
|
subCommitsController,
|
|
)
|
|
|
|
// TODO: add scroll controllers for main panels (need to bring some more functionality across for that e.g. reading more from the currently displayed git command)
|
|
controllers.AttachControllers(gui.State.Contexts.Staging,
|
|
stagingController,
|
|
patchExplorerControllerFactory.Create(gui.State.Contexts.Staging),
|
|
verticalScrollControllerFactory.Create(gui.State.Contexts.Staging),
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.StagingSecondary,
|
|
stagingSecondaryController,
|
|
patchExplorerControllerFactory.Create(gui.State.Contexts.StagingSecondary),
|
|
verticalScrollControllerFactory.Create(gui.State.Contexts.StagingSecondary),
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CustomPatchBuilder,
|
|
patchBuildingController,
|
|
patchExplorerControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder),
|
|
verticalScrollControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder),
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CustomPatchBuilderSecondary,
|
|
verticalScrollControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder),
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.MergeConflicts,
|
|
mergeConflictsController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Files,
|
|
filesController,
|
|
filesRemoveController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Tags,
|
|
tagsController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Submodules,
|
|
submodulesController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.LocalCommits,
|
|
localCommitsController,
|
|
bisectController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Branches,
|
|
branchesController,
|
|
gitFlowController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.LocalCommits,
|
|
localCommitsController,
|
|
bisectController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CommitFiles,
|
|
commitFilesController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Remotes,
|
|
remotesController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Stash,
|
|
stashController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Menu,
|
|
menuController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CommitMessage,
|
|
commitMessageController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CommitDescription,
|
|
commitDescriptionController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.RemoteBranches,
|
|
remoteBranchesController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Status,
|
|
statusController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.CommandLog,
|
|
commandLogController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Confirmation,
|
|
confirmationController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Suggestions,
|
|
suggestionsController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Global,
|
|
syncController,
|
|
undoController,
|
|
globalController,
|
|
contextLinesController,
|
|
jumpToSideWindowController,
|
|
)
|
|
|
|
controllers.AttachControllers(gui.State.Contexts.Snake,
|
|
snakeController,
|
|
)
|
|
|
|
// this must come last so that we've got our click handlers defined against the context
|
|
listControllerFactory := controllers.NewListControllerFactory(common)
|
|
for _, context := range gui.c.Context().AllList() {
|
|
controllers.AttachControllers(context, listControllerFactory.Create(context))
|
|
}
|
|
}
|
|
|
|
func (gui *Gui) getCommitMessageSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
|
return func(text string) {
|
|
// using a getView function so that we don't need to worry about when the view is created
|
|
view := getView()
|
|
view.ClearTextArea()
|
|
view.TextArea.TypeString(text)
|
|
gui.helpers.Confirmation.ResizeCommitMessagePanels()
|
|
view.RenderTextArea()
|
|
}
|
|
}
|