Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ git:
useConfig: false
commit:
signOff: false
autoWrapCommitMessage: true # automatic WYSIWYG wrapping of the commit message as you type
autoWrapWidth: 72 # if autoWrapCommitMessage is true, the width to wrap to
merging:
# only applicable to unix users
manualCommit: false
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ require (
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/creack/pty v1.1.11
github.com/fsmiamoto/git-todo-parser v0.0.5
github.com/gdamore/tcell/v2 v2.7.3
github.com/gdamore/tcell/v2 v2.7.4
github.com/go-errors/errors v1.5.1
github.com/gookit/color v1.4.2
github.com/imdario/mergo v0.3.11
github.com/integrii/flaggy v1.4.0
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
github.com/jesseduffield/gocui v0.3.1-0.20240303173746-f2b0f1f68dd8
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
Expand Down Expand Up @@ -74,8 +74,8 @@ require (
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ github.com/fsmiamoto/git-todo-parser v0.0.5/go.mod h1:B+AgTbNE2BARvJqzXygThzqxLI
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell/v2 v2.7.3 h1:YLQlOj5F0hSlKy5TJvlych29+WTcJzbElnLYwx8gvdg=
github.com/gdamore/tcell/v2 v2.7.3/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
Expand Down Expand Up @@ -187,8 +187,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
github.com/jesseduffield/gocui v0.3.1-0.20240303173746-f2b0f1f68dd8 h1:DGyAjpaAnxDuKO4MEoFjifhkUV7sU6znMR9eRfjjvn0=
github.com/jesseduffield/gocui v0.3.1-0.20240303173746-f2b0f1f68dd8/go.mod h1:lLLfxEGyIvvkzzpHdKkfgIVFmxqEejeACxKMVxSHLeM=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de h1:2ww1SWgakihE8hFxZ7L3agVeGpA6qwW5vdnhFUXKMQo=
github.com/jesseduffield/gocui v0.3.1-0.20240309085756-86e0d5a312de/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
Expand Down Expand Up @@ -470,13 +470,15 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/git_commands/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (self *CommitCommands) GetCommitMessage(commitSha string) (string, error) {
ToArgv()

message, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
return strings.TrimSpace(message), err
return strings.ReplaceAll(strings.TrimSpace(message), "\r\n", "\n"), err
}

func (self *CommitCommands) GetCommitSubject(commitSha string) (string, error) {
Expand Down
8 changes: 7 additions & 1 deletion pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ type PagingConfig struct {
type CommitConfig struct {
// If true, pass '--signoff' flag when committing
SignOff bool `yaml:"signOff"`
// Automatic WYSIWYG wrapping of the commit message as you type
AutoWrapCommitMessage bool `yaml:"autoWrapCommitMessage"`
// If autoWrapCommitMessage is true, the width to wrap to
AutoWrapWidth int `yaml:"autoWrapWidth"`
}

type MergingConfig struct {
Expand Down Expand Up @@ -658,7 +662,9 @@ func GetDefaultConfig() *UserConfig {
ExternalDiffCommand: "",
},
Commit: CommitConfig{
SignOff: false,
SignOff: false,
AutoWrapCommitMessage: true,
AutoWrapWidth: 72,
},
Merging: MergingConfig{
ManualCommit: false,
Expand Down
4 changes: 4 additions & 0 deletions pkg/gui/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ func (gui *Gui) resetHelpersAndControllers() {
getCommitDescription := func() string {
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetContent())
}
getUnwrappedCommitDescription := func() string {
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetUnwrappedContent())
}
commitsHelper := helpers.NewCommitsHelper(helperCommon,
getCommitSummary,
setCommitSummary,
getCommitDescription,
getUnwrappedCommitDescription,
setCommitDescription,
)

Expand Down
6 changes: 5 additions & 1 deletion pkg/gui/controllers/commit_message_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controllers
import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)

Expand Down Expand Up @@ -100,7 +101,7 @@ func (self *CommitMessageController) handleCommitIndexChange(value int) error {
self.c.Helpers().Commits.SetMessageAndDescriptionInView(self.context().GetHistoryMessage())
return nil
} else if currentIndex == context.NoCommitIndex {
self.context().SetHistoryMessage(self.c.Helpers().Commits.JoinCommitMessageAndDescription())
self.context().SetHistoryMessage(self.c.Helpers().Commits.JoinCommitMessageAndUnwrappedDescription())
}

validCommit, err := self.setCommitMessageAtIndex(newIndex)
Expand All @@ -119,6 +120,9 @@ func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, e
}
return false, self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
}
if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
}
self.c.Helpers().Commits.UpdateCommitPanelView(commitMessage)
return true, nil
}
Expand Down
55 changes: 42 additions & 13 deletions pkg/gui/controllers/helpers/commits_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strings"
"time"

