diff --git a/pkg/gui/controllers/commit_description_controller.go b/pkg/gui/controllers/commit_description_controller.go index 41ec54103..b58285688 100644 --- a/pkg/gui/controllers/commit_description_controller.go +++ b/pkg/gui/controllers/commit_description_controller.go @@ -4,7 +4,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" - "github.com/samber/lo" ) type CommitDescriptionController struct { @@ -27,7 +26,7 @@ func (self *CommitDescriptionController) GetKeybindings(opts types.KeybindingsOp bindings := []*types.Binding{ { Keys: opts.GetKeys(opts.Config.Universal.TogglePanel), - Handler: self.handleTogglePanel, + Handler: self.switchToCommitMessage, }, { Keys: opts.GetKeys(opts.Config.Universal.Return), @@ -86,32 +85,6 @@ func (self *CommitDescriptionController) switchToCommitMessage() error { return nil } -func (self *CommitDescriptionController) handleTogglePanel() error { - // The default keybinding for this action is "", which means that we - // also get here when pasting multi-line text that contains tabs. In that - // case we don't want to toggle the panel, but insert the tab as a character - // (somehow, see below). - // - // Only do this if the TogglePanel command is actually mapped to "" - // (the default). If it's not, we can only hope that it's mapped to some - // ctrl key or fn key, which is unlikely to occur in pasted text. And if - // they mapped some *other* command to "", then we're totally out of - // luck. - if self.c.GocuiGui().IsPasting && lo.Contains(self.c.UserConfig().Keybinding.Universal.TogglePanel, "") { - // Handling tabs in pasted commit messages is not optimal, but hopefully - // good enough for now. We simply insert 4 spaces without worrying about - // column alignment. This works well enough for leading indentation, - // which is common in pasted code snippets. - view := self.Context().GetView() - for range 4 { - view.Editor.Edit(view, gocui.NewKeyRune(' ')) - } - return nil - } - - return self.switchToCommitMessage() -} - func (self *CommitDescriptionController) close() error { self.c.Helpers().Commits.CloseCommitMessagePanel() return nil diff --git a/pkg/gui/controllers/commit_message_controller.go b/pkg/gui/controllers/commit_message_controller.go index dde9b5647..d25a6bd06 100644 --- a/pkg/gui/controllers/commit_message_controller.go +++ b/pkg/gui/controllers/commit_message_controller.go @@ -7,7 +7,6 @@ import ( "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" - "github.com/samber/lo" ) type CommitMessageController struct { @@ -48,7 +47,7 @@ func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts) }, { Keys: opts.GetKeys(opts.Config.Universal.TogglePanel), - Handler: self.handleTogglePanel, + Handler: self.switchToCommitDescription, }, { Keys: opts.GetKeys(opts.Config.CommitMessage.CommitMenu), @@ -112,32 +111,6 @@ func (self *CommitMessageController) switchToCommitDescription() error { return nil } -func (self *CommitMessageController) handleTogglePanel() error { - // The default keybinding for this action is "", which means that we - // also get here when pasting multi-line text that contains tabs. In that - // case we don't want to toggle the panel, but insert the tab as a character - // (somehow, see below). - // - // Only do this if the TogglePanel command is actually mapped to "" - // (the default). If it's not, we can only hope that it's mapped to some - // ctrl key or fn key, which is unlikely to occur in pasted text. And if - // they mapped some *other* command to "", then we're totally out of - // luck. - if self.c.GocuiGui().IsPasting && lo.Contains(self.c.UserConfig().Keybinding.Universal.TogglePanel, "") { - // It is unlikely that a pasted commit message contains a tab in the - // subject line, so it shouldn't matter too much how we handle it. - // Simply insert 4 spaces instead; all that matters is that we don't - // switch to the description panel. - view := self.context().GetView() - for range 4 { - view.Editor.Edit(view, gocui.NewKeyRune(' ')) - } - return nil - } - - return self.switchToCommitDescription() -} - func (self *CommitMessageController) handleCommitIndexChange(value int) error { currentIndex := self.context().GetSelectedIndex() newIndex := currentIndex + value @@ -171,20 +144,6 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e } func (self *CommitMessageController) confirm() error { - // The default keybinding for this action is "", which means that we - // also get here when pasting multi-line text that contains newlines. In - // that case we don't want to confirm the commit, but switch to the - // description panel instead so that the rest of the pasted text goes there. - // - // Only do this if the SubmitEditorText command is actually mapped to - // "" (the default). If it's not, we can only hope that it's mapped - // to some ctrl key or fn key, which is unlikely to occur in pasted text. - // And if they mapped some *other* command to "", then we're totally - // out of luck. - if self.c.GocuiGui().IsPasting && lo.Contains(self.c.UserConfig().Keybinding.Universal.SubmitEditorText, "") { - return self.switchToCommitDescription() - } - return self.c.Helpers().Commits.HandleCommitConfirm() } diff --git a/pkg/gui/controllers/helpers/commits_helper.go b/pkg/gui/controllers/helpers/commits_helper.go index 186a48337..5f3b54ca6 100644 --- a/pkg/gui/controllers/helpers/commits_helper.go +++ b/pkg/gui/controllers/helpers/commits_helper.go @@ -320,6 +320,37 @@ func (self *CommitsHelper) copyCommitMessageToClipboard() error { return nil } +// HandlePasteIntoSummary inserts text that the user pasted into the summary +// with the terminal's paste command. If the text has several lines, the rest +// of them goes into the description. +func (self *CommitsHelper) HandlePasteIntoSummary(text string) { + summary, rest, hasMoreLines := strings.Cut(text, "\n") + + view := self.c.Views().CommitMessage + view.TextArea.TypeString(replaceTabsInPastedText(summary)) + view.RenderTextArea() + self.c.Contexts().CommitMessage.RenderSubtitle() + + if hasMoreLines { + self.c.Context().Replace(self.c.Contexts().CommitDescription) + self.HandlePasteIntoDescription(rest) + } +} + +// HandlePasteIntoDescription inserts text that the user pasted into the +// description with the terminal's paste command. +func (self *CommitsHelper) HandlePasteIntoDescription(text string) { + view := self.c.Views().CommitDescription + view.TextArea.TypeString(replaceTabsInPastedText(text)) + view.RenderTextArea() +} + +// Replace each tab with four spaces, without aligning to tab stops. This works +// well enough for leading indentation, which is common in pasted code snippets. +func replaceTabsInPastedText(text string) string { + return strings.ReplaceAll(text, "\t", " ") +} + func stripTrailingWhitespace(message string) string { lines := strings.Split(message, "\n") for i, line := range lines { diff --git a/pkg/gui/views.go b/pkg/gui/views.go index 653c23c4b..6bc414da6 100644 --- a/pkg/gui/views.go +++ b/pkg/gui/views.go @@ -119,10 +119,18 @@ func (gui *Gui) createAllViews() error { gui.Views.CommitMessage.Visible = false gui.Views.CommitMessage.Editable = true gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor) + gui.Views.CommitMessage.OnPaste = func(text string) error { + gui.helpers.Commits.HandlePasteIntoSummary(text) + return nil + } gui.Views.CommitDescription.Visible = false gui.Views.CommitDescription.Editable = true gui.Views.CommitDescription.Editor = gocui.EditorFunc(gui.commitDescriptionEditor) + gui.Views.CommitDescription.OnPaste = func(text string) error { + gui.helpers.Commits.HandlePasteIntoDescription(text) + return nil + } gui.Views.Confirmation.Visible = false gui.Views.Confirmation.Wrap = true