mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Preserve whitespace when remembering commit message (#5528)
This is useful when cancelling out of the commit panel mid-sentence (after having typed the space for the next word); when entering the commit message panel again, the space was gone and you had to type it again. Small thing, but it just seems better to resume the panel in exactly the state that you left it in. (Which we actually don't do; we don't remember the cursor position, or which of the subject/description panels was active. That would be a separate improvement.) Fixes #5519.
This commit is contained in:
commit
0ecf818a73
|
|
@ -61,6 +61,7 @@ func AddCoAuthorToMessage(message string, author string) string {
|
|||
}
|
||||
|
||||
func AddCoAuthorToDescription(description string, author string) string {
|
||||
description = strings.TrimRight(description, "\n")
|
||||
if description != "" {
|
||||
lines := strings.Split(description, "\n")
|
||||
if strings.HasPrefix(lines[len(lines)-1], "Co-authored-by:") {
|
||||
|
|
|
|||
|
|
@ -483,6 +483,11 @@ func TestAddCoAuthorToDescription(t *testing.T) {
|
|||
description: "Body\n\nCo-authored-by: Jane Smith <jane@smith.com>",
|
||||
expectedResult: "Body\n\nCo-authored-by: Jane Smith <jane@smith.com>\nCo-authored-by: John Doe <john@doe.com>",
|
||||
},
|
||||
{
|
||||
name: "Description with trailing newlines",
|
||||
description: "Body\n\n",
|
||||
expectedResult: "Body\n\nCo-authored-by: John Doe <john@doe.com>",
|
||||
},
|
||||
}
|
||||
for _, s := range scenarios {
|
||||
t.Run(s.name, func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ func (self *CommitMessageContext) SetPreservedMessageAndLogError(message string)
|
|||
}
|
||||
|
||||
func (self *CommitMessageContext) GetInitialMessage() string {
|
||||
return strings.TrimSpace(self.viewModel.initialMessage)
|
||||
return self.viewModel.initialMessage
|
||||
}
|
||||
|
||||
func (self *CommitMessageContext) GetHistoryMessage() string {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers"
|
||||
|
|
@ -35,14 +33,14 @@ func (gui *Gui) resetHelpersAndControllers() {
|
|||
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())
|
||||
return gui.Views.CommitMessage.TextArea.GetContent()
|
||||
}
|
||||
|
||||
getCommitDescription := func() string {
|
||||
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetContent())
|
||||
return gui.Views.CommitDescription.TextArea.GetContent()
|
||||
}
|
||||
getUnwrappedCommitDescription := func() string {
|
||||
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetUnwrappedContent())
|
||||
return gui.Views.CommitDescription.TextArea.GetUnwrappedContent()
|
||||
}
|
||||
commitsHelper := helpers.NewCommitsHelper(helperCommon,
|
||||
getCommitSummary,
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ func (self *CommitMessageController) handleCommitIndexChange(value int) error {
|
|||
newIndex := currentIndex + value
|
||||
if newIndex == context.NoCommitIndex {
|
||||
self.context().SetSelectedIndex(newIndex)
|
||||
self.c.Helpers().Commits.SetMessageAndDescriptionInView(self.context().GetHistoryMessage())
|
||||
self.c.Helpers().Commits.SetPreservedMessageInView(self.context().GetHistoryMessage())
|
||||
return nil
|
||||
} else if currentIndex == context.NoCommitIndex {
|
||||
self.context().SetHistoryMessage(self.c.Helpers().Commits.JoinCommitMessageAndUnwrappedDescription())
|
||||
|
|
@ -168,7 +168,7 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
|
|||
if self.c.UserConfig().Git.Commit.AutoWrapCommitMessage {
|
||||
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig().Git.Commit.AutoWrapWidth)
|
||||
}
|
||||
self.c.Helpers().Commits.UpdateCommitPanelView(commitMessage)
|
||||
self.c.Helpers().Commits.SetMessageAndDescriptionInView(commitMessage)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,14 +40,34 @@ func NewCommitsHelper(
|
|||
}
|
||||
}
|
||||
|
||||
// SplitCommitMessageAndDescription splits a message in git's canonical format
|
||||
// (summary and body separated by a blank line) into summary and description.
|
||||
func (self *CommitsHelper) SplitCommitMessageAndDescription(message string) (string, string) {
|
||||
msg, description, _ := strings.Cut(message, "\n")
|
||||
return msg, strings.TrimSpace(description)
|
||||
summary, description, _ := strings.Cut(message, "\n")
|
||||
description = strings.TrimPrefix(description, "\n")
|
||||
return summary, description
|
||||
}
|
||||
|
||||
// SplitPreservedCommitMessage splits a message in our preservation format
|
||||
// (summary and description joined by a single "\n") into summary and description.
|
||||
// It is lossless: round-tripping through JoinCommitMessageAndUnwrappedDescription
|
||||
// preserves the exact content.
|
||||
func (self *CommitsHelper) SplitPreservedCommitMessage(message string) (string, string) {
|
||||
summary, description, _ := strings.Cut(message, "\n")
|
||||
return summary, description
|
||||
}
|
||||
|
||||
func (self *CommitsHelper) SetMessageAndDescriptionInView(message string) {
|
||||
summary, description := self.SplitCommitMessageAndDescription(message)
|
||||
self.setSummaryAndDescriptionInView(summary, description)
|
||||
}
|
||||
|
||||
func (self *CommitsHelper) SetPreservedMessageInView(message string) {
|
||||
summary, description := self.SplitPreservedCommitMessage(message)
|
||||
self.setSummaryAndDescriptionInView(summary, description)
|
||||
}
|
||||
|
||||
func (self *CommitsHelper) setSummaryAndDescriptionInView(summary, description string) {
|
||||
self.setCommitSummary(summary)
|
||||
self.setCommitDescription(description)
|
||||
self.c.Contexts().CommitMessage.RenderSubtitle()
|
||||
|
|
@ -97,21 +117,6 @@ func (self *CommitsHelper) SwitchToEditor() error {
|
|||
return self.c.Contexts().CommitMessage.SwitchToEditor(filepath)
|
||||
}
|
||||
|
||||
func (self *CommitsHelper) UpdateCommitPanelView(message string) {
|
||||
if message != "" {
|
||||
self.SetMessageAndDescriptionInView(message)
|
||||
return
|
||||
}
|
||||
|
||||
if self.c.Contexts().CommitMessage.GetPreserveMessage() {
|
||||
preservedMessage := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()
|
||||
self.SetMessageAndDescriptionInView(preservedMessage)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetMessageAndDescriptionInView("")
|
||||
}
|
||||
|
||||
type OpenCommitMessagePanelOpts struct {
|
||||
CommitIndex int
|
||||
SummaryTitle string
|
||||
|
|
@ -137,19 +142,35 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp
|
|||
return opts.OnConfirm(summary, description)
|
||||
}
|
||||
|
||||
// When there's no explicit initial message but we're in a preservation
|
||||
// context, fall back to any previously preserved message. This is stored as
|
||||
// the "initial" value so the unchanged-message check on close still works
|
||||
// correctly (in particular, clearing the panel then escaping will notice
|
||||
// the difference and delete the preserved file).
|
||||
initialMessage := opts.InitialMessage
|
||||
initialMessageIsPreserved := false
|
||||
if opts.PreserveMessage && initialMessage == "" {
|
||||
initialMessage = self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()
|
||||
initialMessageIsPreserved = true
|
||||
}
|
||||
|
||||
self.c.Contexts().CommitMessage.SetPanelState(
|
||||
opts.CommitIndex,
|
||||
opts.SummaryTitle,
|
||||
opts.DescriptionTitle,
|
||||
opts.PreserveMessage,
|
||||
opts.InitialMessage,
|
||||
initialMessage,
|
||||
onConfirm,
|
||||
opts.OnSwitchToEditor,
|
||||
opts.ForceSkipHooks,
|
||||
opts.SkipHooksPrefix,
|
||||
)
|
||||
|
||||
self.UpdateCommitPanelView(opts.InitialMessage)
|
||||
if initialMessageIsPreserved {
|
||||
self.SetPreservedMessageInView(initialMessage)
|
||||
} else {
|
||||
self.SetMessageAndDescriptionInView(initialMessage)
|
||||
}
|
||||
|
||||
self.c.Context().Push(self.c.Contexts().CommitMessage, types.OnFocusOpts{})
|
||||
}
|
||||
|
|
@ -161,7 +182,7 @@ func (self *CommitsHelper) ClearPreservedCommitMessage() {
|
|||
func (self *CommitsHelper) HandleCommitConfirm() error {
|
||||
summary, description := self.getCommitSummary(), self.getCommitDescription()
|
||||
|
||||
if summary == "" {
|
||||
if strings.TrimSpace(summary) == "" {
|
||||
return errors.New(self.c.Tr.CommitWithoutMessageErr)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,9 +195,9 @@ func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
|
|||
}
|
||||
|
||||
func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||
message := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()
|
||||
|
||||
if message == "" {
|
||||
var initialMessage string
|
||||
preservedMessage := self.c.Contexts().CommitMessage.GetPreservedMessageAndLogError()
|
||||
if preservedMessage == "" {
|
||||
commitPrefixConfigs := self.commitPrefixConfigsForRepo()
|
||||
for _, commitPrefixConfig := range commitPrefixConfigs {
|
||||
prefixPattern := commitPrefixConfig.Pattern
|
||||
|
|
@ -212,14 +212,13 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
|
|||
}
|
||||
|
||||
if rgx.MatchString(branchName) {
|
||||
prefix := rgx.ReplaceAllString(branchName, prefixReplace)
|
||||
message = prefix
|
||||
initialMessage = rgx.ReplaceAllString(branchName, prefixReplace)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self.HandleCommitPressWithMessage(message, false)
|
||||
return self.HandleCommitPressWithMessage(initialMessage, false)
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) WithEnsureCommittableFiles(handler func() error) error {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var PreserveCommitMessageWhitespace = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Whitespace in the description (e.g. leading blank lines, indented first line) should be preserved when canceling and reopening the commit message panel",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFileAndAdd("myfile", "myfile content")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Files.CommitChanges)
|
||||
|
||||
t.ExpectPopup().CommitMessagePanel().
|
||||
Type("my commit message").
|
||||
SwitchToDescription().
|
||||
AddNewline().
|
||||
AddNewline().
|
||||
Type("body ").
|
||||
Cancel()
|
||||
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Files.CommitChanges)
|
||||
|
||||
t.ExpectPopup().CommitMessagePanel().
|
||||
Content(Equals("my commit message")).
|
||||
SwitchToDescription().
|
||||
Content(Equals("\n\nbody ")).
|
||||
Cancel()
|
||||
},
|
||||
})
|
||||
|
|
@ -142,6 +142,7 @@ var tests = []*components.IntegrationTest{
|
|||
commit.PasteCommitMessage,
|
||||
commit.PasteCommitMessageOverExisting,
|
||||
commit.PreserveCommitMessage,
|
||||
commit.PreserveCommitMessageWhitespace,
|
||||
commit.ResetAuthor,
|
||||
commit.ResetAuthorRange,
|
||||
commit.Revert,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# We will have only done a shallow clone, so the git log will consist only of
|
||||
# commits on the current PR
|
||||
commits=$(git log --grep='^fixup!' --grep='^squash!' --grep='^amend!' --grep='^[^\n]*WIP' --grep='^[^\n]*DROPME' --format="%h %s")
|
||||
commits=$(git log --format="%h %s" | egrep '(^fixup!|^squash!|^amend!|WIP|DROPME)')
|
||||
|
||||
if [ -z "$commits" ]; then
|
||||
echo "No fixup commits found."
|
||||
|
|
|
|||
Loading…
Reference in a new issue