aboutsummaryrefslogtreecommitdiffstats
path: root/termui
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-08-12 21:09:30 +0200
committerMichael Muré <batolettre@gmail.com>2018-08-12 21:09:30 +0200
commite2f4b027c946831c3f4f119d87a80513c7cf8fdc (patch)
treeb2ec57c89c49062ab2e8adeacb2646d2f152db80 /termui
parent721ed3248e8bf167a89df14d9fc2bf5b0fe45753 (diff)
downloadgit-bug-e2f4b027c946831c3f4f119d87a80513c7cf8fdc.tar.gz
termui: implement push/pull
Diffstat (limited to 'termui')
-rw-r--r--termui/bug_table.go100
-rw-r--r--termui/error_popup.go72
-rw-r--r--termui/msg_popup.go89
-rw-r--r--termui/show_bug.go6
-rw-r--r--termui/termui.go14
5 files changed, 198 insertions, 83 deletions
diff --git a/termui/bug_table.go b/termui/bug_table.go
index 1432d943..cd5ee1f6 100644
--- a/termui/bug_table.go
+++ b/termui/bug_table.go
@@ -1,7 +1,9 @@
package termui
import (
+ "bytes"
"fmt"
+
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/util"
@@ -14,6 +16,8 @@ const bugTableHeaderView = "bugTableHeaderView"
const bugTableFooterView = "bugTableFooterView"
const bugTableInstructionView = "bugTableInstructionView"
+const remote = "origin"
+
type bugTable struct {
repo cache.RepoCacher
allIds []string
@@ -105,7 +109,7 @@ func (bt *bugTable) layout(g *gocui.Gui) error {
v.Frame = false
v.BgColor = gocui.ColorBlue
- fmt.Fprintf(v, "[q] Quit [←,h] Previous page [↓,j] Down [↑,k] Up [→,l] Next page [enter] Open bug [n] New bug")
+ fmt.Fprintf(v, "[q] Quit [←↓↑→,hjkl] Navigation [enter] Open bug [n] New bug [i] Pull [o] Push")
}
_, err = g.SetCurrentView(bugTableView)
@@ -176,6 +180,18 @@ func (bt *bugTable) keybindings(g *gocui.Gui) error {
return err
}
+ // Pull
+ if err := g.SetKeybinding(bugTableView, 'i', gocui.ModNone,
+ bt.pull); err != nil {
+ return err
+ }
+
+ // Push
+ if err := g.SetKeybinding(bugTableView, 'o', gocui.ModNone,
+ bt.push); err != nil {
+ return err
+ }
+
return nil
}
@@ -383,3 +399,85 @@ func (bt *bugTable) openBug(g *gocui.Gui, v *gocui.View) error {
ui.showBug.SetBug(bt.bugs[bt.pageCursor+y])
return ui.activateWindow(ui.showBug)
}
+
+func (bt *bugTable) pull(g *gocui.Gui, v *gocui.View) error {
+ // Note: this is very hacky
+
+ ui.msgPopup.Activate("Pull from remote "+remote, "...")
+
+ go func() {
+ stdout, err := bt.repo.Fetch(remote)
+
+ if err != nil {
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
+ return nil
+ })
+ } else {
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.UpdateMessage(stdout)
+ return nil
+ })
+ }
+
+ var buffer bytes.Buffer
+ beginLine := ""
+
+ for merge := range bt.repo.MergeAll(remote) {
+ if merge.Status == bug.MsgMergeNothing {
+ continue
+ }
+
+ if merge.Err != nil {
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
+ return nil
+ })
+ } else {
+ fmt.Fprintf(&buffer, "%s%s: %s",
+ beginLine, util.Cyan(merge.HumanId), merge.Status,
+ )
+
+ beginLine = "\n"
+
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.UpdateMessage(buffer.String())
+ return nil
+ })
+ }
+ }
+
+ fmt.Fprintf(&buffer, "%sdone", beginLine)
+
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.UpdateMessage(buffer.String())
+ return nil
+ })
+
+ }()
+
+ return nil
+}
+
+func (bt *bugTable) push(g *gocui.Gui, v *gocui.View) error {
+ ui.msgPopup.Activate("Push to remote "+remote, "...")
+
+ go func() {
+ // TODO: make the remote configurable
+ stdout, err := bt.repo.Push(remote)
+
+ if err != nil {
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
+ return nil
+ })
+ } else {
+ g.Update(func(gui *gocui.Gui) error {
+ ui.msgPopup.UpdateMessage(stdout)
+ return nil
+ })
+ }
+ }()
+
+ return nil
+}
diff --git a/termui/error_popup.go b/termui/error_popup.go
deleted file mode 100644
index f8f53feb..00000000
--- a/termui/error_popup.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package termui
-
-import (
- "fmt"
-
- "github.com/MichaelMure/git-bug/util"
- "github.com/jroimartin/gocui"
-)
-
-const errorPopupView = "errorPopupView"
-
-type errorPopup struct {
- message string
-}
-
-func newErrorPopup() *errorPopup {
- return &errorPopup{
- message: "",
- }
-}
-
-func (ep *errorPopup) keybindings(g *gocui.Gui) error {
- if err := g.SetKeybinding(errorPopupView, gocui.KeySpace, gocui.ModNone, ep.close); err != nil {
- return err
- }
- if err := g.SetKeybinding(errorPopupView, gocui.KeyEnter, gocui.ModNone, ep.close); err != nil {
- return err
- }
-
- return nil
-}
-
-func (ep *errorPopup) layout(g *gocui.Gui) error {
- if ep.message == "" {
- return nil
- }
-
- maxX, maxY := g.Size()
-
- width := minInt(30, maxX)
- wrapped, nblines := util.WordWrap(ep.message, width-2)
- height := minInt(nblines+1, maxY)
- x0 := (maxX - width) / 2
- y0 := (maxY - height) / 2
-
- v, err := g.SetView(errorPopupView, x0, y0, x0+width, y0+height)
- if err != nil {
- if err != gocui.ErrUnknownView {
- return err
- }
-
- v.Frame = true
- v.Title = "Error"
-
- fmt.Fprintf(v, wrapped)
- }
-
- if _, err := g.SetCurrentView(errorPopupView); err != nil {
- return err
- }
-
- return nil
-}
-
-func (ep *errorPopup) close(g *gocui.Gui, v *gocui.View) error {
- ep.message = ""
- return g.DeleteView(errorPopupView)
-}
-
-func (ep *errorPopup) Activate(message string) {
- ep.message = message
-}
diff --git a/termui/msg_popup.go b/termui/msg_popup.go
new file mode 100644
index 00000000..dea24fb4
--- /dev/null
+++ b/termui/msg_popup.go
@@ -0,0 +1,89 @@
+package termui
+
+import (
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/util"
+ "github.com/jroimartin/gocui"
+)
+
+const msgPopupView = "msgPopupView"
+
+const msgPopupErrorTitle = "Error"
+
+type msgPopup struct {
+ active bool
+ title string
+ message string
+}
+
+func newMsgPopup() *msgPopup {
+ return &msgPopup{
+ message: "",
+ }
+}
+
+func (ep *msgPopup) keybindings(g *gocui.Gui) error {
+ if err := g.SetKeybinding(msgPopupView, gocui.KeySpace, gocui.ModNone, ep.close); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding(msgPopupView, gocui.KeyEnter, gocui.ModNone, ep.close); err != nil {
+ return err
+ }
+ if err := g.SetKeybinding(msgPopupView, 'q', gocui.ModNone, ep.close); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (ep *msgPopup) layout(g *gocui.Gui) error {
+ if !ep.active {
+ return nil
+ }
+
+ maxX, maxY := g.Size()
+
+ width := minInt(60, maxX)
+ wrapped, lines := util.TextWrap(ep.message, width-2)
+ height := minInt(lines+1, maxY-3)
+ x0 := (maxX - width) / 2
+ y0 := (maxY - height) / 2
+
+ v, err := g.SetView(msgPopupView, x0, y0, x0+width, y0+height)
+ if err != nil {
+ if err != gocui.ErrUnknownView {
+ return err
+ }
+
+ v.Frame = true
+ v.Autoscroll = true
+ }
+
+ v.Title = ep.title
+
+ v.Clear()
+ fmt.Fprintf(v, wrapped)
+
+ if _, err := g.SetCurrentView(msgPopupView); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (ep *msgPopup) close(g *gocui.Gui, v *gocui.View) error {
+ ep.active = false
+ ep.message = ""
+ return g.DeleteView(msgPopupView)
+}
+
+func (ep *msgPopup) Activate(title string, message string) {
+ ep.active = true
+ ep.title = title
+ ep.message = message
+}
+
+func (ep *msgPopup) UpdateMessage(message string) {
+ ep.message = message
+}
diff --git a/termui/show_bug.go b/termui/show_bug.go
index c0896e08..799af9c7 100644
--- a/termui/show_bug.go
+++ b/termui/show_bug.go
@@ -93,7 +93,7 @@ func (sb *showBug) layout(g *gocui.Gui) error {
}
v.Clear()
- fmt.Fprintf(v, "[q] Save and return [←,h] Left [↓,j] Down [↑,k] Up [→,l] Right ")
+ fmt.Fprintf(v, "[q] Save and return [←↓↑→,hjkl] Navigation ")
if sb.isOnSide {
fmt.Fprint(v, "[a] Add label [r] Remove label")
@@ -591,7 +591,7 @@ func (sb *showBug) addLabel(g *gocui.Gui, v *gocui.View) error {
err := sb.bug.ChangeLabels(trimLabels(labels), nil)
if err != nil {
- ui.errorPopup.Activate(err.Error())
+ ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
}
g.Update(func(gui *gocui.Gui) error {
@@ -614,7 +614,7 @@ func (sb *showBug) removeLabel(g *gocui.Gui, v *gocui.View) error {
err := sb.bug.ChangeLabels(nil, trimLabels(labels))
if err != nil {
- ui.errorPopup.Activate(err.Error())
+ ui.msgPopup.Activate(msgPopupErrorTitle, err.Error())
}
g.Update(func(gui *gocui.Gui) error {
diff --git a/termui/termui.go b/termui/termui.go
index 535842e4..b45bbc2e 100644
--- a/termui/termui.go
+++ b/termui/termui.go
@@ -19,7 +19,7 @@ type termUI struct {
bugTable *bugTable
showBug *showBug
- errorPopup *errorPopup
+ msgPopup *msgPopup
inputPopup *inputPopup
}
@@ -49,7 +49,7 @@ func Run(repo repository.Repo) error {
cache: c,
bugTable: newBugTable(c),
showBug: newShowBug(c),
- errorPopup: newErrorPopup(),
+ msgPopup: newMsgPopup(),
inputPopup: newInputPopup(),
}
@@ -106,7 +106,7 @@ func layout(g *gocui.Gui) error {
return err
}
- if err := ui.errorPopup.layout(g); err != nil {
+ if err := ui.msgPopup.layout(g); err != nil {
return err
}
@@ -131,7 +131,7 @@ func keybindings(g *gocui.Gui) error {
return err
}
- if err := ui.errorPopup.keybindings(g); err != nil {
+ if err := ui.msgPopup.keybindings(g); err != nil {
return err
}
@@ -166,7 +166,7 @@ func newBugWithEditor(repo cache.RepoCacher) error {
}
if err == input.ErrEmptyTitle {
- ui.errorPopup.Activate("Empty title, aborting.")
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Empty title, aborting.")
} else {
_, err := repo.NewBug(title, message)
if err != nil {
@@ -199,7 +199,7 @@ func addCommentWithEditor(bug cache.BugCacher) error {
}
if err == input.ErrEmptyMessage {
- ui.errorPopup.Activate("Empty message, aborting.")
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Empty message, aborting.")
} else {
err := bug.AddComment(message)
if err != nil {
@@ -232,7 +232,7 @@ func setTitleWithEditor(bug cache.BugCacher) error {
}
if err == input.ErrEmptyTitle {
- ui.errorPopup.Activate("Empty title, aborting.")
+ ui.msgPopup.Activate(msgPopupErrorTitle, "Empty title, aborting.")
} else {
err := bug.SetTitle(title)
if err != nil {