mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-13 00:07:59 +02:00
redoing
This commit is contained in:
parent
7c8df28d01
commit
daecdd7c2b
@ -83,6 +83,8 @@ Default path for the config file:
|
|||||||
prevTab: '['
|
prevTab: '['
|
||||||
nextScreenMode: '+'
|
nextScreenMode: '+'
|
||||||
prevScreenMode: '_'
|
prevScreenMode: '_'
|
||||||
|
undo: 'z'
|
||||||
|
redo: '<c-z>'
|
||||||
status:
|
status:
|
||||||
checkForUpdate: 'u'
|
checkForUpdate: 'u'
|
||||||
recentRepos: '<enter>'
|
recentRepos: '<enter>'
|
||||||
@ -138,7 +140,6 @@ Default path for the config file:
|
|||||||
toggleDragSelect-alt: 'V'
|
toggleDragSelect-alt: 'V'
|
||||||
toggleSelectHunk: 'a'
|
toggleSelectHunk: 'a'
|
||||||
pickBothHunks: 'b'
|
pickBothHunks: 'b'
|
||||||
undo: 'z'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Platform Defaults
|
## Platform Defaults
|
||||||
|
@ -314,6 +314,8 @@ keybinding:
|
|||||||
prevTab: '['
|
prevTab: '['
|
||||||
nextScreenMode: '+'
|
nextScreenMode: '+'
|
||||||
prevScreenMode: '_'
|
prevScreenMode: '_'
|
||||||
|
undo: 'z'
|
||||||
|
redo: '<c-z>'
|
||||||
status:
|
status:
|
||||||
checkForUpdate: 'u'
|
checkForUpdate: 'u'
|
||||||
recentRepos: '<enter>'
|
recentRepos: '<enter>'
|
||||||
@ -370,7 +372,6 @@ keybinding:
|
|||||||
toggleDragSelect-alt: 'V'
|
toggleDragSelect-alt: 'V'
|
||||||
toggleSelectHunk: 'a'
|
toggleSelectHunk: 'a'
|
||||||
pickBothHunks: 'b'
|
pickBothHunks: 'b'
|
||||||
undo: 'z'
|
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,9 @@ type guiState struct {
|
|||||||
type UndoState struct {
|
type UndoState struct {
|
||||||
ReflogKey string
|
ReflogKey string
|
||||||
ReflogIdx int
|
ReflogIdx int
|
||||||
|
// this is the index of the most recent reflog entry that the user initiated themselves
|
||||||
|
// (as opposed to being created by an undo or redo action)
|
||||||
|
UndoCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
// for now the split view will always be on
|
// for now the split view will always be on
|
||||||
|
@ -315,11 +315,18 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "",
|
ViewName: "",
|
||||||
Key: gui.getKey("main.undo"),
|
Key: gui.getKey("universal.undo"),
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.reflogUndo,
|
Handler: gui.reflogUndo,
|
||||||
Description: gui.Tr.SLocalize("undoReflog"),
|
Description: gui.Tr.SLocalize("undoReflog"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ViewName: "",
|
||||||
|
Key: gui.getKey("universal.redo"),
|
||||||
|
Modifier: gocui.ModNone,
|
||||||
|
Handler: gui.reflogRedo,
|
||||||
|
Description: gui.Tr.SLocalize("redoReflog"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ViewName: "status",
|
ViewName: "status",
|
||||||
Key: gui.getKey("universal.edit"),
|
Key: gui.getKey("universal.edit"),
|
||||||
@ -1349,7 +1356,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
{
|
{
|
||||||
ViewName: "main",
|
ViewName: "main",
|
||||||
Contexts: []string{"merging"},
|
Contexts: []string{"merging"},
|
||||||
Key: gui.getKey("main.undo"),
|
Key: gui.getKey("universal.undo"),
|
||||||
Modifier: gocui.ModNone,
|
Modifier: gocui.ModNone,
|
||||||
Handler: gui.handlePopFileSnapshot,
|
Handler: gui.handlePopFileSnapshot,
|
||||||
Description: gui.Tr.SLocalize("undo"),
|
Description: gui.Tr.SLocalize("undo"),
|
||||||
|
@ -255,7 +255,7 @@ func (gui *Gui) renderMergeOptions() error {
|
|||||||
fmt.Sprintf("%s %s", gui.getKeyDisplay("universal.prevBlock"), gui.getKeyDisplay("universal.nextBlock")): gui.Tr.SLocalize("navigateConflicts"),
|
fmt.Sprintf("%s %s", gui.getKeyDisplay("universal.prevBlock"), gui.getKeyDisplay("universal.nextBlock")): gui.Tr.SLocalize("navigateConflicts"),
|
||||||
gui.getKeyDisplay("universal.select"): gui.Tr.SLocalize("pickHunk"),
|
gui.getKeyDisplay("universal.select"): gui.Tr.SLocalize("pickHunk"),
|
||||||
gui.getKeyDisplay("main.pickBothHunks"): gui.Tr.SLocalize("pickBothHunks"),
|
gui.getKeyDisplay("main.pickBothHunks"): gui.Tr.SLocalize("pickBothHunks"),
|
||||||
gui.getKeyDisplay("main.undo"): gui.Tr.SLocalize("undo"),
|
gui.getKeyDisplay("universal.undo"): gui.Tr.SLocalize("undo"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func (gui *Gui) handleCreateReflogResetMenu(g *gocui.Gui, v *gocui.View) error {
|
|||||||
|
|
||||||
type reflogAction struct {
|
type reflogAction struct {
|
||||||
regexStr string
|
regexStr string
|
||||||
action func(match []string, commitSha string, prevCommitSha string, onDone func()) (bool, error)
|
action func(match []string, commitSha string, onDone func()) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) reflogKey(reflogCommit *commands.Commit) string {
|
func (gui *Gui) reflogKey(reflogCommit *commands.Commit) string {
|
||||||
@ -130,10 +130,17 @@ func (gui *Gui) setUndoReflogKey(key string) {
|
|||||||
func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error {
|
func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error {
|
||||||
reflogCommits := gui.State.ReflogCommits
|
reflogCommits := gui.State.ReflogCommits
|
||||||
|
|
||||||
|
// if the index of the previous reflog entry has changed, we need to start from the beginning, because it means there's been user input.
|
||||||
|
startIndex := gui.State.Undo.ReflogIdx
|
||||||
|
if gui.idxOfUndoReflogKey(gui.State.Undo.ReflogKey) != gui.State.Undo.ReflogIdx {
|
||||||
|
gui.State.Undo.UndoCount = 0
|
||||||
|
startIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
reflogActions := []reflogAction{
|
reflogActions := []reflogAction{
|
||||||
{
|
{
|
||||||
regexStr: `^checkout: moving from ([\S]+)`,
|
regexStr: `^checkout: moving from ([\S]+)`,
|
||||||
action: func(match []string, commitSha string, prevCommitSha string, onDone func()) (bool, error) {
|
action: func(match []string, commitSha string, onDone func()) (bool, error) {
|
||||||
if len(match) <= 1 {
|
if len(match) <= 1 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@ -141,19 +148,13 @@ func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
regexStr: `^commit|^rebase -i \(start\)`,
|
regexStr: `^commit|^rebase -i \(start\)|^reset: moving to|^pull`,
|
||||||
action: func(match []string, commitSha string, prevCommitSha string, onDone func()) (bool, error) {
|
action: func(match []string, commitSha string, onDone func()) (bool, error) {
|
||||||
return true, gui.handleHardResetWithAutoStash(prevCommitSha, onDone)
|
return true, gui.handleHardResetWithAutoStash(commitSha, onDone)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the index of the previous reflog entry has changed, we need to start from the beginning, because it means there's been user input.
|
|
||||||
startIndex := gui.State.Undo.ReflogIdx
|
|
||||||
if gui.idxOfUndoReflogKey(gui.State.Undo.ReflogKey) != gui.State.Undo.ReflogIdx {
|
|
||||||
startIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for offsetIdx, reflogCommit := range reflogCommits[startIndex:] {
|
for offsetIdx, reflogCommit := range reflogCommits[startIndex:] {
|
||||||
i := offsetIdx + startIndex
|
i := offsetIdx + startIndex
|
||||||
for _, action := range reflogActions {
|
for _, action := range reflogActions {
|
||||||
@ -167,12 +168,68 @@ func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error {
|
|||||||
prevCommitSha = reflogCommits[i+1].Sha
|
prevCommitSha = reflogCommits[i+1].Sha
|
||||||
}
|
}
|
||||||
|
|
||||||
nextKey := gui.reflogKey(gui.State.ReflogCommits[i+1])
|
nextKey := gui.reflogKey(reflogCommits[i+1])
|
||||||
onDone := func() {
|
onDone := func() {
|
||||||
gui.setUndoReflogKey(nextKey)
|
gui.setUndoReflogKey(nextKey)
|
||||||
|
gui.State.Undo.UndoCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
isMatchingAction, err := action.action(match, reflogCommit.Sha, prevCommitSha, onDone)
|
isMatchingAction, err := action.action(match, prevCommitSha, onDone)
|
||||||
|
if !isMatchingAction {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) reflogRedo(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
reflogCommits := gui.State.ReflogCommits
|
||||||
|
|
||||||
|
// if the index of the previous reflog entry has changed there is nothing to redo because there's been a user action
|
||||||
|
startIndex := gui.State.Undo.ReflogIdx
|
||||||
|
if gui.idxOfUndoReflogKey(gui.State.Undo.ReflogKey) != gui.State.Undo.ReflogIdx || startIndex == 0 || gui.State.Undo.UndoCount == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
reflogActions := []reflogAction{
|
||||||
|
{
|
||||||
|
regexStr: `^checkout: moving from [\S]+ to ([\S]+)`,
|
||||||
|
action: func(match []string, commitSha string, onDone func()) (bool, error) {
|
||||||
|
if len(match) <= 1 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, gui.handleCheckoutRef(match[1], handleCheckoutRefOptions{onDone: onDone, waitingStatus: gui.Tr.SLocalize("RedoingStatus")})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
regexStr: `^commit|^rebase -i \(start\)|^reset: moving to|^pull`,
|
||||||
|
action: func(match []string, commitSha string, onDone func()) (bool, error) {
|
||||||
|
return true, gui.handleHardResetWithAutoStash(commitSha, onDone)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := startIndex - 1; i > 0; i++ {
|
||||||
|
reflogCommit := reflogCommits[i]
|
||||||
|
|
||||||
|
for _, action := range reflogActions {
|
||||||
|
re := regexp.MustCompile(action.regexStr)
|
||||||
|
match := re.FindStringSubmatch(reflogCommit.Name)
|
||||||
|
if len(match) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
prevKey := gui.reflogKey(reflogCommits[i-1])
|
||||||
|
onDone := func() {
|
||||||
|
gui.setUndoReflogKey(prevKey)
|
||||||
|
gui.State.Undo.UndoCount--
|
||||||
|
}
|
||||||
|
|
||||||
|
isMatchingAction, err := action.action(match, reflogCommit.Sha, onDone)
|
||||||
if !isMatchingAction {
|
if !isMatchingAction {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -363,6 +363,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
|||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "undoReflog",
|
ID: "undoReflog",
|
||||||
Other: "undo (via reflog) (experimental)",
|
Other: "undo (via reflog) (experimental)",
|
||||||
|
}, &i18n.Message{
|
||||||
|
ID: "redoReflog",
|
||||||
|
Other: "redo (via reflog) (experimental)",
|
||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "pop",
|
ID: "pop",
|
||||||
Other: "pop",
|
Other: "pop",
|
||||||
@ -747,6 +750,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
|||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "UndoingStatus",
|
ID: "UndoingStatus",
|
||||||
Other: "undoing",
|
Other: "undoing",
|
||||||
|
}, &i18n.Message{
|
||||||
|
ID: "RedoingStatus",
|
||||||
|
Other: "redoing",
|
||||||
}, &i18n.Message{
|
}, &i18n.Message{
|
||||||
ID: "CheckingOutStatus",
|
ID: "CheckingOutStatus",
|
||||||
Other: "checking out",
|
Other: "checking out",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user