summaryrefslogtreecommitdiffstats
path: root/pkg/gui/diffing.go
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2020-03-29 14:34:17 +1100
committerJesse Duffield <jessedduffield@gmail.com>2020-03-29 18:26:24 +1100
commit40fbce91ce636eb037c2221946261ce4f4bf4317 (patch)
tree9c31eb84b24e6e742ef519a4dad89218cca8092e /pkg/gui/diffing.go
parent33d287d2f0c6335559ac75c1b9a4705dfaa9ad7b (diff)
add new diff mode
WIP WIP WIP WIP WIP WIP WIP
Diffstat (limited to 'pkg/gui/diffing.go')
-rw-r--r--pkg/gui/diffing.go189
1 files changed, 189 insertions, 0 deletions
diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go
new file mode 100644
index 000000000..a42b6b335
--- /dev/null
+++ b/pkg/gui/diffing.go
@@ -0,0 +1,189 @@
+package gui
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/jesseduffield/gocui"
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+func (gui *Gui) inDiffMode() bool {
+ return gui.State.Diff.Ref != ""
+}
+
+func (gui *Gui) exitDiffMode() error {
+ gui.State.Diff = DiffState{}
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+}
+
+func (gui *Gui) renderDiff() error {
+ filterArg := ""
+ if gui.inFilterMode() {
+ filterArg = fmt.Sprintf(" -- %s", gui.State.FilterPath)
+ }
+
+ cmd := gui.OSCommand.ExecutableFromString(
+ fmt.Sprintf("git diff --color %s %s", gui.diffStr(), filterArg),
+ )
+ if err := gui.newPtyTask("main", cmd); err != nil {
+ gui.Log.Error(err)
+ }
+ return nil
+}
+
+// currentDiffTerminals returns the current diff terminals of the currently selected item.
+// in the case of a branch it returns both the branch and it's upstream name,
+// which becomes an option when you bring up the diff menu, but when you're just
+// flicking through branches it will be using the local branch name.
+func (gui *Gui) currentDiffTerminals() []string {
+ names := []string{}
+ switch gui.g.CurrentView().Name() {
+ case "files":
+ file, err := gui.getSelectedFile()
+ if err == nil {
+ names = append(names, file.Name)
+ }
+ case "commitFiles":
+ file := gui.getSelectedCommitFile()
+ if file != nil {
+ names = append(names, file.Name)
+ }
+ case "commits":
+ var commit *commands.Commit
+ switch gui.getCommitsView().Context {
+ case "reflog-commits":
+ commit = gui.getSelectedReflogCommit()
+ case "branch-commits":
+ commit = gui.getSelectedCommit()
+ }
+ if commit != nil {
+ names = append(names, commit.Sha)
+ }
+ case "stash":
+ entry := gui.getSelectedStashEntry()
+ if entry != nil {
+ names = append(names, entry.RefName())
+ }
+ case "branches":
+ switch gui.getBranchesView().Context {
+ case "local-branches":
+ branch := gui.getSelectedBranch()
+ if branch != nil {
+ names = append(names, branch.Name)
+ if branch.UpstreamName != "" {
+ names = append(names, branch.UpstreamName)
+ }
+ }
+ case "remotes":
+ remote := gui.getSelectedRemote()
+ if remote != nil {
+ names = append(names, remote.Name)
+ }
+ case "remote-branches":
+ remoteBranch := gui.getSelectedRemoteBranch()
+ if remoteBranch != nil {
+ names = append(names, remoteBranch.FullName())
+ }
+ case "tags":
+ tag := gui.getSelectedTag()
+ if tag != nil {
+ names = append(names, tag.Name)
+ }
+ }
+ }
+ return names
+}
+
+func (gui *Gui) currentDiffTerminal() string {
+ names := gui.currentDiffTerminals()
+ if len(names) == 0 {
+ return "HEAD"
+ }
+ return names[0]
+}
+
+func (gui *Gui) diffStr() string {
+ left := gui.State.Diff.Ref
+ right := gui.currentDiffTerminal()
+ if gui.State.Diff.Reverse {
+ left, right = right, left
+ }
+ return fmt.Sprintf("%s %s", left, right)
+}
+
+func (gui *Gui) handleCreateDiffingMenuPanel(g *gocui.Gui, v *gocui.View) error {
+ if gui.popupPanelFocused() {
+ return nil
+ }
+
+ names := gui.currentDiffTerminals()
+
+ menuItems := []*menuItem{}
+ for _, name := range names {
+ name := name
+ menuItems = append(menuItems, []*menuItem{
+ {
+ displayString: fmt.Sprintf("%s %s", gui.Tr.SLocalize("diffFrom"), name),
+ onPress: func() error {
+ gui.State.Diff.Ref = name
+ gui.State.Diff.Reverse = false
+ // can scope this down based on current view but too lazy right now
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ },
+ },
+ {
+ displayString: fmt.Sprintf("%s %s", gui.Tr.SLocalize("diffTo"), name),
+ onPress: func() error {
+ gui.State.Diff.Ref = name
+ gui.State.Diff.Reverse = true
+ // can scope this down based on current view but too lazy right now
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ },
+ },
+ }...)
+ }
+
+ menuItems = append(menuItems, []*menuItem{
+ {
+ displayString: gui.Tr.SLocalize("enterRefToDiffFrom"),
+ onPress: func() error {
+ return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enteRefName"), "", func(g *gocui.Gui, promptView *gocui.View) error {
+ gui.State.Diff.Ref = strings.TrimSpace(promptView.Buffer())
+ gui.State.Diff.Reverse = false
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ })
+ },
+ },
+ {
+ displayString: gui.Tr.SLocalize("enterRefToDiffTo"),
+ onPress: func() error {
+ return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("enteRefName"), "", func(g *gocui.Gui, promptView *gocui.View) error {
+ gui.State.Diff.Ref = strings.TrimSpace(promptView.Buffer())
+ gui.State.Diff.Reverse = true
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ })
+ },
+ },
+ }...)
+
+ menuItems = append(menuItems, &menuItem{
+ displayString: gui.Tr.SLocalize("swapDiff"),
+ onPress: func() error {
+ gui.State.Diff.Reverse = !gui.State.Diff.Reverse
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ },
+ })
+
+ if gui.inDiffMode() {
+ menuItems = append(menuItems, &menuItem{
+ displayString: gui.Tr.SLocalize("exitDiffMode"),
+ onPress: func() error {
+ gui.State.Diff = DiffState{}
+ return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
+ },
+ })
+ }
+
+ return gui.createMenu(gui.Tr.SLocalize("DiffingMenuTitle"), menuItems, createMenuOptions{showCancel: true})
+}