mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-15 01:34:26 +02:00
Merge pull request #2390 from seand52/revamp-commit-message
This commit is contained in:
@ -171,7 +171,6 @@ keybinding:
|
|||||||
diffingMenu-alt: '<c-e>' # deprecated
|
diffingMenu-alt: '<c-e>' # deprecated
|
||||||
copyToClipboard: '<c-o>'
|
copyToClipboard: '<c-o>'
|
||||||
submitEditorText: '<enter>'
|
submitEditorText: '<enter>'
|
||||||
appendNewline: '<a-enter>'
|
|
||||||
extrasMenu: '@'
|
extrasMenu: '@'
|
||||||
toggleWhitespaceInDiffView: '<c-w>'
|
toggleWhitespaceInDiffView: '<c-w>'
|
||||||
increaseContextInDiffView: '}'
|
increaseContextInDiffView: '}'
|
||||||
|
@ -87,33 +87,34 @@ func writeString(file *os.File, str string) {
|
|||||||
|
|
||||||
func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
func localisedTitle(tr *i18n.TranslationSet, str string) string {
|
||||||
contextTitleMap := map[string]string{
|
contextTitleMap := map[string]string{
|
||||||
"global": tr.GlobalTitle,
|
"global": tr.GlobalTitle,
|
||||||
"navigation": tr.NavigationTitle,
|
"navigation": tr.NavigationTitle,
|
||||||
"branches": tr.BranchesTitle,
|
"branches": tr.BranchesTitle,
|
||||||
"localBranches": tr.LocalBranchesTitle,
|
"localBranches": tr.LocalBranchesTitle,
|
||||||
"files": tr.FilesTitle,
|
"files": tr.FilesTitle,
|
||||||
"status": tr.StatusTitle,
|
"status": tr.StatusTitle,
|
||||||
"submodules": tr.SubmodulesTitle,
|
"submodules": tr.SubmodulesTitle,
|
||||||
"subCommits": tr.SubCommitsTitle,
|
"subCommits": tr.SubCommitsTitle,
|
||||||
"remoteBranches": tr.RemoteBranchesTitle,
|
"remoteBranches": tr.RemoteBranchesTitle,
|
||||||
"remotes": tr.RemotesTitle,
|
"remotes": tr.RemotesTitle,
|
||||||
"reflogCommits": tr.ReflogCommitsTitle,
|
"reflogCommits": tr.ReflogCommitsTitle,
|
||||||
"tags": tr.TagsTitle,
|
"tags": tr.TagsTitle,
|
||||||
"commitFiles": tr.CommitFilesTitle,
|
"commitFiles": tr.CommitFilesTitle,
|
||||||
"commitMessage": tr.CommitMessageTitle,
|
"commitMessage": tr.CommitMessageTitle,
|
||||||
"commits": tr.CommitsTitle,
|
"commitDescription": tr.CommitDescriptionTitle,
|
||||||
"confirmation": tr.ConfirmationTitle,
|
"commits": tr.CommitsTitle,
|
||||||
"information": tr.InformationTitle,
|
"confirmation": tr.ConfirmationTitle,
|
||||||
"main": tr.NormalTitle,
|
"information": tr.InformationTitle,
|
||||||
"patchBuilding": tr.PatchBuildingTitle,
|
"main": tr.NormalTitle,
|
||||||
"mergeConflicts": tr.MergingTitle,
|
"patchBuilding": tr.PatchBuildingTitle,
|
||||||
"staging": tr.StagingTitle,
|
"mergeConflicts": tr.MergingTitle,
|
||||||
"menu": tr.MenuTitle,
|
"staging": tr.StagingTitle,
|
||||||
"search": tr.SearchTitle,
|
"menu": tr.MenuTitle,
|
||||||
"secondary": tr.SecondaryTitle,
|
"search": tr.SearchTitle,
|
||||||
"stash": tr.StashTitle,
|
"secondary": tr.SecondaryTitle,
|
||||||
"suggestions": tr.SuggestionsCheatsheetTitle,
|
"stash": tr.StashTitle,
|
||||||
"extras": tr.ExtrasTitle,
|
"suggestions": tr.SuggestionsCheatsheetTitle,
|
||||||
|
"extras": tr.ExtrasTitle,
|
||||||
}
|
}
|
||||||
|
|
||||||
title, ok := contextTitleMap[str]
|
title, ok := contextTitleMap[str]
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrInvalidCommitIndex = errors.New("invalid commit index")
|
||||||
|
|
||||||
type CommitCommands struct {
|
type CommitCommands struct {
|
||||||
*GitCommon
|
*GitCommon
|
||||||
}
|
}
|
||||||
@ -18,11 +20,6 @@ func NewCommitCommands(gitCommon *GitCommon) *CommitCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RewordLastCommit rewords the topmost commit with the given message
|
|
||||||
func (self *CommitCommands) RewordLastCommit(message string) error {
|
|
||||||
return self.cmd.New("git commit --allow-empty --amend --only -m " + self.cmd.Quote(message)).Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetAuthor resets the author of the topmost commit
|
// ResetAuthor resets the author of the topmost commit
|
||||||
func (self *CommitCommands) ResetAuthor() error {
|
func (self *CommitCommands) ResetAuthor() error {
|
||||||
return self.cmd.New("git commit --allow-empty --only --no-edit --amend --reset-author").Run()
|
return self.cmd.New("git commit --allow-empty --only --no-edit --amend --reset-author").Run()
|
||||||
@ -45,11 +42,7 @@ func (self *CommitCommands) ResetToCommit(sha string, strength string, envVars [
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitCommands) CommitCmdObj(message string) oscommands.ICmdObj {
|
func (self *CommitCommands) CommitCmdObj(message string) oscommands.ICmdObj {
|
||||||
splitMessage := strings.Split(message, "\n")
|
messageArgs := self.commitMessageArgs(message)
|
||||||
lineArgs := ""
|
|
||||||
for _, line := range splitMessage {
|
|
||||||
lineArgs += fmt.Sprintf(" -m %s", self.cmd.Quote(line))
|
|
||||||
}
|
|
||||||
|
|
||||||
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
skipHookPrefix := self.UserConfig.Git.SkipHookPrefix
|
||||||
noVerifyFlag := ""
|
noVerifyFlag := ""
|
||||||
@ -57,7 +50,23 @@ func (self *CommitCommands) CommitCmdObj(message string) oscommands.ICmdObj {
|
|||||||
noVerifyFlag = " --no-verify"
|
noVerifyFlag = " --no-verify"
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.cmd.New(fmt.Sprintf("git commit%s%s%s", noVerifyFlag, self.signoffFlag(), lineArgs))
|
return self.cmd.New(fmt.Sprintf("git commit%s%s%s", noVerifyFlag, self.signoffFlag(), messageArgs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewordLastCommit rewords the topmost commit with the given message
|
||||||
|
func (self *CommitCommands) RewordLastCommit(message string) error {
|
||||||
|
messageArgs := self.commitMessageArgs(message)
|
||||||
|
return self.cmd.New(fmt.Sprintf("git commit --allow-empty --amend --only%s", messageArgs)).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitCommands) commitMessageArgs(message string) string {
|
||||||
|
msg, description, _ := strings.Cut(message, "\n")
|
||||||
|
descriptionArgs := ""
|
||||||
|
if description != "" {
|
||||||
|
descriptionArgs = fmt.Sprintf(" -m %s", self.cmd.Quote(description))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(" -m %s%s", self.cmd.Quote(msg), descriptionArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runs git commit without the -m argument meaning it will invoke the user's editor
|
// runs git commit without the -m argument meaning it will invoke the user's editor
|
||||||
@ -178,3 +187,13 @@ func (self *CommitCommands) RevertMerge(sha string, parentNumber int) error {
|
|||||||
func (self *CommitCommands) CreateFixupCommit(sha string) error {
|
func (self *CommitCommands) CreateFixupCommit(sha string) error {
|
||||||
return self.cmd.New(fmt.Sprintf("git commit --fixup=%s", sha)).Run()
|
return self.cmd.New(fmt.Sprintf("git commit --fixup=%s", sha)).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a value of 0 means the head commit, 1 is the parent commit, etc
|
||||||
|
func (self *CommitCommands) GetCommitMessageFromHistory(value int) (string, error) {
|
||||||
|
hash, _ := self.cmd.New(fmt.Sprintf("git log -1 --skip=%d --pretty=%%H", value)).DontLog().RunWithOutput()
|
||||||
|
formattedHash := strings.TrimSpace(hash)
|
||||||
|
if len(formattedHash) == 0 {
|
||||||
|
return "", ErrInvalidCommitIndex
|
||||||
|
}
|
||||||
|
return self.GetCommitMessage(formattedHash)
|
||||||
|
}
|
||||||
|
@ -9,12 +9,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCommitRewordCommit(t *testing.T) {
|
func TestCommitRewordCommit(t *testing.T) {
|
||||||
runner := oscommands.NewFakeRunner(t).
|
type scenario struct {
|
||||||
ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test"}, "", nil)
|
testName string
|
||||||
instance := buildCommitCommands(commonDeps{runner: runner})
|
runner *oscommands.FakeCmdObjRunner
|
||||||
|
input string
|
||||||
|
}
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
"Single line reword",
|
||||||
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test"}, "", nil),
|
||||||
|
"test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Multi line reword",
|
||||||
|
oscommands.NewFakeRunner(t).ExpectGitArgs([]string{"commit", "--allow-empty", "--amend", "--only", "-m", "test", "-m", "line 2\nline 3"}, "", nil),
|
||||||
|
"test\nline 2\nline 3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, s := range scenarios {
|
||||||
|
s := s
|
||||||
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
|
instance := buildCommitCommands(commonDeps{runner: s.runner})
|
||||||
|
|
||||||
assert.NoError(t, instance.RewordLastCommit("test"))
|
assert.NoError(t, instance.RewordLastCommit(s.input))
|
||||||
runner.CheckForMissingCalls()
|
s.runner.CheckForMissingCalls()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommitResetToCommit(t *testing.T) {
|
func TestCommitResetToCommit(t *testing.T) {
|
||||||
@ -274,3 +294,40 @@ Merge pull request #1750 from mark2185/fix-issue-template
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetCommitMessageFromHistory(t *testing.T) {
|
||||||
|
type scenario struct {
|
||||||
|
testName string
|
||||||
|
runner *oscommands.FakeCmdObjRunner
|
||||||
|
test func(string, error)
|
||||||
|
}
|
||||||
|
scenarios := []scenario{
|
||||||
|
{
|
||||||
|
"Empty message",
|
||||||
|
oscommands.NewFakeRunner(t).Expect("git log -1 --skip=2 --pretty=%H", "", nil).Expect("git rev-list --format=%B --max-count=1 ", "", nil),
|
||||||
|
func(output string, err error) {
|
||||||
|
assert.Error(t, err)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Default case to retrieve a commit in history",
|
||||||
|
oscommands.NewFakeRunner(t).Expect("git log -1 --skip=2 --pretty=%H", "sha3 \n", nil).Expect("git rev-list --format=%B --max-count=1 sha3", `commit sha3
|
||||||
|
use generics to DRY up context code`, nil),
|
||||||
|
func(output string, err error) {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "use generics to DRY up context code", output)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
s := s
|
||||||
|
t.Run(s.testName, func(t *testing.T) {
|
||||||
|
instance := buildCommitCommands(commonDeps{runner: s.runner})
|
||||||
|
|
||||||
|
output, err := instance.GetCommitMessageFromHistory(2)
|
||||||
|
|
||||||
|
s.test(output, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -165,6 +165,7 @@ type KeybindingUniversalConfig struct {
|
|||||||
Select string `yaml:"select"`
|
Select string `yaml:"select"`
|
||||||
GoInto string `yaml:"goInto"`
|
GoInto string `yaml:"goInto"`
|
||||||
Confirm string `yaml:"confirm"`
|
Confirm string `yaml:"confirm"`
|
||||||
|
ConfirmInEditor string `yaml:"confirmInEditor"`
|
||||||
Remove string `yaml:"remove"`
|
Remove string `yaml:"remove"`
|
||||||
New string `yaml:"new"`
|
New string `yaml:"new"`
|
||||||
Edit string `yaml:"edit"`
|
Edit string `yaml:"edit"`
|
||||||
@ -193,7 +194,6 @@ type KeybindingUniversalConfig struct {
|
|||||||
CopyToClipboard string `yaml:"copyToClipboard"`
|
CopyToClipboard string `yaml:"copyToClipboard"`
|
||||||
OpenRecentRepos string `yaml:"openRecentRepos"`
|
OpenRecentRepos string `yaml:"openRecentRepos"`
|
||||||
SubmitEditorText string `yaml:"submitEditorText"`
|
SubmitEditorText string `yaml:"submitEditorText"`
|
||||||
AppendNewline string `yaml:"appendNewline"`
|
|
||||||
ExtrasMenu string `yaml:"extrasMenu"`
|
ExtrasMenu string `yaml:"extrasMenu"`
|
||||||
ToggleWhitespaceInDiffView string `yaml:"toggleWhitespaceInDiffView"`
|
ToggleWhitespaceInDiffView string `yaml:"toggleWhitespaceInDiffView"`
|
||||||
IncreaseContextInDiffView string `yaml:"increaseContextInDiffView"`
|
IncreaseContextInDiffView string `yaml:"increaseContextInDiffView"`
|
||||||
@ -492,6 +492,7 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
Select: "<space>",
|
Select: "<space>",
|
||||||
GoInto: "<enter>",
|
GoInto: "<enter>",
|
||||||
Confirm: "<enter>",
|
Confirm: "<enter>",
|
||||||
|
ConfirmInEditor: "<a-enter>",
|
||||||
Remove: "d",
|
Remove: "d",
|
||||||
New: "n",
|
New: "n",
|
||||||
Edit: "e",
|
Edit: "e",
|
||||||
@ -520,7 +521,6 @@ func GetDefaultConfig() *UserConfig {
|
|||||||
DiffingMenuAlt: "<c-e>",
|
DiffingMenuAlt: "<c-e>",
|
||||||
CopyToClipboard: "<c-o>",
|
CopyToClipboard: "<c-o>",
|
||||||
SubmitEditorText: "<enter>",
|
SubmitEditorText: "<enter>",
|
||||||
AppendNewline: "<a-enter>",
|
|
||||||
ExtrasMenu: "@",
|
ExtrasMenu: "@",
|
||||||
ToggleWhitespaceInDiffView: "<c-w>",
|
ToggleWhitespaceInDiffView: "<c-w>",
|
||||||
IncreaseContextInDiffView: "}",
|
IncreaseContextInDiffView: "}",
|
||||||
|
@ -15,7 +15,6 @@ func (gui *Gui) handleCommitMessageFocused() error {
|
|||||||
map[string]string{
|
map[string]string{
|
||||||
"keyBindClose": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Return),
|
"keyBindClose": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Return),
|
||||||
"keyBindConfirm": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Confirm),
|
"keyBindConfirm": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Confirm),
|
||||||
"keyBindNewLine": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.AppendNewline),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,17 +78,11 @@ func (gui *Gui) getMessageHeight(wrap bool, message string, width int) int {
|
|||||||
return lineCount
|
return lineCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensions(wrap bool, prompt string) (int, int, int, int) {
|
func (gui *Gui) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) {
|
||||||
panelWidth := gui.getConfirmationPanelWidth()
|
return gui.getPopupPanelDimensionsAux(panelWidth, contentHeight)
|
||||||
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth)
|
|
||||||
return gui.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) {
|
func (gui *Gui) getPopupPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) {
|
||||||
return gui.getConfirmationPanelDimensionsAux(panelWidth, contentHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) {
|
|
||||||
width, height := gui.g.Size()
|
width, height := gui.g.Size()
|
||||||
if panelHeight > height*3/4 {
|
if panelHeight > height*3/4 {
|
||||||
panelHeight = height * 3 / 4
|
panelHeight = height * 3 / 4
|
||||||
@ -186,7 +180,7 @@ func (gui *Gui) createPopupPanel(ctx context.Context, opts types.CreatePopupPane
|
|||||||
}
|
}
|
||||||
confirmationView := gui.Views.Confirmation
|
confirmationView := gui.Views.Confirmation
|
||||||
confirmationView.Editable = opts.Editable
|
confirmationView.Editable = opts.Editable
|
||||||
confirmationView.Editor = gocui.EditorFunc(gui.defaultEditor)
|
confirmationView.Editor = gocui.EditorFunc(gui.promptEditor)
|
||||||
|
|
||||||
if opts.Editable {
|
if opts.Editable {
|
||||||
textArea := confirmationView.TextArea
|
textArea := confirmationView.TextArea
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file is for the management of contexts. There is a context stack such that
|
// This file is for the management of contexts. There is a context stack such that
|
||||||
@ -146,6 +147,36 @@ func (gui *Gui) popContext() error {
|
|||||||
return gui.activateContext(newContext, types.OnFocusOpts{})
|
return gui.activateContext(newContext, types.OnFocusOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) removeContexts(contextsToRemove []types.Context) error {
|
||||||
|
gui.State.ContextManager.Lock()
|
||||||
|
|
||||||
|
if len(gui.State.ContextManager.ContextStack) == 1 {
|
||||||
|
gui.State.ContextManager.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rest := lo.Filter(gui.State.ContextManager.ContextStack, func(context types.Context, _ int) bool {
|
||||||
|
for _, contextToRemove := range contextsToRemove {
|
||||||
|
if context.GetKey() == contextToRemove.GetKey() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
gui.State.ContextManager.ContextStack = rest
|
||||||
|
contextToActivate := rest[len(rest)-1]
|
||||||
|
gui.State.ContextManager.Unlock()
|
||||||
|
|
||||||
|
for _, context := range contextsToRemove {
|
||||||
|
if err := gui.deactivateContext(context, types.OnFocusLostOpts{NewContextKey: contextToActivate.GetKey()}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// activate the item at the top of the stack
|
||||||
|
return gui.activateContext(contextToActivate, types.OnFocusOpts{})
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) deactivateContext(c types.Context, opts types.OnFocusLostOpts) error {
|
func (gui *Gui) deactivateContext(c types.Context, opts types.OnFocusLostOpts) error {
|
||||||
view, _ := gui.g.View(c.GetViewName())
|
view, _ := gui.g.View(c.GetViewName())
|
||||||
|
|
||||||
|
95
pkg/gui/context/commit_message_context.go
Normal file
95
pkg/gui/context/commit_message_context.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommitMessageContext struct {
|
||||||
|
types.Context
|
||||||
|
viewModel *CommitMessageViewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
// when selectedIndex (see below) is set to this value, it means that we're not
|
||||||
|
// currently viewing a commit message of an existing commit: instead we're making our own
|
||||||
|
// new commit message
|
||||||
|
const NoCommitIndex = -1
|
||||||
|
|
||||||
|
type CommitMessageViewModel struct {
|
||||||
|
// index of the commit message, where -1 is 'no commit', 0 is the HEAD commit, 1
|
||||||
|
// is the prior commit, and so on
|
||||||
|
selectedindex int
|
||||||
|
// if true, then upon escaping from the commit message panel, we will preserve
|
||||||
|
// the message so that it's still shown next time we open the panel
|
||||||
|
preserveMessage bool
|
||||||
|
// the full preserved message (combined summary and description)
|
||||||
|
preservedMessage string
|
||||||
|
// invoked when pressing enter in the commit message panel
|
||||||
|
onConfirm func(string) error
|
||||||
|
|
||||||
|
// The message typed in before cycling through history
|
||||||
|
// We store this separately to 'preservedMessage' because 'preservedMessage'
|
||||||
|
// is specifically for committing staged files and we don't want this affected
|
||||||
|
// by cycling through history in the context of rewording an old commit.
|
||||||
|
historyMessage string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCommitMessageContext(
|
||||||
|
view *gocui.View,
|
||||||
|
opts ContextCallbackOpts,
|
||||||
|
) *CommitMessageContext {
|
||||||
|
viewModel := &CommitMessageViewModel{}
|
||||||
|
return &CommitMessageContext{
|
||||||
|
viewModel: viewModel,
|
||||||
|
Context: NewSimpleContext(
|
||||||
|
NewBaseContext(NewBaseContextOpts{
|
||||||
|
Kind: types.PERSISTENT_POPUP,
|
||||||
|
View: view,
|
||||||
|
WindowName: "commitMessage",
|
||||||
|
Key: COMMIT_MESSAGE_CONTEXT_KEY,
|
||||||
|
Focusable: true,
|
||||||
|
HasUncontrolledBounds: true,
|
||||||
|
}),
|
||||||
|
opts,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) SetSelectedIndex(value int) {
|
||||||
|
self.viewModel.selectedindex = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) GetSelectedIndex() int {
|
||||||
|
return self.viewModel.selectedindex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) GetPreserveMessage() bool {
|
||||||
|
return self.viewModel.preserveMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) GetPreservedMessage() string {
|
||||||
|
return self.viewModel.preservedMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) SetPreservedMessage(message string) {
|
||||||
|
self.viewModel.preservedMessage = message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) GetHistoryMessage() string {
|
||||||
|
return self.viewModel.historyMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) SetHistoryMessage(message string) {
|
||||||
|
self.viewModel.historyMessage = message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) OnConfirm(message string) error {
|
||||||
|
return self.viewModel.onConfirm(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) SetPanelState(index int, title string, preserveMessage bool, onConfirm func(string) error) {
|
||||||
|
self.viewModel.selectedindex = index
|
||||||
|
self.viewModel.preserveMessage = preserveMessage
|
||||||
|
self.viewModel.onConfirm = onConfirm
|
||||||
|
self.GetView().Title = title
|
||||||
|
}
|
@ -33,13 +33,14 @@ const (
|
|||||||
INFORMATION_CONTEXT_KEY types.ContextKey = "information"
|
INFORMATION_CONTEXT_KEY types.ContextKey = "information"
|
||||||
LIMIT_CONTEXT_KEY types.ContextKey = "limit"
|
LIMIT_CONTEXT_KEY types.ContextKey = "limit"
|
||||||
|
|
||||||
MENU_CONTEXT_KEY types.ContextKey = "menu"
|
MENU_CONTEXT_KEY types.ContextKey = "menu"
|
||||||
CONFIRMATION_CONTEXT_KEY types.ContextKey = "confirmation"
|
CONFIRMATION_CONTEXT_KEY types.ContextKey = "confirmation"
|
||||||
SEARCH_CONTEXT_KEY types.ContextKey = "search"
|
SEARCH_CONTEXT_KEY types.ContextKey = "search"
|
||||||
COMMIT_MESSAGE_CONTEXT_KEY types.ContextKey = "commitMessage"
|
COMMIT_MESSAGE_CONTEXT_KEY types.ContextKey = "commitMessage"
|
||||||
SUBMODULES_CONTEXT_KEY types.ContextKey = "submodules"
|
COMMIT_DESCRIPTION_CONTEXT_KEY types.ContextKey = "commitDescription"
|
||||||
SUGGESTIONS_CONTEXT_KEY types.ContextKey = "suggestions"
|
SUBMODULES_CONTEXT_KEY types.ContextKey = "submodules"
|
||||||
COMMAND_LOG_CONTEXT_KEY types.ContextKey = "cmdLog"
|
SUGGESTIONS_CONTEXT_KEY types.ContextKey = "suggestions"
|
||||||
|
COMMAND_LOG_CONTEXT_KEY types.ContextKey = "cmdLog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AllContextKeys = []types.ContextKey{
|
var AllContextKeys = []types.ContextKey{
|
||||||
@ -97,7 +98,8 @@ type ContextTree struct {
|
|||||||
CustomPatchBuilderSecondary types.Context
|
CustomPatchBuilderSecondary types.Context
|
||||||
MergeConflicts *MergeConflictsContext
|
MergeConflicts *MergeConflictsContext
|
||||||
Confirmation types.Context
|
Confirmation types.Context
|
||||||
CommitMessage types.Context
|
CommitMessage *CommitMessageContext
|
||||||
|
CommitDescription types.Context
|
||||||
CommandLog types.Context
|
CommandLog types.Context
|
||||||
|
|
||||||
// display contexts
|
// display contexts
|
||||||
@ -129,6 +131,7 @@ func (self *ContextTree) Flatten() []types.Context {
|
|||||||
self.Menu,
|
self.Menu,
|
||||||
self.Confirmation,
|
self.Confirmation,
|
||||||
self.CommitMessage,
|
self.CommitMessage,
|
||||||
|
self.CommitDescription,
|
||||||
|
|
||||||
self.MergeConflicts,
|
self.MergeConflicts,
|
||||||
self.StagingSecondary,
|
self.StagingSecondary,
|
||||||
|
@ -217,17 +217,29 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
CommitMessage: context.NewSimpleContext(
|
CommitMessage: context.NewCommitMessageContext(
|
||||||
|
gui.Views.CommitMessage,
|
||||||
|
context.ContextCallbackOpts{
|
||||||
|
OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CommitDescription: context.NewSimpleContext(
|
||||||
context.NewBaseContext(context.NewBaseContextOpts{
|
context.NewBaseContext(context.NewBaseContextOpts{
|
||||||
Kind: types.PERSISTENT_POPUP,
|
Kind: types.PERSISTENT_POPUP,
|
||||||
View: gui.Views.CommitMessage,
|
View: gui.Views.CommitDescription,
|
||||||
WindowName: "commitMessage",
|
WindowName: "commitDescription",
|
||||||
Key: context.COMMIT_MESSAGE_CONTEXT_KEY,
|
Key: context.COMMIT_DESCRIPTION_CONTEXT_KEY,
|
||||||
Focusable: true,
|
Focusable: true,
|
||||||
HasUncontrolledBounds: true,
|
HasUncontrolledBounds: true,
|
||||||
}),
|
}),
|
||||||
context.ContextCallbackOpts{
|
context.ContextCallbackOpts{
|
||||||
OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused),
|
OnFocus: func(opts types.OnFocusOpts) error {
|
||||||
|
_, err := gui.g.SetViewBeneath("commitDescription", "commitMessage", 10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Search: context.NewSimpleContext(
|
Search: context.NewSimpleContext(
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking"
|
"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands"
|
"github.com/jesseduffield/lazygit/pkg/gui/services/custom_commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/snake"
|
"github.com/jesseduffield/lazygit/pkg/snake"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,10 +25,24 @@ func (gui *Gui) resetControllers() {
|
|||||||
|
|
||||||
rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, gui.State.Contexts, gui.git, refsHelper)
|
rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, gui.State.Contexts, gui.git, refsHelper)
|
||||||
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon, model, gui.refreshSuggestions)
|
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon, model, gui.refreshSuggestions)
|
||||||
setCommitMessage := gui.getSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage })
|
setCommitSummary := gui.getCommitMessageSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage })
|
||||||
getSavedCommitMessage := func() string {
|
setCommitDescription := gui.getCommitMessageSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitDescription })
|
||||||
return gui.State.savedCommitMessage
|
getCommitSummary := func() string {
|
||||||
|
return strings.TrimSpace(gui.Views.CommitMessage.TextArea.GetContent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCommitDescription := func() string {
|
||||||
|
return strings.TrimSpace(gui.Views.CommitDescription.TextArea.GetContent())
|
||||||
|
}
|
||||||
|
commitsHelper := helpers.NewCommitsHelper(helperCommon,
|
||||||
|
gui.State.Model,
|
||||||
|
gui.State.Contexts,
|
||||||
|
getCommitSummary,
|
||||||
|
setCommitSummary,
|
||||||
|
getCommitDescription,
|
||||||
|
setCommitDescription,
|
||||||
|
gui.RenderCommitLength,
|
||||||
|
)
|
||||||
gpgHelper := helpers.NewGpgHelper(helperCommon, gui.os, gui.git)
|
gpgHelper := helpers.NewGpgHelper(helperCommon, gui.os, gui.git)
|
||||||
gui.helpers = &helpers.Helpers{
|
gui.helpers = &helpers.Helpers{
|
||||||
Refs: refsHelper,
|
Refs: refsHelper,
|
||||||
@ -38,7 +51,7 @@ func (gui *Gui) resetControllers() {
|
|||||||
Bisect: helpers.NewBisectHelper(helperCommon, gui.git),
|
Bisect: helpers.NewBisectHelper(helperCommon, gui.git),
|
||||||
Suggestions: suggestionsHelper,
|
Suggestions: suggestionsHelper,
|
||||||
Files: helpers.NewFilesHelper(helperCommon, gui.git, osCommand),
|
Files: helpers.NewFilesHelper(helperCommon, gui.git, osCommand),
|
||||||
WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, gui.git, gui.State.Contexts, refsHelper, model, setCommitMessage, getSavedCommitMessage),
|
WorkingTree: helpers.NewWorkingTreeHelper(helperCommon, gui.git, gui.State.Contexts, refsHelper, model, setCommitSummary, commitsHelper, gpgHelper),
|
||||||
Tags: helpers.NewTagsHelper(helperCommon, gui.git),
|
Tags: helpers.NewTagsHelper(helperCommon, gui.git),
|
||||||
GPG: gpgHelper,
|
GPG: gpgHelper,
|
||||||
MergeAndRebase: rebaseHelper,
|
MergeAndRebase: rebaseHelper,
|
||||||
@ -52,6 +65,7 @@ func (gui *Gui) resetControllers() {
|
|||||||
),
|
),
|
||||||
Upstream: helpers.NewUpstreamHelper(helperCommon, model, suggestionsHelper.GetRemoteBranchesSuggestionsFunc),
|
Upstream: helpers.NewUpstreamHelper(helperCommon, model, suggestionsHelper.GetRemoteBranchesSuggestionsFunc),
|
||||||
AmendHelper: helpers.NewAmendHelper(helperCommon, gui.git, gpgHelper),
|
AmendHelper: helpers.NewAmendHelper(helperCommon, gui.git, gpgHelper),
|
||||||
|
Commits: commitsHelper,
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.CustomCommandsClient = custom_commands.NewClient(
|
gui.CustomCommandsClient = custom_commands.NewClient(
|
||||||
@ -84,27 +98,12 @@ func (gui *Gui) resetControllers() {
|
|||||||
|
|
||||||
bisectController := controllers.NewBisectController(common)
|
bisectController := controllers.NewBisectController(common)
|
||||||
|
|
||||||
getCommitMessage := func() string {
|
|
||||||
return strings.TrimSpace(gui.Views.CommitMessage.TextArea.GetContent())
|
|
||||||
}
|
|
||||||
|
|
||||||
onCommitAttempt := func(message string) {
|
|
||||||
gui.State.savedCommitMessage = message
|
|
||||||
gui.Views.CommitMessage.ClearTextArea()
|
|
||||||
}
|
|
||||||
|
|
||||||
onCommitSuccess := func() {
|
|
||||||
gui.State.savedCommitMessage = ""
|
|
||||||
_ = gui.c.Refresh(types.RefreshOptions{
|
|
||||||
Scope: []types.RefreshableView{types.STAGING},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
commitMessageController := controllers.NewCommitMessageController(
|
commitMessageController := controllers.NewCommitMessageController(
|
||||||
common,
|
common,
|
||||||
getCommitMessage,
|
)
|
||||||
onCommitAttempt,
|
|
||||||
onCommitSuccess,
|
commitDescriptionController := controllers.NewCommitDescriptionController(
|
||||||
|
common,
|
||||||
)
|
)
|
||||||
|
|
||||||
remoteBranchesController := controllers.NewRemoteBranchesController(common)
|
remoteBranchesController := controllers.NewRemoteBranchesController(common)
|
||||||
@ -115,8 +114,7 @@ func (gui *Gui) resetControllers() {
|
|||||||
filesController := controllers.NewFilesController(
|
filesController := controllers.NewFilesController(
|
||||||
common,
|
common,
|
||||||
gui.enterSubmodule,
|
gui.enterSubmodule,
|
||||||
setCommitMessage,
|
setCommitSummary,
|
||||||
getSavedCommitMessage,
|
|
||||||
)
|
)
|
||||||
mergeConflictsController := controllers.NewMergeConflictsController(common)
|
mergeConflictsController := controllers.NewMergeConflictsController(common)
|
||||||
remotesController := controllers.NewRemotesController(
|
remotesController := controllers.NewRemotesController(
|
||||||
@ -250,6 +248,10 @@ func (gui *Gui) resetControllers() {
|
|||||||
commitMessageController,
|
commitMessageController,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
controllers.AttachControllers(gui.State.Contexts.CommitDescription,
|
||||||
|
commitDescriptionController,
|
||||||
|
)
|
||||||
|
|
||||||
controllers.AttachControllers(gui.State.Contexts.RemoteBranches,
|
controllers.AttachControllers(gui.State.Contexts.RemoteBranches,
|
||||||
remoteBranchesController,
|
remoteBranchesController,
|
||||||
)
|
)
|
||||||
|
60
pkg/gui/controllers/commit_description_controller.go
Normal file
60
pkg/gui/controllers/commit_description_controller.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommitDescriptionController struct {
|
||||||
|
baseController
|
||||||
|
*controllerCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.IController = &CommitMessageController{}
|
||||||
|
|
||||||
|
func NewCommitDescriptionController(
|
||||||
|
common *controllerCommon,
|
||||||
|
) *CommitDescriptionController {
|
||||||
|
return &CommitDescriptionController{
|
||||||
|
baseController: baseController{},
|
||||||
|
controllerCommon: common,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
|
bindings := []*types.Binding{
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
|
Handler: self.switchToCommitMessage,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
|
Handler: self.close,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.ConfirmInEditor),
|
||||||
|
Handler: self.confirm,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) Context() types.Context {
|
||||||
|
return self.context()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) context() types.Context {
|
||||||
|
return self.contexts.CommitMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) switchToCommitMessage() error {
|
||||||
|
return self.c.PushContext(self.contexts.CommitMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) close() error {
|
||||||
|
return self.helpers.Commits.CloseCommitMessagePanel()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionController) confirm() error {
|
||||||
|
return self.helpers.Commits.HandleCommitConfirm()
|
||||||
|
}
|
@ -1,33 +1,24 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommitMessageController struct {
|
type CommitMessageController struct {
|
||||||
baseController
|
baseController
|
||||||
*controllerCommon
|
*controllerCommon
|
||||||
|
|
||||||
getCommitMessage func() string
|
|
||||||
onCommitAttempt func(message string)
|
|
||||||
onCommitSuccess func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &CommitMessageController{}
|
var _ types.IController = &CommitMessageController{}
|
||||||
|
|
||||||
func NewCommitMessageController(
|
func NewCommitMessageController(
|
||||||
common *controllerCommon,
|
common *controllerCommon,
|
||||||
getCommitMessage func() string,
|
|
||||||
onCommitAttempt func(message string),
|
|
||||||
onCommitSuccess func(),
|
|
||||||
) *CommitMessageController {
|
) *CommitMessageController {
|
||||||
return &CommitMessageController{
|
return &CommitMessageController{
|
||||||
baseController: baseController{},
|
baseController: baseController{},
|
||||||
controllerCommon: common,
|
controllerCommon: common,
|
||||||
|
|
||||||
getCommitMessage: getCommitMessage,
|
|
||||||
onCommitAttempt: onCommitAttempt,
|
|
||||||
onCommitSuccess: onCommitSuccess,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +32,18 @@ func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
Handler: self.close,
|
Handler: self.close,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
||||||
|
Handler: self.handlePreviousCommit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||||
|
Handler: self.handleNextCommit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
|
Handler: self.switchToCommitDescription,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
@ -50,30 +53,63 @@ func (self *CommitMessageController) Context() types.Context {
|
|||||||
return self.context()
|
return self.context()
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is pointless in this context but I'm keeping it consistent
|
func (self *CommitMessageController) context() *context.CommitMessageContext {
|
||||||
// with other contexts so that when generics arrive it's easier to refactor
|
|
||||||
func (self *CommitMessageController) context() types.Context {
|
|
||||||
return self.contexts.CommitMessage
|
return self.contexts.CommitMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitMessageController) confirm() error {
|
func (self *CommitMessageController) handlePreviousCommit() error {
|
||||||
message := self.getCommitMessage()
|
return self.handleCommitIndexChange(1)
|
||||||
self.onCommitAttempt(message)
|
}
|
||||||
|
|
||||||
if message == "" {
|
func (self *CommitMessageController) handleNextCommit() error {
|
||||||
return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
|
if self.context().GetSelectedIndex() == context.NoCommitIndex {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return self.handleCommitIndexChange(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageController) switchToCommitDescription() error {
|
||||||
|
if err := self.c.PushContext(self.contexts.CommitDescription); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageController) handleCommitIndexChange(value int) error {
|
||||||
|
currentIndex := self.context().GetSelectedIndex()
|
||||||
|
newIndex := currentIndex + value
|
||||||
|
if newIndex == context.NoCommitIndex {
|
||||||
|
self.context().SetSelectedIndex(newIndex)
|
||||||
|
self.helpers.Commits.SetMessageAndDescriptionInView(self.context().GetHistoryMessage())
|
||||||
|
return nil
|
||||||
|
} else if currentIndex == context.NoCommitIndex {
|
||||||
|
self.context().SetHistoryMessage(self.helpers.Commits.JoinCommitMessageAndDescription())
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdObj := self.git.Commit.CommitCmdObj(message)
|
validCommit, err := self.setCommitMessageAtIndex(newIndex)
|
||||||
self.c.LogAction(self.c.Tr.Actions.Commit)
|
if validCommit {
|
||||||
|
self.context().SetSelectedIndex(newIndex)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_ = self.c.PopContext()
|
// returns true if the given index is for a valid commit
|
||||||
return self.helpers.GPG.WithGpgHandling(cmdObj, self.c.Tr.CommittingStatus, func() error {
|
func (self *CommitMessageController) setCommitMessageAtIndex(index int) (bool, error) {
|
||||||
self.onCommitSuccess()
|
commitMessage, err := self.git.Commit.GetCommitMessageFromHistory(index)
|
||||||
return nil
|
if err != nil {
|
||||||
})
|
if err == git_commands.ErrInvalidCommitIndex {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
|
||||||
|
}
|
||||||
|
self.helpers.Commits.UpdateCommitPanelView(commitMessage)
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageController) confirm() error {
|
||||||
|
return self.helpers.Commits.HandleCommitConfirm()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitMessageController) close() error {
|
func (self *CommitMessageController) close() error {
|
||||||
return self.c.PopContext()
|
return self.helpers.Commits.CloseCommitMessagePanel()
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,8 @@ type FilesController struct {
|
|||||||
baseController // nolint: unused
|
baseController // nolint: unused
|
||||||
*controllerCommon
|
*controllerCommon
|
||||||
|
|
||||||
enterSubmodule func(submodule *models.SubmoduleConfig) error
|
enterSubmodule func(submodule *models.SubmoduleConfig) error
|
||||||
setCommitMessage func(message string)
|
setCommitMessage func(message string)
|
||||||
getSavedCommitMessage func() string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IController = &FilesController{}
|
var _ types.IController = &FilesController{}
|
||||||
@ -26,13 +25,11 @@ func NewFilesController(
|
|||||||
common *controllerCommon,
|
common *controllerCommon,
|
||||||
enterSubmodule func(submodule *models.SubmoduleConfig) error,
|
enterSubmodule func(submodule *models.SubmoduleConfig) error,
|
||||||
setCommitMessage func(message string),
|
setCommitMessage func(message string),
|
||||||
getSavedCommitMessage func() string,
|
|
||||||
) *FilesController {
|
) *FilesController {
|
||||||
return &FilesController{
|
return &FilesController{
|
||||||
controllerCommon: common,
|
controllerCommon: common,
|
||||||
enterSubmodule: enterSubmodule,
|
enterSubmodule: enterSubmodule,
|
||||||
setCommitMessage: setCommitMessage,
|
setCommitMessage: setCommitMessage,
|
||||||
getSavedCommitMessage: getSavedCommitMessage,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
166
pkg/gui/controllers/helpers/commits_helper.go
Normal file
166
pkg/gui/controllers/helpers/commits_helper.go
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ICommitsHelper interface {
|
||||||
|
UpdateCommitPanelView(message string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommitsHelper struct {
|
||||||
|
c *types.HelperCommon
|
||||||
|
|
||||||
|
model *types.Model
|
||||||
|
contexts *context.ContextTree
|
||||||
|
getCommitSummary func() string
|
||||||
|
setCommitSummary func(string)
|
||||||
|
getCommitDescription func() string
|
||||||
|
setCommitDescription func(string)
|
||||||
|
renderCommitLength func()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ICommitsHelper = &CommitsHelper{}
|
||||||
|
|
||||||
|
func NewCommitsHelper(
|
||||||
|
c *types.HelperCommon,
|
||||||
|
model *types.Model,
|
||||||
|
contexts *context.ContextTree,
|
||||||
|
getCommitSummary func() string,
|
||||||
|
setCommitSummary func(string),
|
||||||
|
getCommitDescription func() string,
|
||||||
|
setCommitDescription func(string),
|
||||||
|
renderCommitLength func(),
|
||||||
|
) *CommitsHelper {
|
||||||
|
return &CommitsHelper{
|
||||||
|
c: c,
|
||||||
|
model: model,
|
||||||
|
contexts: contexts,
|
||||||
|
getCommitSummary: getCommitSummary,
|
||||||
|
setCommitSummary: setCommitSummary,
|
||||||
|
getCommitDescription: getCommitDescription,
|
||||||
|
setCommitDescription: setCommitDescription,
|
||||||
|
renderCommitLength: renderCommitLength,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.renderCommitLength()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitsHelper) JoinCommitMessageAndDescription() string {
|
||||||
|
if len(self.getCommitDescription()) == 0 {
|
||||||
|
return self.getCommitSummary()
|
||||||
|
}
|
||||||
|
return self.getCommitSummary() + "\n" + self.getCommitDescription()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitsHelper) UpdateCommitPanelView(message string) {
|
||||||
|
// first try the passed in message, if not fallback to context -> view in that order
|
||||||
|
if message != "" {
|
||||||
|
self.SetMessageAndDescriptionInView(message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message = self.contexts.CommitMessage.GetPreservedMessage()
|
||||||
|
if message != "" {
|
||||||
|
self.SetMessageAndDescriptionInView(message)
|
||||||
|
} else {
|
||||||
|
self.SetMessageAndDescriptionInView(self.getCommitSummary())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenCommitMessagePanelOpts struct {
|
||||||
|
CommitIndex int
|
||||||
|
Title string
|
||||||
|
PreserveMessage bool
|
||||||
|
OnConfirm func(string) error
|
||||||
|
InitialMessage string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOpts) error {
|
||||||
|
self.contexts.CommitMessage.SetPanelState(
|
||||||
|
opts.CommitIndex,
|
||||||
|
opts.Title,
|
||||||
|
opts.PreserveMessage,
|
||||||
|
opts.OnConfirm,
|
||||||
|
)
|
||||||
|
|
||||||
|
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.contexts.CommitMessage.GetPreserveMessage() {
|
||||||
|
self.contexts.CommitMessage.SetPreservedMessage("")
|
||||||
|
}
|
||||||
|
self.SetMessageAndDescriptionInView("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitsHelper) HandleCommitConfirm() error {
|
||||||
|
fullMessage := self.JoinCommitMessageAndDescription()
|
||||||
|
|
||||||
|
if fullMessage == "" {
|
||||||
|
return self.c.ErrorMsg(self.c.Tr.CommitWithoutMessageErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := self.contexts.CommitMessage.OnConfirm(fullMessage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitsHelper) CloseCommitMessagePanel() error {
|
||||||
|
if self.contexts.CommitMessage.GetPreserveMessage() {
|
||||||
|
message := self.JoinCommitMessageAndDescription()
|
||||||
|
|
||||||
|
self.contexts.CommitMessage.SetPreservedMessage(message)
|
||||||
|
} else {
|
||||||
|
self.SetMessageAndDescriptionInView("")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.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.contexts.CommitDescription,
|
||||||
|
self.contexts.CommitMessage,
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ type Helpers struct {
|
|||||||
GPG *GpgHelper
|
GPG *GpgHelper
|
||||||
Upstream *UpstreamHelper
|
Upstream *UpstreamHelper
|
||||||
AmendHelper *AmendHelper
|
AmendHelper *AmendHelper
|
||||||
|
Commits *CommitsHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStubHelpers() *Helpers {
|
func NewStubHelpers() *Helpers {
|
||||||
@ -33,5 +34,6 @@ func NewStubHelpers() *Helpers {
|
|||||||
GPG: &GpgHelper{},
|
GPG: &GpgHelper{},
|
||||||
Upstream: &UpstreamHelper{},
|
Upstream: &UpstreamHelper{},
|
||||||
AmendHelper: &AmendHelper{},
|
AmendHelper: &AmendHelper{},
|
||||||
|
Commits: &CommitsHelper{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,14 @@ type IWorkingTreeHelper interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WorkingTreeHelper struct {
|
type WorkingTreeHelper struct {
|
||||||
c *types.HelperCommon
|
c *types.HelperCommon
|
||||||
git *commands.GitCommand
|
git *commands.GitCommand
|
||||||
contexts *context.ContextTree
|
contexts *context.ContextTree
|
||||||
refHelper *RefsHelper
|
refHelper *RefsHelper
|
||||||
model *types.Model
|
model *types.Model
|
||||||
setCommitMessage func(message string)
|
setCommitMessage func(message string)
|
||||||
getSavedCommitMessage func() string
|
commitsHelper *CommitsHelper
|
||||||
|
gpgHelper *GpgHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorkingTreeHelper(
|
func NewWorkingTreeHelper(
|
||||||
@ -36,16 +37,18 @@ func NewWorkingTreeHelper(
|
|||||||
refHelper *RefsHelper,
|
refHelper *RefsHelper,
|
||||||
model *types.Model,
|
model *types.Model,
|
||||||
setCommitMessage func(message string),
|
setCommitMessage func(message string),
|
||||||
getSavedCommitMessage func() string,
|
commitsHelper *CommitsHelper,
|
||||||
|
gpgHelper *GpgHelper,
|
||||||
) *WorkingTreeHelper {
|
) *WorkingTreeHelper {
|
||||||
return &WorkingTreeHelper{
|
return &WorkingTreeHelper{
|
||||||
c: c,
|
c: c,
|
||||||
git: git,
|
git: git,
|
||||||
contexts: contexts,
|
contexts: contexts,
|
||||||
refHelper: refHelper,
|
refHelper: refHelper,
|
||||||
model: model,
|
model: model,
|
||||||
setCommitMessage: setCommitMessage,
|
setCommitMessage: setCommitMessage,
|
||||||
getSavedCommitMessage: getSavedCommitMessage,
|
commitsHelper: commitsHelper,
|
||||||
|
gpgHelper: gpgHelper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +97,7 @@ func (self *WorkingTreeHelper) OpenMergeTool() error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeHelper) HandleCommitPress() error {
|
func (self *WorkingTreeHelper) HandleCommitPressWithMessage(initialMessage string) error {
|
||||||
if err := self.prepareFilesForCommit(); err != nil {
|
if err := self.prepareFilesForCommit(); err != nil {
|
||||||
return self.c.Error(err)
|
return self.c.Error(err)
|
||||||
}
|
}
|
||||||
@ -107,28 +110,25 @@ func (self *WorkingTreeHelper) HandleCommitPress() error {
|
|||||||
return self.PromptToStageAllAndRetry(self.HandleCommitPress)
|
return self.PromptToStageAllAndRetry(self.HandleCommitPress)
|
||||||
}
|
}
|
||||||
|
|
||||||
savedCommitMessage := self.getSavedCommitMessage()
|
return self.commitsHelper.OpenCommitMessagePanel(
|
||||||
if len(savedCommitMessage) > 0 {
|
&OpenCommitMessagePanelOpts{
|
||||||
self.setCommitMessage(savedCommitMessage)
|
CommitIndex: context.NoCommitIndex,
|
||||||
} else {
|
InitialMessage: initialMessage,
|
||||||
commitPrefixConfig := self.commitPrefixConfigForRepo()
|
Title: self.c.Tr.CommitSummary,
|
||||||
if commitPrefixConfig != nil {
|
PreserveMessage: true,
|
||||||
prefixPattern := commitPrefixConfig.Pattern
|
OnConfirm: self.handleCommit,
|
||||||
prefixReplace := commitPrefixConfig.Replace
|
},
|
||||||
rgx, err := regexp.Compile(prefixPattern)
|
)
|
||||||
if err != nil {
|
}
|
||||||
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.LcCommitPrefixPatternError, err.Error()))
|
|
||||||
}
|
|
||||||
prefix := rgx.ReplaceAllString(self.refHelper.GetCheckedOutRef().Name, prefixReplace)
|
|
||||||
self.setCommitMessage(prefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := self.c.PushContext(self.contexts.CommitMessage); err != nil {
|
func (self *WorkingTreeHelper) handleCommit(message string) error {
|
||||||
return err
|
cmdObj := self.git.Commit.CommitCmdObj(message)
|
||||||
}
|
self.c.LogAction(self.c.Tr.Actions.Commit)
|
||||||
|
_ = self.commitsHelper.PopCommitMessageContexts()
|
||||||
return nil
|
return self.gpgHelper.WithGpgHandling(cmdObj, self.c.Tr.CommittingStatus, func() error {
|
||||||
|
self.commitsHelper.OnCommitSuccess()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleCommitEditorPress - handle when the user wants to commit changes via
|
// HandleCommitEditorPress - handle when the user wants to commit changes via
|
||||||
@ -154,9 +154,27 @@ func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
|
|||||||
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
|
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.setCommitMessage(skipHookPrefix)
|
return self.HandleCommitPressWithMessage(skipHookPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
return self.HandleCommitPress()
|
func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||||
|
message := self.contexts.CommitMessage.GetPreservedMessage()
|
||||||
|
|
||||||
|
if message != "" {
|
||||||
|
commitPrefixConfig := self.commitPrefixConfigForRepo()
|
||||||
|
if commitPrefixConfig != nil {
|
||||||
|
prefixPattern := commitPrefixConfig.Pattern
|
||||||
|
prefixReplace := commitPrefixConfig.Replace
|
||||||
|
rgx, err := regexp.Compile(prefixPattern)
|
||||||
|
if err != nil {
|
||||||
|
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.LcCommitPrefixPatternError, err.Error()))
|
||||||
|
}
|
||||||
|
prefix := rgx.ReplaceAllString(self.refHelper.GetCheckedOutRef().Name, prefixReplace)
|
||||||
|
message = prefix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.HandleCommitPressWithMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeHelper) PromptToStageAllAndRetry(retry func() error) error {
|
func (self *WorkingTreeHelper) PromptToStageAllAndRetry(retry func() error) error {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
@ -19,7 +20,6 @@ type (
|
|||||||
type LocalCommitsController struct {
|
type LocalCommitsController struct {
|
||||||
baseController
|
baseController
|
||||||
*controllerCommon
|
*controllerCommon
|
||||||
|
|
||||||
pullFiles PullFilesFn
|
pullFiles PullFilesFn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,24 +209,30 @@ func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
message, err := self.git.Commit.GetCommitMessage(commit.Sha)
|
commitMessage, err := self.git.Commit.GetCommitMessage(commit.Sha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return self.c.Error(err)
|
return self.c.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use the commit message panel here
|
return self.helpers.Commits.OpenCommitMessagePanel(
|
||||||
return self.c.Prompt(types.PromptOpts{
|
&helpers.OpenCommitMessagePanelOpts{
|
||||||
Title: self.c.Tr.LcRewordCommit,
|
CommitIndex: self.context().GetSelectedLineIdx(),
|
||||||
InitialContent: message,
|
InitialMessage: commitMessage,
|
||||||
HandleConfirm: func(response string) error {
|
Title: self.c.Tr.Actions.RewordCommit,
|
||||||
self.c.LogAction(self.c.Tr.Actions.RewordCommit)
|
PreserveMessage: false,
|
||||||
if err := self.git.Rebase.RewordCommit(self.model.Commits, self.context().GetSelectedLineIdx(), response); err != nil {
|
OnConfirm: self.handleReword,
|
||||||
return self.c.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *LocalCommitsController) handleReword(message string) error {
|
||||||
|
err := self.git.Rebase.RewordCommit(self.model.Commits, self.contexts.LocalCommits.GetSelectedLineIdx(), message)
|
||||||
|
if err != nil {
|
||||||
|
return self.c.Error(err)
|
||||||
|
}
|
||||||
|
self.helpers.Commits.OnCommitSuccess()
|
||||||
|
_ = self.helpers.Commits.PopCommitMessageContexts()
|
||||||
|
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) doRewordEditor() error {
|
func (self *LocalCommitsController) doRewordEditor() error {
|
||||||
|
@ -4,15 +4,9 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) handleEditorKeypress(textArea *gocui.TextArea, key gocui.Key, ch rune, mod gocui.Modifier, allowMultiline bool) bool {
|
func (gui *Gui) handleEditorKeypress(textArea *gocui.TextArea, key gocui.Key, ch rune, mod gocui.Modifier, allowMultiline bool) bool {
|
||||||
newlineKey, ok := keybindings.GetKey(gui.c.UserConfig.Keybinding.Universal.AppendNewline).(gocui.Key)
|
|
||||||
if !ok {
|
|
||||||
newlineKey = gocui.KeyAltEnter
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
|
case key == gocui.KeyBackspace || key == gocui.KeyBackspace2:
|
||||||
textArea.BackSpaceChar()
|
textArea.BackSpaceChar()
|
||||||
@ -30,7 +24,7 @@ func (gui *Gui) handleEditorKeypress(textArea *gocui.TextArea, key gocui.Key, ch
|
|||||||
textArea.MoveRightWord()
|
textArea.MoveRightWord()
|
||||||
case key == gocui.KeyArrowRight || key == gocui.KeyCtrlF:
|
case key == gocui.KeyArrowRight || key == gocui.KeyCtrlF:
|
||||||
textArea.MoveCursorRight()
|
textArea.MoveCursorRight()
|
||||||
case key == newlineKey:
|
case key == gocui.KeyEnter:
|
||||||
if allowMultiline {
|
if allowMultiline {
|
||||||
textArea.TypeRune('\n')
|
textArea.TypeRune('\n')
|
||||||
} else {
|
} else {
|
||||||
@ -66,22 +60,20 @@ func (gui *Gui) handleEditorKeypress(textArea *gocui.TextArea, key gocui.Key, ch
|
|||||||
// we've just copy+pasted the editor from gocui to here so that we can also re-
|
// we've just copy+pasted the editor from gocui to here so that we can also re-
|
||||||
// render the commit message length on each keypress
|
// render the commit message length on each keypress
|
||||||
func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
||||||
matched := gui.handleEditorKeypress(v.TextArea, key, ch, mod, true)
|
matched := gui.handleEditorKeypress(v.TextArea, key, ch, mod, false)
|
||||||
|
|
||||||
// This function is called again on refresh as part of the general resize popup call,
|
|
||||||
// but we need to call it here so that when we go to render the text area it's not
|
|
||||||
// considered out of bounds to add a newline, meaning we can avoid unnecessary scrolling.
|
|
||||||
err := gui.resizePopupPanel(v, v.TextArea.GetContent())
|
|
||||||
if err != nil {
|
|
||||||
gui.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
v.RenderTextArea()
|
v.RenderTextArea()
|
||||||
gui.RenderCommitLength()
|
gui.RenderCommitLength()
|
||||||
|
|
||||||
return matched
|
return matched
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) defaultEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
func (gui *Gui) commitDescriptionEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
||||||
|
matched := gui.handleEditorKeypress(v.TextArea, key, ch, mod, true)
|
||||||
|
v.RenderTextArea()
|
||||||
|
gui.RenderCommitLength()
|
||||||
|
return matched
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) promptEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.Modifier) bool {
|
||||||
matched := gui.handleEditorKeypress(v.TextArea, key, ch, mod, false)
|
matched := gui.handleEditorKeypress(v.TextArea, key, ch, mod, false)
|
||||||
|
|
||||||
v.RenderTextArea()
|
v.RenderTextArea()
|
||||||
|
@ -83,13 +83,13 @@ func (gui *Gui) filesRenderToMain() error {
|
|||||||
return gui.c.RenderToMainViews(refreshOpts)
|
return gui.c.RenderToMainViews(refreshOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
func (gui *Gui) getCommitMessageSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
||||||
return func(text string) {
|
return func(text string) {
|
||||||
// using a getView function so that we don't need to worry about when the view is created
|
// using a getView function so that we don't need to worry about when the view is created
|
||||||
view := getView()
|
view := getView()
|
||||||
view.ClearTextArea()
|
view.ClearTextArea()
|
||||||
view.TextArea.TypeString(text)
|
view.TextArea.TypeString(text)
|
||||||
_ = gui.resizePopupPanel(view, view.TextArea.GetContent())
|
gui.resizeCommitMessagePanels()
|
||||||
view.RenderTextArea()
|
view.RenderTextArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,10 +195,6 @@ type GuiRepoState struct {
|
|||||||
// back in sync with the repo state
|
// back in sync with the repo state
|
||||||
ViewsSetup bool
|
ViewsSetup bool
|
||||||
|
|
||||||
// we store a commit message in this field if we've escaped the commit message
|
|
||||||
// panel without committing or if our commit failed
|
|
||||||
savedCommitMessage string
|
|
||||||
|
|
||||||
ScreenMode WindowMaximisation
|
ScreenMode WindowMaximisation
|
||||||
|
|
||||||
CurrentPopupOpts *types.CreatePopupPanelOpts
|
CurrentPopupOpts *types.CreatePopupPanelOpts
|
||||||
|
@ -58,6 +58,10 @@ func (self *guiCommon) PopContext() error {
|
|||||||
return self.gui.popContext()
|
return self.gui.popContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *guiCommon) RemoveContexts(contexts []types.Context) error {
|
||||||
|
return self.gui.removeContexts(contexts)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *guiCommon) CurrentContext() types.Context {
|
func (self *guiCommon) CurrentContext() types.Context {
|
||||||
return self.gui.currentContext()
|
return self.gui.currentContext()
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ func (gui *Gui) Refresh(options types.RefreshOptions) error {
|
|||||||
types.REMOTES,
|
types.REMOTES,
|
||||||
types.STATUS,
|
types.STATUS,
|
||||||
types.BISECT_INFO,
|
types.BISECT_INFO,
|
||||||
|
types.STAGING,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
scopeSet = set.NewFromSlice(options.Scope)
|
scopeSet = set.NewFromSlice(options.Scope)
|
||||||
@ -563,6 +564,13 @@ func (gui *Gui) refreshStatus() {
|
|||||||
|
|
||||||
func (gui *Gui) refreshStagingPanel(focusOpts types.OnFocusOpts) error {
|
func (gui *Gui) refreshStagingPanel(focusOpts types.OnFocusOpts) error {
|
||||||
secondaryFocused := gui.secondaryStagingFocused()
|
secondaryFocused := gui.secondaryStagingFocused()
|
||||||
|
mainFocused := gui.mainStagingFocused()
|
||||||
|
|
||||||
|
// this method could be called when the staging panel is not being used,
|
||||||
|
// in which case we don't want to do anything.
|
||||||
|
if !mainFocused && !secondaryFocused {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
mainSelectedLineIdx := -1
|
mainSelectedLineIdx := -1
|
||||||
secondarySelectedLineIdx := -1
|
secondarySelectedLineIdx := -1
|
||||||
@ -647,6 +655,10 @@ func (gui *Gui) secondaryStagingFocused() bool {
|
|||||||
return gui.currentStaticContext().GetKey() == gui.State.Contexts.StagingSecondary.GetKey()
|
return gui.currentStaticContext().GetKey() == gui.State.Contexts.StagingSecondary.GetKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) mainStagingFocused() bool {
|
||||||
|
return gui.currentStaticContext().GetKey() == gui.State.Contexts.Staging.GetKey()
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error {
|
func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error {
|
||||||
selectedLineIdx := -1
|
selectedLineIdx := -1
|
||||||
if opts.ClickedWindowName == "main" {
|
if opts.ClickedWindowName == "main" {
|
||||||
|
@ -42,6 +42,10 @@ type IGuiCommon interface {
|
|||||||
|
|
||||||
PushContext(context Context, opts ...OnFocusOpts) error
|
PushContext(context Context, opts ...OnFocusOpts) error
|
||||||
PopContext() error
|
PopContext() error
|
||||||
|
// Removes all given contexts from the stack. If a given context is not in the stack, it is ignored.
|
||||||
|
// This is for when you have a group of contexts that are bundled together e.g. with the commit message panel.
|
||||||
|
// If you want to remove a single context, you should probably use PopContext instead.
|
||||||
|
RemoveContexts([]Context) error
|
||||||
CurrentContext() Context
|
CurrentContext() Context
|
||||||
CurrentStaticContext() Context
|
CurrentStaticContext() Context
|
||||||
IsCurrentContext(Context) bool
|
IsCurrentContext(Context) bool
|
||||||
|
@ -78,28 +78,24 @@ func (gui *Gui) resizeCurrentPopupPanel() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == gui.Views.Menu {
|
c := gui.c.CurrentContext()
|
||||||
|
|
||||||
|
if c == gui.State.Contexts.Menu {
|
||||||
gui.resizeMenu()
|
gui.resizeMenu()
|
||||||
} else if v == gui.Views.Confirmation || v == gui.Views.Suggestions {
|
} else if c == gui.State.Contexts.Confirmation || c == gui.State.Contexts.Suggestions {
|
||||||
gui.resizeConfirmationPanel()
|
gui.resizeConfirmationPanel()
|
||||||
} else if gui.isPopupPanel(v.Name()) {
|
} else if c == gui.State.Contexts.CommitMessage || c == gui.State.Contexts.CommitDescription {
|
||||||
return gui.resizePopupPanel(v, v.Buffer())
|
gui.resizeCommitMessagePanels()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) resizePopupPanel(v *gocui.View, content string) error {
|
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(v.Wrap, content)
|
|
||||||
_, err := gui.g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) resizeMenu() {
|
func (gui *Gui) resizeMenu() {
|
||||||
itemCount := gui.State.Contexts.Menu.GetList().Len()
|
itemCount := gui.State.Contexts.Menu.GetList().Len()
|
||||||
offset := 3
|
offset := 3
|
||||||
panelWidth := gui.getConfirmationPanelWidth()
|
panelWidth := gui.getConfirmationPanelWidth()
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensionsForContentHeight(panelWidth, itemCount+offset)
|
x0, y0, x1, y1 := gui.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset)
|
||||||
menuBottom := y1 - offset
|
menuBottom := y1 - offset
|
||||||
_, _ = gui.g.SetView(gui.Views.Menu.Name(), x0, y0, x1, menuBottom, 0)
|
_, _ = gui.g.SetView(gui.Views.Menu.Name(), x0, y0, x1, menuBottom, 0)
|
||||||
|
|
||||||
@ -121,7 +117,7 @@ func (gui *Gui) resizeConfirmationPanel() {
|
|||||||
wrap = false
|
wrap = false
|
||||||
}
|
}
|
||||||
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
|
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
x0, y0, x1, y1 := gui.getPopupPanelDimensionsAux(panelWidth, panelHeight)
|
||||||
confirmationViewBottom := y1 - suggestionsViewHeight
|
confirmationViewBottom := y1 - suggestionsViewHeight
|
||||||
_, _ = gui.g.SetView(gui.Views.Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
|
_, _ = gui.g.SetView(gui.Views.Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
|
||||||
|
|
||||||
@ -129,6 +125,21 @@ func (gui *Gui) resizeConfirmationPanel() {
|
|||||||
_, _ = gui.g.SetView(gui.Views.Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
|
_, _ = gui.g.SetView(gui.Views.Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) resizeCommitMessagePanels() {
|
||||||
|
panelWidth := gui.getConfirmationPanelWidth()
|
||||||
|
content := gui.Views.CommitDescription.TextArea.GetContent()
|
||||||
|
summaryViewHeight := 3
|
||||||
|
panelHeight := gui.getMessageHeight(false, content, panelWidth)
|
||||||
|
minHeight := 7
|
||||||
|
if panelHeight < minHeight {
|
||||||
|
panelHeight = minHeight
|
||||||
|
}
|
||||||
|
x0, y0, x1, y1 := gui.getPopupPanelDimensionsAux(panelWidth, panelHeight)
|
||||||
|
|
||||||
|
_, _ = gui.g.SetView(gui.Views.CommitMessage.Name(), x0, y0, x1, y0+summaryViewHeight-1, 0)
|
||||||
|
_, _ = gui.g.SetView(gui.Views.CommitDescription.Name(), x0, y0+summaryViewHeight, x1, y1+summaryViewHeight, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) globalOptionsMap() map[string]string {
|
func (gui *Gui) globalOptionsMap() map[string]string {
|
||||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
keybindingConfig := gui.c.UserConfig.Keybinding
|
||||||
|
|
||||||
|
@ -26,20 +26,21 @@ type Views struct {
|
|||||||
PatchBuildingSecondary *gocui.View
|
PatchBuildingSecondary *gocui.View
|
||||||
MergeConflicts *gocui.View
|
MergeConflicts *gocui.View
|
||||||
|
|
||||||
Options *gocui.View
|
Options *gocui.View
|
||||||
Confirmation *gocui.View
|
Confirmation *gocui.View
|
||||||
Menu *gocui.View
|
Menu *gocui.View
|
||||||
CommitMessage *gocui.View
|
CommitMessage *gocui.View
|
||||||
CommitFiles *gocui.View
|
CommitDescription *gocui.View
|
||||||
SubCommits *gocui.View
|
CommitFiles *gocui.View
|
||||||
Information *gocui.View
|
SubCommits *gocui.View
|
||||||
AppStatus *gocui.View
|
Information *gocui.View
|
||||||
Search *gocui.View
|
AppStatus *gocui.View
|
||||||
SearchPrefix *gocui.View
|
Search *gocui.View
|
||||||
Limit *gocui.View
|
SearchPrefix *gocui.View
|
||||||
Suggestions *gocui.View
|
Limit *gocui.View
|
||||||
Tooltip *gocui.View
|
Suggestions *gocui.View
|
||||||
Extras *gocui.View
|
Tooltip *gocui.View
|
||||||
|
Extras *gocui.View
|
||||||
|
|
||||||
// for playing the easter egg snake game
|
// for playing the easter egg snake game
|
||||||
Snake *gocui.View
|
Snake *gocui.View
|
||||||
@ -94,6 +95,7 @@ func (gui *Gui) orderedViewNameMappings() []viewNameMapping {
|
|||||||
|
|
||||||
// popups.
|
// popups.
|
||||||
{viewPtr: &gui.Views.CommitMessage, name: "commitMessage"},
|
{viewPtr: &gui.Views.CommitMessage, name: "commitMessage"},
|
||||||
|
{viewPtr: &gui.Views.CommitDescription, name: "commitDescription"},
|
||||||
{viewPtr: &gui.Views.Menu, name: "menu"},
|
{viewPtr: &gui.Views.Menu, name: "menu"},
|
||||||
{viewPtr: &gui.Views.Suggestions, name: "suggestions"},
|
{viewPtr: &gui.Views.Suggestions, name: "suggestions"},
|
||||||
{viewPtr: &gui.Views.Confirmation, name: "confirmation"},
|
{viewPtr: &gui.Views.Confirmation, name: "confirmation"},
|
||||||
@ -199,10 +201,17 @@ func (gui *Gui) createAllViews() error {
|
|||||||
gui.Views.AppStatus.Frame = false
|
gui.Views.AppStatus.Frame = false
|
||||||
|
|
||||||
gui.Views.CommitMessage.Visible = false
|
gui.Views.CommitMessage.Visible = false
|
||||||
gui.Views.CommitMessage.Title = gui.c.Tr.CommitMessage
|
gui.Views.CommitMessage.Title = gui.c.Tr.CommitSummary
|
||||||
gui.Views.CommitMessage.Editable = true
|
gui.Views.CommitMessage.Editable = true
|
||||||
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
||||||
|
|
||||||
|
gui.Views.CommitDescription.Visible = false
|
||||||
|
gui.Views.CommitDescription.Title = gui.c.Tr.CommitDescriptionTitle
|
||||||
|
gui.Views.CommitDescription.Subtitle = gui.Tr.CommitDescriptionSubTitle
|
||||||
|
gui.Views.CommitDescription.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
gui.Views.CommitDescription.Editable = true
|
||||||
|
gui.Views.CommitDescription.Editor = gocui.EditorFunc(gui.commitDescriptionEditor)
|
||||||
|
|
||||||
gui.Views.Confirmation.Visible = false
|
gui.Views.Confirmation.Visible = false
|
||||||
|
|
||||||
gui.Views.Suggestions.Visible = false
|
gui.Views.Suggestions.Visible = false
|
||||||
|
@ -47,7 +47,7 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
StagingTitle: "正在暂存",
|
StagingTitle: "正在暂存",
|
||||||
MergingTitle: "正在合并",
|
MergingTitle: "正在合并",
|
||||||
NormalTitle: "正常",
|
NormalTitle: "正常",
|
||||||
CommitMessage: "提交信息",
|
CommitSummary: "提交信息",
|
||||||
CredentialsUsername: "用户名",
|
CredentialsUsername: "用户名",
|
||||||
CredentialsPassword: "密码",
|
CredentialsPassword: "密码",
|
||||||
CredentialsPassphrase: "输入 SSH 密钥的密码",
|
CredentialsPassphrase: "输入 SSH 密钥的密码",
|
||||||
@ -94,7 +94,7 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "新分支",
|
LcNewBranch: "新分支",
|
||||||
LcDeleteBranch: "删除分支",
|
LcDeleteBranch: "删除分支",
|
||||||
NoBranchesThisRepo: "此仓库中没有分支",
|
NoBranchesThisRepo: "此仓库中没有分支",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}:关闭,{{.keyBindNewLine}}:新行,{{.keyBindConfirm}}:确认",
|
CommitMessageConfirm: "{{.keyBindClose}}:关闭,{{.keyBindConfirm}}:确认",
|
||||||
CommitWithoutMessageErr: "您必须编写提交消息才能进行提交",
|
CommitWithoutMessageErr: "您必须编写提交消息才能进行提交",
|
||||||
CloseConfirm: "{{.keyBindClose}}:关闭,{{.keyBindConfirm}}:确认",
|
CloseConfirm: "{{.keyBindClose}}:关闭,{{.keyBindConfirm}}:确认",
|
||||||
LcClose: "关闭",
|
LcClose: "关闭",
|
||||||
|
@ -13,7 +13,7 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
MainTitle: "Hoofd",
|
MainTitle: "Hoofd",
|
||||||
StagingTitle: "Staging",
|
StagingTitle: "Staging",
|
||||||
NormalTitle: "Normaal",
|
NormalTitle: "Normaal",
|
||||||
CommitMessage: "Commitbericht",
|
CommitSummary: "Commitbericht",
|
||||||
CredentialsUsername: "Gebruikersnaam",
|
CredentialsUsername: "Gebruikersnaam",
|
||||||
CredentialsPassword: "Wachtwoord",
|
CredentialsPassword: "Wachtwoord",
|
||||||
CredentialsPassphrase: "Voer een wachtwoordzin in voor de SSH-sleutel",
|
CredentialsPassphrase: "Voer een wachtwoordzin in voor de SSH-sleutel",
|
||||||
@ -60,7 +60,7 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "nieuwe branch",
|
LcNewBranch: "nieuwe branch",
|
||||||
LcDeleteBranch: "verwijder branch",
|
LcDeleteBranch: "verwijder branch",
|
||||||
NoBranchesThisRepo: "Geen branches voor deze repo",
|
NoBranchesThisRepo: "Geen branches voor deze repo",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindNewLine}}: Nieuwe lijn, {{.keyBindConfirm}}: Bevestig",
|
CommitMessageConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
|
||||||
CommitWithoutMessageErr: "Je kan geen commit maken zonder commit bericht",
|
CommitWithoutMessageErr: "Je kan geen commit maken zonder commit bericht",
|
||||||
CloseConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
|
CloseConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
|
||||||
LcClose: "sluiten",
|
LcClose: "sluiten",
|
||||||
|
@ -27,7 +27,7 @@ type TranslationSet struct {
|
|||||||
MergeConfirmTitle string
|
MergeConfirmTitle string
|
||||||
NormalTitle string
|
NormalTitle string
|
||||||
LogTitle string
|
LogTitle string
|
||||||
CommitMessage string
|
CommitSummary string
|
||||||
CredentialsUsername string
|
CredentialsUsername string
|
||||||
CredentialsPassword string
|
CredentialsPassword string
|
||||||
CredentialsPassphrase string
|
CredentialsPassphrase string
|
||||||
@ -197,6 +197,8 @@ type TranslationSet struct {
|
|||||||
MergeOptionsTitle string
|
MergeOptionsTitle string
|
||||||
RebaseOptionsTitle string
|
RebaseOptionsTitle string
|
||||||
CommitMessageTitle string
|
CommitMessageTitle string
|
||||||
|
CommitDescriptionTitle string
|
||||||
|
CommitDescriptionSubTitle string
|
||||||
LocalBranchesTitle string
|
LocalBranchesTitle string
|
||||||
SearchTitle string
|
SearchTitle string
|
||||||
TagsTitle string
|
TagsTitle string
|
||||||
@ -698,7 +700,7 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
MergingTitle: "Main Panel (Merging)",
|
MergingTitle: "Main Panel (Merging)",
|
||||||
NormalTitle: "Main Panel (Normal)",
|
NormalTitle: "Main Panel (Normal)",
|
||||||
LogTitle: "Log",
|
LogTitle: "Log",
|
||||||
CommitMessage: "Commit message",
|
CommitSummary: "Commit summary",
|
||||||
CredentialsUsername: "Username",
|
CredentialsUsername: "Username",
|
||||||
CredentialsPassword: "Password",
|
CredentialsPassword: "Password",
|
||||||
CredentialsPassphrase: "Enter passphrase for SSH key",
|
CredentialsPassphrase: "Enter passphrase for SSH key",
|
||||||
@ -750,7 +752,7 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "new branch",
|
LcNewBranch: "new branch",
|
||||||
LcDeleteBranch: "delete branch",
|
LcDeleteBranch: "delete branch",
|
||||||
NoBranchesThisRepo: "No branches for this repo",
|
NoBranchesThisRepo: "No branches for this repo",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: close, {{.keyBindNewLine}}: new line, {{.keyBindConfirm}}: confirm",
|
CommitMessageConfirm: "{{.keyBindClose}}: close, {{.keyBindConfirm}}: confirm",
|
||||||
CommitWithoutMessageErr: "You cannot commit without a commit message",
|
CommitWithoutMessageErr: "You cannot commit without a commit message",
|
||||||
CloseConfirm: "{{.keyBindClose}}: close/cancel, {{.keyBindConfirm}}: confirm",
|
CloseConfirm: "{{.keyBindClose}}: close/cancel, {{.keyBindConfirm}}: confirm",
|
||||||
LcClose: "close",
|
LcClose: "close",
|
||||||
@ -866,7 +868,9 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
RecentRepos: "recent repositories",
|
RecentRepos: "recent repositories",
|
||||||
MergeOptionsTitle: "Merge Options",
|
MergeOptionsTitle: "Merge Options",
|
||||||
RebaseOptionsTitle: "Rebase Options",
|
RebaseOptionsTitle: "Rebase Options",
|
||||||
CommitMessageTitle: "Commit Message",
|
CommitMessageTitle: "Commit Summary",
|
||||||
|
CommitDescriptionTitle: "Commit description",
|
||||||
|
CommitDescriptionSubTitle: "Press tab to toggle focus",
|
||||||
LocalBranchesTitle: "Local Branches",
|
LocalBranchesTitle: "Local Branches",
|
||||||
SearchTitle: "Search",
|
SearchTitle: "Search",
|
||||||
TagsTitle: "Tags",
|
TagsTitle: "Tags",
|
||||||
|
@ -34,7 +34,7 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
MergingTitle: "メインパネル (Merging)",
|
MergingTitle: "メインパネル (Merging)",
|
||||||
NormalTitle: "メインパネル (Normal)",
|
NormalTitle: "メインパネル (Normal)",
|
||||||
LogTitle: "ログ",
|
LogTitle: "ログ",
|
||||||
CommitMessage: "コミットメッセージ",
|
CommitSummary: "コミットメッセージ",
|
||||||
CredentialsUsername: "ユーザ名",
|
CredentialsUsername: "ユーザ名",
|
||||||
CredentialsPassword: "パスワード",
|
CredentialsPassword: "パスワード",
|
||||||
CredentialsPassphrase: "SSH鍵のパスフレーズを入力",
|
CredentialsPassphrase: "SSH鍵のパスフレーズを入力",
|
||||||
@ -85,7 +85,7 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "新しいブランチを作成",
|
LcNewBranch: "新しいブランチを作成",
|
||||||
LcDeleteBranch: "ブランチを削除",
|
LcDeleteBranch: "ブランチを削除",
|
||||||
NoBranchesThisRepo: "リポジトリにブランチが存在しません",
|
NoBranchesThisRepo: "リポジトリにブランチが存在しません",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: 閉じる, {{.keyBindNewLine}}: 改行, {{.keyBindConfirm}}: 確定",
|
CommitMessageConfirm: "{{.keyBindClose}}: 閉じる, {{.keyBindConfirm}}: 確定",
|
||||||
CommitWithoutMessageErr: "コミットメッセージを入力してください",
|
CommitWithoutMessageErr: "コミットメッセージを入力してください",
|
||||||
CloseConfirm: "{{.keyBindClose}}: 閉じる/キャンセル, {{.keyBindConfirm}}: 確認",
|
CloseConfirm: "{{.keyBindClose}}: 閉じる/キャンセル, {{.keyBindConfirm}}: 確認",
|
||||||
LcClose: "閉じる",
|
LcClose: "閉じる",
|
||||||
|
@ -33,7 +33,7 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
MergingTitle: "메인 패널 (Merging)",
|
MergingTitle: "메인 패널 (Merging)",
|
||||||
NormalTitle: "메인 패널 (Normal)",
|
NormalTitle: "메인 패널 (Normal)",
|
||||||
LogTitle: "로그",
|
LogTitle: "로그",
|
||||||
CommitMessage: "커밋 메시지",
|
CommitSummary: "커밋 메시지",
|
||||||
CredentialsUsername: "사용자 이름",
|
CredentialsUsername: "사용자 이름",
|
||||||
CredentialsPassword: "패스워드",
|
CredentialsPassword: "패스워드",
|
||||||
CredentialsPassphrase: "SSH키의 passphrase 입력",
|
CredentialsPassphrase: "SSH키의 passphrase 입력",
|
||||||
@ -84,7 +84,7 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "새 브랜치 생성",
|
LcNewBranch: "새 브랜치 생성",
|
||||||
LcDeleteBranch: "브랜치 삭제",
|
LcDeleteBranch: "브랜치 삭제",
|
||||||
NoBranchesThisRepo: "저장소에 브랜치가 존재하지 않습니다.",
|
NoBranchesThisRepo: "저장소에 브랜치가 존재하지 않습니다.",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: 닫기, {{.keyBindNewLine}}: 개행, {{.keyBindConfirm}}: 확인",
|
CommitMessageConfirm: "{{.keyBindClose}}: 닫기, {{.keyBindConfirm}}: 확인",
|
||||||
CommitWithoutMessageErr: "커밋 메시지를 입력하세요.",
|
CommitWithoutMessageErr: "커밋 메시지를 입력하세요.",
|
||||||
CloseConfirm: "{{.keyBindClose}}: 닫기/취소, {{.keyBindConfirm}}: 확인",
|
CloseConfirm: "{{.keyBindClose}}: 닫기/취소, {{.keyBindConfirm}}: 확인",
|
||||||
LcClose: "닫기",
|
LcClose: "닫기",
|
||||||
|
@ -10,7 +10,7 @@ func polishTranslationSet() TranslationSet {
|
|||||||
StashTitle: "Schowek",
|
StashTitle: "Schowek",
|
||||||
UnstagedChanges: "Zmiany poza poczekalnią",
|
UnstagedChanges: "Zmiany poza poczekalnią",
|
||||||
StagedChanges: "Zmiany w poczekalni",
|
StagedChanges: "Zmiany w poczekalni",
|
||||||
CommitMessage: "Komunikat commita",
|
CommitSummary: "Komunikat commita",
|
||||||
CredentialsUsername: "Użytkownik",
|
CredentialsUsername: "Użytkownik",
|
||||||
CredentialsPassword: "Hasło",
|
CredentialsPassword: "Hasło",
|
||||||
CredentialsPassphrase: "Fraza",
|
CredentialsPassphrase: "Fraza",
|
||||||
@ -55,7 +55,7 @@ func polishTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "nowa gałąź",
|
LcNewBranch: "nowa gałąź",
|
||||||
LcDeleteBranch: "usuń gałąź",
|
LcDeleteBranch: "usuń gałąź",
|
||||||
NoBranchesThisRepo: "Brak gałęzi dla tego repozytorium",
|
NoBranchesThisRepo: "Brak gałęzi dla tego repozytorium",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindNewLine}}: nowa linia, {{.keyBindConfirm}}: potwierdź",
|
CommitMessageConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź",
|
||||||
CommitWithoutMessageErr: "Nie możesz commitować bez komunikatu",
|
CommitWithoutMessageErr: "Nie możesz commitować bez komunikatu",
|
||||||
CloseConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź",
|
CloseConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź",
|
||||||
LcClose: "zamknij",
|
LcClose: "zamknij",
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package components
|
||||||
|
|
||||||
|
type CommitDescriptionPanelDriver struct {
|
||||||
|
t *TestDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionPanelDriver) getViewDriver() *ViewDriver {
|
||||||
|
return self.t.Views().CommitDescription()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionPanelDriver) Type(value string) *CommitDescriptionPanelDriver {
|
||||||
|
self.t.typeContent(value)
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionPanelDriver) SwitchToSummary() *CommitMessagePanelDriver {
|
||||||
|
self.getViewDriver().PressTab()
|
||||||
|
return &CommitMessagePanelDriver{t: self.t}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitDescriptionPanelDriver) AddNewline() *CommitDescriptionPanelDriver {
|
||||||
|
self.t.press(self.t.keys.Universal.Confirm)
|
||||||
|
return self
|
||||||
|
}
|
@ -10,19 +10,36 @@ func (self *CommitMessagePanelDriver) getViewDriver() *ViewDriver {
|
|||||||
|
|
||||||
// asserts on the text initially present in the prompt
|
// asserts on the text initially present in the prompt
|
||||||
func (self *CommitMessagePanelDriver) InitialText(expected *Matcher) *CommitMessagePanelDriver {
|
func (self *CommitMessagePanelDriver) InitialText(expected *Matcher) *CommitMessagePanelDriver {
|
||||||
|
return self.Content(expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// asserts on the current context in the prompt
|
||||||
|
func (self *CommitMessagePanelDriver) Content(expected *Matcher) *CommitMessagePanelDriver {
|
||||||
self.getViewDriver().Content(expected)
|
self.getViewDriver().Content(expected)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// asserts that the confirmation view has the expected title
|
||||||
|
func (self *CommitMessagePanelDriver) Title(expected *Matcher) *CommitMessagePanelDriver {
|
||||||
|
self.getViewDriver().Title(expected)
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitMessagePanelDriver) Type(value string) *CommitMessagePanelDriver {
|
func (self *CommitMessagePanelDriver) Type(value string) *CommitMessagePanelDriver {
|
||||||
self.t.typeContent(value)
|
self.t.typeContent(value)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessagePanelDriver) SwitchToDescription() *CommitDescriptionPanelDriver {
|
||||||
|
self.getViewDriver().PressTab()
|
||||||
|
return &CommitDescriptionPanelDriver{t: self.t}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitMessagePanelDriver) AddNewline() *CommitMessagePanelDriver {
|
func (self *CommitMessagePanelDriver) AddNewline() *CommitMessagePanelDriver {
|
||||||
self.t.press(self.t.keys.Universal.AppendNewline)
|
self.t.press(self.t.keys.Universal.Confirm)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
@ -49,6 +66,20 @@ func (self *CommitMessagePanelDriver) Confirm() {
|
|||||||
self.getViewDriver().PressEnter()
|
self.getViewDriver().PressEnter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessagePanelDriver) Close() {
|
||||||
|
self.getViewDriver().PressEscape()
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitMessagePanelDriver) Cancel() {
|
func (self *CommitMessagePanelDriver) Cancel() {
|
||||||
self.getViewDriver().PressEscape()
|
self.getViewDriver().PressEscape()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessagePanelDriver) SelectPreviousMessage() *CommitMessagePanelDriver {
|
||||||
|
self.getViewDriver().SelectPreviousItem()
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessagePanelDriver) SelectNextMessage() *CommitMessagePanelDriver {
|
||||||
|
self.getViewDriver().SelectNextItem()
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
@ -62,9 +62,22 @@ func (self *Popup) CommitMessagePanel() *CommitMessagePanelDriver {
|
|||||||
return &CommitMessagePanelDriver{t: self.t}
|
return &CommitMessagePanelDriver{t: self.t}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Popup) CommitDescriptionPanel() *CommitMessagePanelDriver {
|
||||||
|
self.inCommitDescriptionPanel()
|
||||||
|
|
||||||
|
return &CommitMessagePanelDriver{t: self.t}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Popup) inCommitMessagePanel() {
|
func (self *Popup) inCommitMessagePanel() {
|
||||||
self.t.assertWithRetries(func() (bool, string) {
|
self.t.assertWithRetries(func() (bool, string) {
|
||||||
currentView := self.t.gui.CurrentContext().GetView()
|
currentView := self.t.gui.CurrentContext().GetView()
|
||||||
return currentView.Name() == "commitMessage", "Expected commit message panel to be focused"
|
return currentView.Name() == "commitMessage", "Expected commit message panel to be focused"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Popup) inCommitDescriptionPanel() {
|
||||||
|
self.t.assertWithRetries(func() (bool, string) {
|
||||||
|
currentView := self.t.gui.CurrentContext().GetView()
|
||||||
|
return currentView.Name() == "commitDescription", "Expected commit description panel to be focused"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -361,6 +361,11 @@ func (self *ViewDriver) PressEnter() *ViewDriver {
|
|||||||
return self.Press(self.t.keys.Universal.Confirm)
|
return self.Press(self.t.keys.Universal.Confirm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// i.e. pressing tab
|
||||||
|
func (self *ViewDriver) PressTab() *ViewDriver {
|
||||||
|
return self.Press(self.t.keys.Universal.TogglePanel)
|
||||||
|
}
|
||||||
|
|
||||||
// i.e. pressing escape
|
// i.e. pressing escape
|
||||||
func (self *ViewDriver) PressEscape() *ViewDriver {
|
func (self *ViewDriver) PressEscape() *ViewDriver {
|
||||||
return self.Press(self.t.keys.Universal.Return)
|
return self.Press(self.t.keys.Universal.Return)
|
||||||
|
@ -207,6 +207,10 @@ func (self *Views) CommitMessage() *ViewDriver {
|
|||||||
return self.regularView("commitMessage")
|
return self.regularView("commitMessage")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Views) CommitDescription() *ViewDriver {
|
||||||
|
return self.regularView("commitDescription")
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Views) Suggestions() *ViewDriver {
|
func (self *Views) Suggestions() *ViewDriver {
|
||||||
return self.regularView("suggestions")
|
return self.regularView("suggestions")
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,20 @@ var CommitMultiline = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
PressPrimaryAction().
|
PressPrimaryAction().
|
||||||
Press(keys.Files.CommitChanges)
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
t.ExpectPopup().CommitMessagePanel().Type("first line").AddNewline().AddNewline().Type("third line").Confirm()
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
Type("first line").
|
||||||
|
SwitchToDescription().
|
||||||
|
AddNewline().
|
||||||
|
AddNewline().
|
||||||
|
Type("fourth line").
|
||||||
|
SwitchToSummary().
|
||||||
|
Confirm()
|
||||||
t.Views().Commits().
|
t.Views().Commits().
|
||||||
Lines(
|
Lines(
|
||||||
Contains("first line"),
|
Contains("first line"),
|
||||||
)
|
)
|
||||||
|
|
||||||
t.Views().Commits().Focus()
|
t.Views().Commits().Focus()
|
||||||
t.Views().Main().Content(MatchesRegexp("first line\n\\s*\n\\s*third line"))
|
t.Views().Main().Content(MatchesRegexp("first line\n\\s*\n\\s*fourth line"))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
53
pkg/integration/tests/commit/history.go
Normal file
53
pkg/integration/tests/commit/history.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package commit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var History = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Cycling through commit message history in the commit message panel",
|
||||||
|
ExtraCmdArgs: "",
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.EmptyCommit("initial commit")
|
||||||
|
shell.EmptyCommit("commit 2")
|
||||||
|
shell.EmptyCommit("commit 3")
|
||||||
|
|
||||||
|
shell.CreateFile("myfile", "myfile content")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Files().
|
||||||
|
IsFocused().
|
||||||
|
PressPrimaryAction(). // stage file
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
InitialText(Equals("")).
|
||||||
|
Type("my commit message").
|
||||||
|
SelectPreviousMessage().
|
||||||
|
Content(Equals("commit 3")).
|
||||||
|
SelectPreviousMessage().
|
||||||
|
Content(Equals("commit 2")).
|
||||||
|
SelectPreviousMessage().
|
||||||
|
Content(Equals("initial commit")).
|
||||||
|
SelectPreviousMessage().
|
||||||
|
Content(Equals("initial commit")). // we hit the end
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("commit 2")).
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("commit 3")).
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("my commit message")).
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("my commit message")). // we hit the beginning
|
||||||
|
Type(" with extra added").
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
TopLines(
|
||||||
|
Contains("my commit message with extra added").IsSelected(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
59
pkg/integration/tests/commit/history_complex.go
Normal file
59
pkg/integration/tests/commit/history_complex.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package commit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var HistoryComplex = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "More complex flow for cycling commit message history",
|
||||||
|
ExtraCmdArgs: "",
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.EmptyCommit("initial commit")
|
||||||
|
shell.EmptyCommit("commit 2")
|
||||||
|
shell.EmptyCommit("commit 3")
|
||||||
|
|
||||||
|
shell.CreateFileAndAdd("myfile", "myfile content")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
// We're going to start a new commit message,
|
||||||
|
// then leave and try to reword a commit, then
|
||||||
|
// come back to original message and confirm we haven't lost our message.
|
||||||
|
// This shows that we're storing the preserved message for a new commit separately
|
||||||
|
// to the message when cycling history.
|
||||||
|
|
||||||
|
t.Views().Files().
|
||||||
|
IsFocused().
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
InitialText(Equals("")).
|
||||||
|
Type("my commit message").
|
||||||
|
Cancel()
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
SelectedLine(Contains("commit 3")).
|
||||||
|
Press(keys.Commits.RenameCommit)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
InitialText(Equals("commit 3")).
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("")).
|
||||||
|
Type("reworded message").
|
||||||
|
SelectPreviousMessage().
|
||||||
|
Content(Equals("commit 3")).
|
||||||
|
SelectNextMessage().
|
||||||
|
Content(Equals("reworded message")).
|
||||||
|
Cancel()
|
||||||
|
|
||||||
|
t.Views().Files().
|
||||||
|
Focus().
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
InitialText(Equals("my commit message"))
|
||||||
|
},
|
||||||
|
})
|
66
pkg/integration/tests/commit/reword.go
Normal file
66
pkg/integration/tests/commit/reword.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package commit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Reword = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Staging a couple files and committing",
|
||||||
|
ExtraCmdArgs: "",
|
||||||
|
Skip: false,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.CreateFile("myfile", "myfile content")
|
||||||
|
shell.CreateFile("myfile2", "myfile2 content")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.Views().Commits().
|
||||||
|
IsEmpty()
|
||||||
|
|
||||||
|
t.Views().Files().
|
||||||
|
IsFocused().
|
||||||
|
PressPrimaryAction().
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
commitMessage := "my commit message"
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().Type(commitMessage).Confirm()
|
||||||
|
t.Views().Commits().
|
||||||
|
Lines(
|
||||||
|
Contains(commitMessage),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Views().Files().
|
||||||
|
IsFocused().
|
||||||
|
PressPrimaryAction().
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
wipCommitMessage := "my commit message wip"
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().Type(wipCommitMessage).Close()
|
||||||
|
|
||||||
|
t.Views().Commits().Focus().
|
||||||
|
Lines(
|
||||||
|
Contains(commitMessage),
|
||||||
|
).Press(keys.Commits.RenameCommit)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
|
SwitchToDescription().
|
||||||
|
Type("some description").
|
||||||
|
SwitchToSummary().
|
||||||
|
Confirm()
|
||||||
|
|
||||||
|
t.Views().Main().Content(MatchesRegexp("my commit message\n\\s*some description"))
|
||||||
|
|
||||||
|
t.Views().Files().
|
||||||
|
Focus().
|
||||||
|
Press(keys.Files.CommitChanges)
|
||||||
|
|
||||||
|
t.ExpectPopup().CommitMessagePanel().Confirm()
|
||||||
|
t.Views().Commits().
|
||||||
|
Lines(
|
||||||
|
Contains(wipCommitMessage),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -27,8 +27,8 @@ var RewordFirstCommit = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
NavigateToLine(Contains("commit 01")).
|
NavigateToLine(Contains("commit 01")).
|
||||||
Press(keys.Commits.RenameCommit).
|
Press(keys.Commits.RenameCommit).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
t.ExpectPopup().Prompt().
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
Title(Equals("reword commit")).
|
Title(Equals("Reword commit")).
|
||||||
InitialText(Equals("commit 01")).
|
InitialText(Equals("commit 01")).
|
||||||
Clear().
|
Clear().
|
||||||
Type("renamed 01").
|
Type("renamed 01").
|
||||||
|
@ -23,8 +23,8 @@ var RewordLastCommit = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
).
|
).
|
||||||
Press(keys.Commits.RenameCommit).
|
Press(keys.Commits.RenameCommit).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
t.ExpectPopup().Prompt().
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
Title(Equals("reword commit")).
|
Title(Equals("Reword commit")).
|
||||||
InitialText(Equals("commit 02")).
|
InitialText(Equals("commit 02")).
|
||||||
Clear().
|
Clear().
|
||||||
Type("renamed 02").
|
Type("renamed 02").
|
||||||
|
@ -31,8 +31,8 @@ var RewordYouAreHereCommit = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
).
|
).
|
||||||
Press(keys.Commits.RenameCommit).
|
Press(keys.Commits.RenameCommit).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
t.ExpectPopup().Prompt().
|
t.ExpectPopup().CommitMessagePanel().
|
||||||
Title(Equals("reword commit")).
|
Title(Equals("Reword commit")).
|
||||||
InitialText(Equals("commit 02")).
|
InitialText(Equals("commit 02")).
|
||||||
Clear().
|
Clear().
|
||||||
Type("renamed 02").
|
Type("renamed 02").
|
||||||
|
@ -49,10 +49,13 @@ var tests = []*components.IntegrationTest{
|
|||||||
commit.CommitMultiline,
|
commit.CommitMultiline,
|
||||||
commit.CreateTag,
|
commit.CreateTag,
|
||||||
commit.DiscardOldFileChange,
|
commit.DiscardOldFileChange,
|
||||||
|
commit.History,
|
||||||
|
commit.HistoryComplex,
|
||||||
commit.NewBranch,
|
commit.NewBranch,
|
||||||
commit.ResetAuthor,
|
commit.ResetAuthor,
|
||||||
commit.Revert,
|
commit.Revert,
|
||||||
commit.RevertMerge,
|
commit.RevertMerge,
|
||||||
|
commit.Reword,
|
||||||
commit.Search,
|
commit.Search,
|
||||||
commit.SetAuthor,
|
commit.SetAuthor,
|
||||||
commit.StageRangeOfLines,
|
commit.StageRangeOfLines,
|
||||||
|
Reference in New Issue
Block a user