"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
Expand All @@ -16,10 +17,11 @@ type ICommitsHelper interface {
type CommitsHelper struct {
c *HelperCommon

getCommitSummary func() string
setCommitSummary func(string)
getCommitDescription func() string
setCommitDescription func(string)
getCommitSummary func() string
setCommitSummary func(string)
getCommitDescription func() string
getUnwrappedCommitDescription func() string
setCommitDescription func(string)
}

var _ ICommitsHelper = &CommitsHelper{}
Expand All @@ -29,14 +31,16 @@ func NewCommitsHelper(
getCommitSummary func() string,
setCommitSummary func(string),
getCommitDescription func() string,
getUnwrappedCommitDescription func() string,
setCommitDescription func(string),
) *CommitsHelper {
return &CommitsHelper{
c: c,
getCommitSummary: getCommitSummary,
setCommitSummary: setCommitSummary,
getCommitDescription: getCommitDescription,
setCommitDescription: setCommitDescription,
c: c,
getCommitSummary: getCommitSummary,
setCommitSummary: setCommitSummary,
getCommitDescription: getCommitDescription,
getUnwrappedCommitDescription: getUnwrappedCommitDescription,
setCommitDescription: setCommitDescription,
}
}

Expand All @@ -53,11 +57,36 @@ func (self *CommitsHelper) SetMessageAndDescriptionInView(message string) {
self.c.Contexts().CommitMessage.RenderCommitLength()
}

func (self *CommitsHelper) JoinCommitMessageAndDescription() string {
if len(self.getCommitDescription()) == 0 {
func (self *CommitsHelper) JoinCommitMessageAndUnwrappedDescription() string {
if len(self.getUnwrappedCommitDescription()) == 0 {
return self.getCommitSummary()
}
return self.getCommitSummary() + "\n" + self.getCommitDescription()
return self.getCommitSummary() + "\n" + self.getUnwrappedCommitDescription()
}

func TryRemoveHardLineBreaks(message string, autoWrapWidth int) string {
messageRunes := []rune(message)
lastHardLineStart := 0
for i, r := range messageRunes {
if r == '\n' {
// Try to make this a soft linebreak by turning it into a space, and
// checking whether it still wraps to the same result then.
messageRunes[i] = ' '

_, cursorMapping := gocui.AutoWrapContent(messageRunes[lastHardLineStart:], autoWrapWidth)

// Look at the cursorMapping to check whether auto-wrapping inserted
// a line break. If it did, there will be a cursorMapping entry with
// Orig pointing to the position after the inserted line break.
if len(cursorMapping) == 0 || cursorMapping[0].Orig != i-lastHardLineStart+1 {
// It didn't, so change it back to a newline
messageRunes[i] = '\n'
}
lastHardLineStart = i + 1
}
}

return string(messageRunes)
}

func (self *CommitsHelper) SwitchToEditor() error {
Expand Down Expand Up @@ -154,7 +183,7 @@ func (self *CommitsHelper) HandleCommitConfirm() error {

func (self *CommitsHelper) CloseCommitMessagePanel() error {
if self.c.Contexts().CommitMessage.GetPreserveMessage() {
message := self.JoinCommitMessageAndDescription()
message := self.JoinCommitMessageAndUnwrappedDescription()

self.c.Contexts().CommitMessage.SetPreservedMessage(message)
} else {
Expand Down
41 changes: 41 additions & 0 deletions pkg/gui/controllers/helpers/commits_helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package helpers

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestTryRemoveHardLineBreaks(t *testing.T) {
scenarios := []struct {
name string
message string
autoWrapWidth int
expectedResult string
}{
{
name: "empty",
message: "",
autoWrapWidth: 7,
expectedResult: "",
},
{
name: "all line breaks are needed",
message: "abc\ndef\n\nxyz",
autoWrapWidth: 7,
expectedResult: "abc\ndef\n\nxyz",
},
{
name: "some can be unwrapped",
message: "123\nabc def\nghi jkl\nmno\n456\n",
autoWrapWidth: 7,
expectedResult: "123\nabc def ghi jkl mno\n456\n",
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
actualResult := TryRemoveHardLineBreaks(s.message, s.autoWrapWidth)
assert.Equal(t, s.expectedResult, actualResult)
})
}
}
4 changes: 3 additions & 1 deletion pkg/gui/controllers/local_commits_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,9 @@ func (self *LocalCommitsController) reword(commit *models.Commit) error {
if err != nil {
return self.c.Error(err)
}

if self.c.UserConfig.Git.Commit.AutoWrapCommitMessage {
commitMessage = helpers.TryRemoveHardLineBreaks(commitMessage, self.c.UserConfig.Git.Commit.AutoWrapWidth)
}
return self.c.Helpers().Commits.OpenCommitMessagePanel(
&helpers.OpenCommitMessagePanelOpts{
CommitIndex: self.context().GetSelectedLineIdx(),
Expand Down
2 changes: 2 additions & 0 deletions pkg/gui/views.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ func (gui *Gui) createAllViews() error {
gui.Views.CommitDescription.FgColor = theme.GocuiDefaultTextColor
gui.Views.CommitDescription.Editable = true
gui.Views.CommitDescription.Editor = gocui.EditorFunc(gui.commitDescriptionEditor)
gui.Views.CommitDescription.TextArea.AutoWrap = gui.c.UserConfig.Git.Commit.AutoWrapCommitMessage
gui.Views.CommitDescription.TextArea.AutoWrapWidth = gui.c.UserConfig.Git.Commit.AutoWrapWidth

gui.Views.Confirmation.Visible = false
gui.Views.Confirmation.Editor = gocui.EditorFunc(gui.promptEditor)
Expand Down
10 changes: 10 additions & 0 deletions pkg/integration/components/commit_description_panel_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ func (self *CommitDescriptionPanelDriver) AddNewline() *CommitDescriptionPanelDr
return self
}

func (self *CommitDescriptionPanelDriver) GoToBeginning() *CommitDescriptionPanelDriver {
numLines := len(self.getViewDriver().getView().BufferLines())
for i := 0; i < numLines; i++ {
self.t.pressFast("<up>")
}

self.t.pressFast("<c-a>")
return self
}

func (self *CommitDescriptionPanelDriver) Title(expected *TextMatcher) *CommitDescriptionPanelDriver {
self.getViewDriver().Title(expected)

Expand Down
59 changes: 59 additions & 0 deletions pkg/integration/tests/commit/auto_wrap_message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package commit

import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)

var AutoWrapMessage = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Commit, and test how the commit message body is auto-wrapped",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
// Use a ridiculously small width so that we don't have to use so much test data
config.UserConfig.Git.Commit.AutoWrapWidth = 20
},
SetupRepo: func(shell *Shell) {
shell.CreateFile("file", "file content")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
IsEmpty()

t.Views().Files().
IsFocused().
PressPrimaryAction(). // stage file
Press(keys.Files.CommitChanges)

t.ExpectPopup().CommitMessagePanel().
Type("subject").
SwitchToDescription().
Type("Lorem ipsum dolor sit amet, consectetur adipiscing elit.").
// See how it automatically inserted line feeds to wrap the text:
Content(Equals("Lorem ipsum dolor \nsit amet, \nconsectetur \nadipiscing elit.")).
SwitchToSummary().
Confirm()

t.Views().Commits().
Lines(
Contains("subject"),
).
Focus().
Tap(func() {
t.Views().Main().Content(Contains(
"subject\n \n Lorem ipsum dolor\n sit amet,\n consectetur\n adipiscing elit."))
}).
Press(keys.Commits.RenameCommit)

// Test that when rewording, the hard line breaks are turned back into
// soft ones, so that we can insert text at the beginning and have the
// paragraph reflow nicely.
t.ExpectPopup().CommitMessagePanel().
InitialText(Equals("subject")).
SwitchToDescription().
Content(Equals("Lorem ipsum dolor \nsit amet, \nconsectetur \nadipiscing elit.")).
GoToBeginning().
Type("More text. ").
Content(Equals("More text. Lorem \nipsum dolor sit \namet, consectetur \nadipiscing elit."))
},
})
1 change: 1 addition & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ var tests = []*components.IntegrationTest{
cherry_pick.CherryPickRange,
commit.AddCoAuthor,
commit.Amend,
commit.AutoWrapMessage,
commit.Commit,
commit.CommitMultiline,
commit.CommitSwitchToEditor,
Expand Down
Loading