summaryrefslogtreecommitdiffstats
path: root/pkg/gui
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2019-11-18 09:38:36 +1100
committerJesse Duffield <jessedduffield@gmail.com>2019-11-21 22:07:14 +1100
commit3c1322914518168374be02a78cee968cf1d13730 (patch)
treed31c1064a1101a6081db025328f39789fc3b74c4 /pkg/gui
parentcea24c2cf98c48e187900041d9e3bbeb93596019 (diff)
add tags panel
Diffstat (limited to 'pkg/gui')
-rw-r--r--pkg/gui/branches_panel.go9
-rw-r--r--pkg/gui/commits_panel.go27
-rw-r--r--pkg/gui/gui.go9
-rw-r--r--pkg/gui/keybindings.go39
-rw-r--r--pkg/gui/list_view.go10
-rw-r--r--pkg/gui/remotes_panel.go8
-rw-r--r--pkg/gui/tags_panel.go149
-rw-r--r--pkg/gui/view_helpers.go2
8 files changed, 249 insertions, 4 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 790f24bd4..f78d86ab8 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -80,6 +80,10 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
return err
}
+ if err := gui.refreshTags(); err != nil {
+ return err
+ }
+
g.Update(func(g *gocui.Gui) error {
builder, err := commands.NewBranchListBuilder(gui.Log, gui.GitCommand)
if err != nil {
@@ -373,7 +377,7 @@ func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) onBranchesTabClick(tabIndex int) error {
- contexts := []string{"local-branches", "remotes", "tabs"}
+ contexts := []string{"local-branches", "remotes", "tags"}
branchesView := gui.getBranchesView()
branchesView.TabIndex = tabIndex
@@ -388,6 +392,7 @@ func (gui *Gui) switchBranchesPanelContext(context string) error {
"local-branches": 0,
"remotes": 1,
"remote-branches": 1,
+ "tags": 2,
}
branchesView.TabIndex = contextTabIndexMap[context]
@@ -399,6 +404,8 @@ func (gui *Gui) switchBranchesPanelContext(context string) error {
return gui.renderRemotesWithSelection()
case "remote-branches":
return gui.renderRemoteBranchesWithSelection()
+ case "tags":
+ return gui.renderTagsWithSelection()
}
return nil
diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go
index c29935f14..22ea6fe7e 100644
--- a/pkg/gui/commits_panel.go
+++ b/pkg/gui/commits_panel.go
@@ -584,3 +584,30 @@ func (gui *Gui) handleCreateCommitResetMenu(g *gocui.Gui, v *gocui.View) error {
return gui.createMenu(fmt.Sprintf("%s %s", gui.Tr.SLocalize("resetTo"), commit.Sha), options, len(options), handleMenuPress)
}
+
+func (gui *Gui) handleTagCommit(g *gocui.Gui, v *gocui.View) error {
+ // TODO: bring up menu asking if you want to make a lightweight or annotated tag
+ // if annotated, switch to a subprocess to create the message
+
+ commit := gui.getSelectedCommit(g)
+ if commit == nil {
+ return nil
+ }
+
+ return gui.handleCreateLightweightTag(commit.Sha)
+}
+
+func (gui *Gui) handleCreateLightweightTag(commitSha string) error {
+ return gui.createPromptPanel(gui.g, gui.getCommitsView(), gui.Tr.SLocalize("TagNameTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
+ if err := gui.GitCommand.CreateLightweightTag(v.Buffer(), commitSha); err != nil {
+ return gui.createErrorPanel(g, err.Error())
+ }
+ if err := gui.refreshCommits(g); err != nil {
+ return gui.createErrorPanel(g, err.Error())
+ }
+ if err := gui.refreshTags(); err != nil {
+ return gui.createErrorPanel(g, err.Error())
+ }
+ return gui.handleCommitSelect(g, v)
+ })
+}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index c08c82817..3b6f2fb11 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -120,6 +120,10 @@ type remoteBranchesState struct {
SelectedLine int
}
+type tagsPanelState struct {
+ SelectedLine int
+}
+
type commitPanelState struct {
SelectedLine int
SpecificDiffMode bool
@@ -148,6 +152,7 @@ type panelStates struct {
Branches *branchPanelState
Remotes *remotePanelState
RemoteBranches *remoteBranchesState
+ Tags *tagsPanelState
Commits *commitPanelState
Stash *stashPanelState
Menu *menuPanelState
@@ -166,6 +171,7 @@ type guiState struct {
DiffEntries []*commands.Commit
Remotes []*commands.Remote
RemoteBranches []*commands.RemoteBranch
+ Tags []*commands.Tag
MenuItemCount int // can't store the actual list because it's of interface{} type
PreviousView string
Platform commands.Platform
@@ -198,6 +204,7 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma
Branches: &branchPanelState{SelectedLine: 0},
Remotes: &remotePanelState{SelectedLine: 0},
RemoteBranches: &remoteBranchesState{SelectedLine: -1},
+ Tags: &tagsPanelState{SelectedLine: -1},
Commits: &commitPanelState{SelectedLine: -1},
CommitFiles: &commitFilesPanelState{SelectedLine: -1},
Stash: &stashPanelState{SelectedLine: -1},
@@ -497,7 +504,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
return err
}
branchesView.Title = gui.Tr.SLocalize("BranchesTitle")
- branchesView.Tabs = []string{"Local Branches", "Remotes"}
+ branchesView.Tabs = []string{"Local Branches", "Remotes", "Tags"}
branchesView.FgColor = textColor
}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index a64bb2965..2dfdedf61 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -403,6 +403,38 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Description: gui.Tr.SLocalize("FastForward"),
},
{
+ ViewName: "branches",
+ Contexts: []string{"tags"},
+ Key: gocui.KeySpace,
+ Modifier: gocui.ModNone,
+ Handler: gui.handleCheckoutTag,
+ Description: gui.Tr.SLocalize("checkout"),
+ },
+ {
+ ViewName: "branches",
+ Contexts: []string{"tags"},
+ Key: 'd',
+ Modifier: gocui.ModNone,
+ Handler: gui.handleDeleteTag,
+ Description: gui.Tr.SLocalize("deleteTag"),
+ },
+ {
+ ViewName: "branches",
+ Contexts: []string{"tags"},
+ Key: 'P',
+ Modifier: gocui.ModNone,
+ Handler: gui.handlePushTag,
+ Description: gui.Tr.SLocalize("pushTags"),
+ },
+ {
+ ViewName: "branches",
+ Contexts: []string{"tags"},
+ Key: 'n',
+ Modifier: gocui.ModNone,
+ Handler: gui.handleCreateTag,
+ Description: gui.Tr.SLocalize("createTag"),
+ },
+ {
ViewName: "branches",
Key: ']',
Modifier: gocui.ModNone,
@@ -556,6 +588,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Description: gui.Tr.SLocalize("CommitsDiff"),
},
{
+ ViewName: "commits",
+ Key: 'T',
+ Modifier: gocui.ModNone,
+ Handler: gui.handleTagCommit,
+ Description: gui.Tr.SLocalize("tagCommit"),
+ },
+ {
ViewName: "stash",
Key: gocui.KeySpace,
Modifier: gocui.ModNone,
diff --git a/pkg/gui/list_view.go b/pkg/gui/list_view.go
index 3a93bd526..4d72efc43 100644
--- a/pkg/gui/list_view.go
+++ b/pkg/gui/list_view.go
@@ -117,6 +117,16 @@ func (gui *Gui) getListViews() []*listView {
rendersToMainView: true,
},
{
+ viewName: "branches",
+ context: "tags",
+ getItemsLength: func() int { return len(gui.State.Tags) },
+ getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Tags.SelectedLine },
+ handleFocus: gui.handleTagSelect,
+ handleItemSelect: gui.handleTagSelect,
+ gui: gui,
+ rendersToMainView: true,
+ },
+ {
viewName: "commits",
getItemsLength: func() int { return len(gui.State.Commits) },
getSelectedLineIdxPtr: func() *int { return &gui.State.Panels.Commits.SelectedLine },
diff --git a/pkg/gui/remotes_panel.go b/pkg/gui/remotes_panel.go
index bf9f8e110..90c2c8d59 100644
--- a/pkg/gui/remotes_panel.go
+++ b/pkg/gui/remotes_panel.go
@@ -35,6 +35,9 @@ func (gui *Gui) handleRemoteSelect(g *gocui.Gui, v *gocui.View) error {
gui.getMainView().Title = "Remote"
remote := gui.getSelectedRemote()
+ if remote == nil {
+ return gui.renderString(g, "main", "No remotes")
+ }
if err := gui.focusPoint(0, gui.State.Panels.Remotes.SelectedLine, len(gui.State.Remotes), v); err != nil {
return err
}
@@ -42,8 +45,6 @@ func (gui *Gui) handleRemoteSelect(g *gocui.Gui, v *gocui.View) error {
return gui.renderString(g, "main", fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n")))
}
-// gui.refreshStatus is called at the end of this because that's when we can
-// be sure there is a state.Remotes array to pick the current remote from
func (gui *Gui) refreshRemotes() error {
prevSelectedRemote := gui.getSelectedRemote()
@@ -92,6 +93,9 @@ func (gui *Gui) renderRemotesWithSelection() error {
func (gui *Gui) handleRemoteEnter(g *gocui.Gui, v *gocui.View) error {
// naive implementation: get the branches and render them to the list, change the context
remote := gui.getSelectedRemote()
+ if remote == nil {
+ return nil
+ }
gui.State.RemoteBranches = remote.Branches
diff --git a/pkg/gui/tags_panel.go b/pkg/gui/tags_panel.go
new file mode 100644
index 000000000..e1f9d364a
--- /dev/null
+++ b/pkg/gui/tags_panel.go
@@ -0,0 +1,149 @@
+package gui
+
+import (
+ "fmt"
+
+ "github.com/jesseduffield/gocui"
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+// list panel functions
+
+func (gui *Gui) getSelectedTag() *commands.Tag {
+ selectedLine := gui.State.Panels.Tags.SelectedLine
+ if selectedLine == -1 || len(gui.State.Tags) == 0 {
+ return nil
+ }
+
+ return gui.State.Tags[selectedLine]
+}
+
+func (gui *Gui) handleTagSelect(g *gocui.Gui, v *gocui.View) error {
+ if gui.popupPanelFocused() {
+ return nil
+ }
+
+ gui.State.SplitMainPanel = false
+
+ if _, err := gui.g.SetCurrentView(v.Name()); err != nil {
+ return err
+ }
+
+ gui.getMainView().Title = "Tag"
+
+ tag := gui.getSelectedTag()
+ if tag == nil {
+ return gui.renderString(g, "main", "No tags")
+ }
+ if err := gui.focusPoint(0, gui.State.Panels.Tags.SelectedLine, len(gui.State.Tags), v); err != nil {
+ return err
+ }
+
+ go func() {
+ show, err := gui.GitCommand.ShowTag(tag.Name)
+ if err != nil {
+ show = ""
+ }
+
+ graph, err := gui.GitCommand.GetBranchGraph(tag.Name)
+ if err != nil {
+ graph = "No graph for tag " + tag.Name
+ }
+
+ _ = gui.renderString(g, "main", fmt.Sprintf("%s\n%s", show, graph))
+ }()
+
+ return nil
+}
+
+func (gui *Gui) refreshTags() error {
+ tags, err := gui.GitCommand.GetTags()
+ if err != nil {
+ return gui.createErrorPanel(gui.g, err.Error())
+ }
+
+ gui.State.Tags = tags
+
+ if gui.getBranchesView().Context == "tags" {
+ gui.renderTagsWithSelection()
+ }
+
+ return nil
+}
+
+func (gui *Gui) renderTagsWithSelection() error {
+ branchesView := gui.getBranchesView()
+
+ gui.refreshSelectedLine(&gui.State.Panels.Tags.SelectedLine, len(gui.State.Tags))
+ if err := gui.renderListPanel(branchesView, gui.State.Tags); err != nil {
+ return err
+ }
+ if err := gui.handleTagSelect(gui.g, branchesView); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (gui *Gui) handleCheckoutTag(g *gocui.Gui, v *gocui.View) error {
+ tag := gui.getSelectedTag()
+ if tag == nil {
+ return nil
+ }
+ if err := gui.handleCheckoutBranch(tag.Name); err != nil {
+ return err
+ }
+ return gui.switchBranchesPanelContext("local-branches")
+}
+
+func (gui *Gui) handleDeleteTag(g *gocui.Gui, v *gocui.View) error {
+ tag := gui.getSelectedTag()
+ if tag == nil {
+ return nil
+ }
+
+ prompt := gui.Tr.TemplateLocalize(
+ "DeleteTagPrompt",
+ Teml{
+ "tagName": tag.Name,
+ },
+ )
+
+ return gui.createConfirmationPanel(gui.g, v, true, gui.Tr.SLocalize("DeleteTagTitle"), prompt, func(g *gocui.Gui, v *gocui.View) error {
+ if err := gui.GitCommand.DeleteTag(tag.Name); err != nil {
+ return gui.createErrorPanel(gui.g, err.Error())
+ }
+ return gui.refreshTags()
+ }, nil)
+}
+
+func (gui *Gui) handlePushTag(g *gocui.Gui, v *gocui.View) error {
+ tag := gui.getSelectedTag()
+ if tag == nil {
+ return nil
+ }
+
+ title := gui.Tr.TemplateLocalize(
+ "PushTagTitle",
+ Teml{
+ "tagName": tag.Name,
+ },
+ )
+
+ return gui.createPromptPanel(gui.g, v, title, "origin", func(g *gocui.Gui, v *gocui.View) error {
+ if err := gui.GitCommand.PushTag(v.Buffer(), tag.Name); err != nil {
+ return gui.createErrorPanel(gui.g, err.Error())
+ }
+ return gui.refreshTags()
+ })
+}
+
+func (gui *Gui) handleCreateTag(g *gocui.Gui, v *gocui.View) error {
+ return gui.createPromptPanel(gui.g, v, gui.Tr.SLocalize("CreateTagTitle"), "", func(g *gocui.Gui, v *gocui.View) error {
+ // leaving commit SHA blank so that we're just creating the tag for the current commit
+ if err := gui.GitCommand.CreateLightweightTag(v.Buffer(), ""); err != nil {
+ return gui.createErrorPanel(gui.g, err.Error())
+ }
+ return gui.refreshTags()
+ })
+}
diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go
index e671165a3..6112a5422 100644
--- a/pkg/gui/view_helpers.go
+++ b/pkg/gui/view_helpers.go
@@ -112,6 +112,8 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
return gui.handleRemoteSelect(g, v)
case "remote-branches":
return gui.handleRemoteBranchSelect(g, v)
+ case "tags":
+ return gui.handleTagSelect(g, v)
default:
return errors.New("unknown branches panel context: " + branchesView.Context)
}