1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-01-26 05:37:18 +02:00
lazygit/pkg/gui/controllers/helpers/commits_helper.go
Stefan Haller 61bd3e8dd2 Add key binding for switching from the commit message panel to an editor
This is useful for when you begin to type the message in lazygit's commit panel,
and then realize that you'd rather use your editor's more powerful editing
capabilities. Pressing <c-o> will take you right there.
2023-08-21 10:03:34 +02:00

194 lines
4.9 KiB
Go

package helpers
import (
"path/filepath"
"strings"
"time"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
type ICommitsHelper interface {
UpdateCommitPanelView(message string)
}
type CommitsHelper struct {
c *HelperCommon
getCommitSummary func() string
setCommitSummary func(string)
getCommitDescription func() string
setCommitDescription func(string)
}
var _ ICommitsHelper = &CommitsHelper{}
func NewCommitsHelper(
c *HelperCommon,
getCommitSummary func() string,
setCommitSummary func(string),
getCommitDescription func() string,
setCommitDescription func(string),
) *CommitsHelper {
return &CommitsHelper{
c: c,
getCommitSummary: getCommitSummary,
setCommitSummary: setCommitSummary,
getCommitDescription: getCommitDescription,
setCommitDescription: setCommitDescription,
}
}
func (self *CommitsHelper) SplitCommitMessageAndDescription(message string) (string, string) {
for _, separator := range []string{"\n\n", "\n\r\n\r", "\n", "\n\r"} {
msg, description, found := strings.Cut(message, separator)
if found {
return msg, description
}
}
return message, ""
}
func (self *CommitsHelper) SetMessageAndDescriptionInView(message string) {
summary, description := self.SplitCommitMessageAndDescription(message)
self.setCommitSummary(summary)
self.setCommitDescription(description)
self.c.Contexts().CommitMessage.RenderCommitLength()
}
func (self *CommitsHelper) JoinCommitMessageAndDescription() string {
if len(self.getCommitDescription()) == 0 {
return self.getCommitSummary()
}
return self.getCommitSummary() + "\n" + self.getCommitDescription()
}
func (self *CommitsHelper) SwitchToEditor() error {
if !self.c.Contexts().CommitMessage.CanSwitchToEditor() {
return nil
}
message := lo.Ternary(len(self.getCommitDescription()) == 0,
self.getCommitSummary(),
self.getCommitSummary()+"\n\n"+self.getCommitDescription())
filepath := filepath.Join(self.c.OS().GetTempDir(), self.c.Git().RepoPaths.RepoName(), time.Now().Format("Jan _2 15.04.05.000000000")+".msg")
err := self.c.OS().CreateFileWithContent(filepath, message)
if err != nil {
return err
}
err = self.CloseCommitMessagePanel()
if err != nil {
return err
}
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.GetPreservedMessage()
self.SetMessageAndDescriptionInView(preservedMessage)
return
}
self.SetMessageAndDescriptionInView("")
}
type OpenCommitMessagePanelOpts struct {
CommitIndex int
SummaryTitle string
DescriptionTitle string
PreserveMessage bool
OnConfirm func(summary string, description string) error
OnSwitchToEditor func(string) error
InitialMessage string
}
func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOpts) error {
onConfirm := func(summary string, description string) error {
if err := self.CloseCommitMessagePanel(); err != nil {
return err
}
return opts.OnConfirm(summary, description)
}
self.c.Contexts().CommitMessage.SetPanelState(
opts.CommitIndex,
opts.SummaryTitle,
opts.DescriptionTitle,
opts.PreserveMessage,
onConfirm,
opts.OnSwitchToEditor,
)
self.UpdateCommitPanelView(opts.InitialMessage)
return self.pushCommitMessageContexts()
}
func (self *CommitsHelper) OnCommitSuccess() {
// if we have a preserved message we want to clear it on success
if self.c.Contexts().CommitMessage.GetPreserveMessage() {
self.c.Contexts().CommitMessage.SetPreservedMessage("")
}
}
func (self *CommitsHelper) HandleCommitConfirm() error {
summary, description := self.getCommitSummary(), self.getCommitDescription()
if summary == "" {
return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
}
err := self.c.Contexts().CommitMessage.OnConfirm(summary, description)
if err != nil {
return err
}
return nil
}
func (self *CommitsHelper) CloseCommitMessagePanel() error {
if self.c.Contexts().CommitMessage.GetPreserveMessage() {
message := self.JoinCommitMessageAndDescription()
self.c.Contexts().CommitMessage.SetPreservedMessage(message)
} else {
self.SetMessageAndDescriptionInView("")
}
self.c.Contexts().CommitMessage.SetHistoryMessage("")
return self.PopCommitMessageContexts()
}
func (self *CommitsHelper) PopCommitMessageContexts() error {
return self.c.RemoveContexts(self.commitMessageContexts())
}
func (self *CommitsHelper) pushCommitMessageContexts() error {
for _, context := range self.commitMessageContexts() {
if err := self.c.PushContext(context); err != nil {
return err
}
}
return nil
}
func (self *CommitsHelper) commitMessageContexts() []types.Context {
return []types.Context{
self.c.Contexts().CommitDescription,
self.c.Contexts().CommitMessage,
}
}