Add option to copy commit message body

This commit is contained in:
Chris McDonnell 2025-02-15 19:48:54 -05:00
parent 01eece3737
commit ab23539c0c
8 changed files with 166 additions and 45 deletions

View file

@ -122,7 +122,24 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
return bindings
}
func (self *BasicCommitsController) getCommitMessageBody(hash string) string {
commitMessageBody, err := self.c.Git().Commit.GetCommitMessage(hash)
if err != nil {
return ""
}
_, body := self.c.Helpers().Commits.SplitCommitMessageAndDescription(commitMessageBody)
return body
}
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
commitMessageBody := self.getCommitMessageBody(commit.Hash)
var commitMessageBodyDisabled *types.DisabledReason
if commitMessageBody == "" {
commitMessageBodyDisabled = &types.DisabledReason{
Text: self.c.Tr.CommitHasNoMessageBody,
}
}
items := []*types.MenuItem{
{
Label: self.c.Tr.CommitHash,
@ -144,6 +161,14 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
},
Key: 'm',
},
{
Label: self.c.Tr.CommitMessageBody,
DisabledReason: commitMessageBodyDisabled,
OnPress: func() error {
return self.copyCommitMessageBodyToClipboard(commitMessageBody)
},
Key: 'b',
},
{
Label: self.c.Tr.CommitURL,
OnPress: func() error {
@ -259,6 +284,16 @@ func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.
return nil
}
func (self *BasicCommitsController) copyCommitMessageBodyToClipboard(commitMessageBody string) error {
self.c.LogAction(self.c.Tr.Actions.CopyCommitMessageBodyToClipboard)
if err := self.c.OS().CopyToClipboard(commitMessageBody); err != nil {
return err
}
self.c.Toast(self.c.Tr.CommitMessageBodyCopiedToClipboard)
return nil
}
func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.Commit) error {
message, err := self.c.Git().Commit.GetCommitSubject(commit.Hash)
if err != nil {

View file

@ -621,6 +621,7 @@ type TranslationSet struct {
PasteCommitMessageFromClipboard string
SurePasteCommitMessage string
CommitMessage string
CommitMessageBody string
CommitSubject string
CommitAuthor string
CommitTags string
@ -685,10 +686,12 @@ type TranslationSet struct {
CommitDiffCopiedToClipboard string
CommitURLCopiedToClipboard string
CommitMessageCopiedToClipboard string
CommitMessageBodyCopiedToClipboard string
CommitSubjectCopiedToClipboard string
CommitAuthorCopiedToClipboard string
CommitTagsCopiedToClipboard string
CommitHasNoTags string
CommitHasNoMessageBody string
PatchCopiedToClipboard string
CopiedToClipboard string
ErrCannotEditDirectory string
@ -914,6 +917,7 @@ type Actions struct {
MoveCommitUp string
MoveCommitDown string
CopyCommitMessageToClipboard string
CopyCommitMessageBodyToClipboard string
CopyCommitSubjectToClipboard string
CopyCommitDiffToClipboard string
CopyCommitHashToClipboard string
@ -1653,7 +1657,8 @@ func EnglishTranslationSet() *TranslationSet {
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
PasteCommitMessageFromClipboard: "Paste commit message from clipboard",
SurePasteCommitMessage: "Pasting will overwrite the current commit message, continue?",
CommitMessage: "Commit message",
CommitMessage: "Commit message (subject and body)",
CommitMessageBody: "Commit message body",
CommitSubject: "Commit subject",
CommitAuthor: "Commit author",
CommitTags: "Commit tags",
@ -1717,10 +1722,12 @@ func EnglishTranslationSet() *TranslationSet {
CommitDiffCopiedToClipboard: "Commit diff copied to clipboard",
CommitURLCopiedToClipboard: "Commit URL copied to clipboard",
CommitMessageCopiedToClipboard: "Commit message copied to clipboard",
CommitMessageBodyCopiedToClipboard: "Commit message body copied to clipboard",
CommitSubjectCopiedToClipboard: "Commit subject copied to clipboard",
CommitAuthorCopiedToClipboard: "Commit author copied to clipboard",
CommitTagsCopiedToClipboard: "Commit tags copied to clipboard",
CommitHasNoTags: "Commit has no tags",
CommitHasNoMessageBody: "Commit has no message body",
PatchCopiedToClipboard: "Patch copied to clipboard",
CopiedToClipboard: "copied to clipboard",
ErrCannotEditDirectory: "Cannot edit directories: you can only edit individual files",
@ -1873,48 +1880,49 @@ func EnglishTranslationSet() *TranslationSet {
Actions: Actions{
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
CheckoutCommit: "Checkout commit",
CheckoutBranchAtCommit: "Checkout branch '%s'",
CheckoutCommitAsDetachedHead: "Checkout commit %s as detached head",
CheckoutTag: "Checkout tag",
CheckoutBranch: "Checkout branch",
ForceCheckoutBranch: "Force checkout branch",
CheckoutBranchOrCommit: "Checkout branch or commit",
DeleteLocalBranch: "Delete local branch",
Merge: "Merge",
SquashMerge: "Squash merge",
RebaseBranch: "Rebase branch",
RenameBranch: "Rename branch",
CreateBranch: "Create branch",
CherryPick: "(Cherry-pick) paste commits",
CheckoutFile: "Checkout file",
DiscardOldFileChange: "Discard old file change",
SquashCommitDown: "Squash commit down",
FixupCommit: "Fixup commit",
RewordCommit: "Reword commit",
DropCommit: "Drop commit",
EditCommit: "Edit commit",
AmendCommit: "Amend commit",
ResetCommitAuthor: "Reset commit author",
SetCommitAuthor: "Set commit author",
AddCommitCoAuthor: "Add commit co-author",
RevertCommit: "Revert commit",
CreateFixupCommit: "Create fixup commit",
SquashAllAboveFixupCommits: "Squash all above fixup commits",
CreateLightweightTag: "Create lightweight tag",
CreateAnnotatedTag: "Create annotated tag",
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
CopyCommitSubjectToClipboard: "Copy commit subject to clipboard",
CopyCommitTagsToClipboard: "Copy commit tags to clipboard",
CopyCommitDiffToClipboard: "Copy commit diff to clipboard",
CopyCommitHashToClipboard: "Copy full commit hash to clipboard",
CopyCommitURLToClipboard: "Copy commit URL to clipboard",
CopyCommitAuthorToClipboard: "Copy commit author to clipboard",
CopyCommitAttributeToClipboard: "Copy to clipboard",
CopyPatchToClipboard: "Copy patch to clipboard",
MoveCommitUp: "Move commit up",
MoveCommitDown: "Move commit down",
CustomCommand: "Custom command",
CheckoutCommit: "Checkout commit",
CheckoutBranchAtCommit: "Checkout branch '%s'",
CheckoutCommitAsDetachedHead: "Checkout commit %s as detached head",
CheckoutTag: "Checkout tag",
CheckoutBranch: "Checkout branch",
ForceCheckoutBranch: "Force checkout branch",
CheckoutBranchOrCommit: "Checkout branch or commit",
DeleteLocalBranch: "Delete local branch",
Merge: "Merge",
SquashMerge: "Squash merge",
RebaseBranch: "Rebase branch",
RenameBranch: "Rename branch",
CreateBranch: "Create branch",
CherryPick: "(Cherry-pick) paste commits",
CheckoutFile: "Checkout file",
DiscardOldFileChange: "Discard old file change",
SquashCommitDown: "Squash commit down",
FixupCommit: "Fixup commit",
RewordCommit: "Reword commit",
DropCommit: "Drop commit",
EditCommit: "Edit commit",
AmendCommit: "Amend commit",
ResetCommitAuthor: "Reset commit author",
SetCommitAuthor: "Set commit author",
AddCommitCoAuthor: "Add commit co-author",
RevertCommit: "Revert commit",
CreateFixupCommit: "Create fixup commit",
SquashAllAboveFixupCommits: "Squash all above fixup commits",
CreateLightweightTag: "Create lightweight tag",
CreateAnnotatedTag: "Create annotated tag",
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
CopyCommitMessageBodyToClipboard: "Copy commit message body to clipboard",
CopyCommitSubjectToClipboard: "Copy commit subject to clipboard",
CopyCommitTagsToClipboard: "Copy commit tags to clipboard",
CopyCommitDiffToClipboard: "Copy commit diff to clipboard",
CopyCommitHashToClipboard: "Copy full commit hash to clipboard",
CopyCommitURLToClipboard: "Copy commit URL to clipboard",
CopyCommitAuthorToClipboard: "Copy commit author to clipboard",
CopyCommitAttributeToClipboard: "Copy to clipboard",
CopyPatchToClipboard: "Copy patch to clipboard",
MoveCommitUp: "Move commit up",
MoveCommitDown: "Move commit down",
CustomCommand: "Custom command",
// TODO: remove
DiscardAllChangesInDirectory: "Discard all changes in directory",

View file

@ -174,6 +174,10 @@ func (self *Shell) EmptyCommit(message string) *Shell {
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", message})
}
func (self *Shell) EmptyCommitWithBody(subject string, body string) *Shell {
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", subject, "-m", body})
}
func (self *Shell) EmptyCommitDaysAgo(message string, daysAgo int) *Shell {
return self.RunCommand([]string{"git", "commit", "--allow-empty", "--date", fmt.Sprintf("%d days ago", daysAgo), "-m", message})
}

View file

@ -0,0 +1,39 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
// We're emulating the clipboard by writing to a file called clipboard
var CopyMessageBodyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Copy a commit message body to the clipboard",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {
config.GetUserConfig().OS.CopyToClipboardCmd = "printf '%s' {{text}} > clipboard"
},
SetupRepo: func(shell *Shell) {
shell.EmptyCommitWithBody("My Subject", "My awesome commit message body")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("My Subject").IsSelected(),
).
Press(keys.Commits.CopyCommitAttributeToClipboard)
t.ExpectPopup().Menu().
Title(Equals("Copy to clipboard")).
Select(Contains("Commit message body")).
Confirm()
t.ExpectToast(Equals("Commit message body copied to clipboard"))
t.FileSystem().FileContent("clipboard", Equals("My awesome commit message body"))
},
})

View file

@ -0,0 +1,33 @@
package commit
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var DisableCopyCommitMessageBody = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Disables copy commit message body when there is no body",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("commit")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Commits().
Focus().
Lines(
Contains("commit").IsSelected(),
).
Press(keys.Commits.CopyCommitAttributeToClipboard)
t.ExpectPopup().Menu().
Title(Equals("Copy to clipboard")).
Select(Contains("Commit message body")).
Confirm()
t.ExpectToast(Equals("Disabled: Commit has no message body"))
},
})

View file

@ -26,7 +26,7 @@ var PasteCommitMessage = NewIntegrationTest(NewIntegrationTestArgs{
Press(keys.Commits.CopyCommitAttributeToClipboard)
t.ExpectPopup().Menu().Title(Equals("Copy to clipboard")).
Select(Contains("Commit message")).Confirm()
Select(Contains("Commit message (subject and body)")).Confirm()
t.ExpectToast(Equals("Commit message copied to clipboard"))

View file

@ -26,7 +26,7 @@ var PasteCommitMessageOverExisting = NewIntegrationTest(NewIntegrationTestArgs{
Press(keys.Commits.CopyCommitAttributeToClipboard)
t.ExpectPopup().Menu().Title(Equals("Copy to clipboard")).
Select(Contains("Commit message")).Confirm()
Select(Contains("Commit message (subject and body)")).Confirm()
t.ExpectToast(Equals("Commit message copied to clipboard"))

View file

@ -97,10 +97,12 @@ var tests = []*components.IntegrationTest{
commit.CommitWithNonMatchingBranchName,
commit.CommitWithPrefix,
commit.CopyAuthorToClipboard,
commit.CopyMessageBodyToClipboard,
commit.CopyTagToClipboard,
commit.CreateAmendCommit,
commit.CreateFixupCommitInBranchStack,
commit.CreateTag,
commit.DisableCopyCommitMessageBody,
commit.DiscardOldFileChanges,
commit.FindBaseCommitForFixup,
commit.FindBaseCommitForFixupDisregardMainBranch,