summaryrefslogtreecommitdiff
path: root/pkg/gui/gui.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/gui/gui.go')
-rw-r--r--pkg/gui/gui.go142
1 files changed, 91 insertions, 51 deletions
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 96e2c0a..55c6c18 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -2,28 +2,103 @@ package gui
import (
"github.com/isacikgoz/gitbatch/pkg/git"
- "github.com/isacikgoz/gitbatch/pkg/utils"
- "github.com/fatih/color"
"github.com/jroimartin/gocui"
"fmt"
+ "time"
+ "os"
+ "os/exec"
+ "io/ioutil"
+ "log"
)
+// SentinelErrors are the errors that have special meaning and need to be checked
+// by calling functions. The less of these, the better
+type SentinelErrors struct {
+ ErrSubProcess error
+}
+
// Gui wraps the gocui Gui object which handles rendering and events
type Gui struct {
g *gocui.Gui
- Repositories []*git.RepoEntity
+ SubProcess *exec.Cmd
+ State guiState
+ Errors SentinelErrors
+}
+
+type guiState struct {
+ Repositories []*git.RepoEntity
+ Directories []string
}
// NewGui builds a new gui handler
-func NewGui(entities []*git.RepoEntity) (*Gui, error) {
+func NewGui(directoies []string) (*Gui, error) {
+ rs, err := git.LoadRepositoryEntities(directoies)
+ if err != nil {
+ return nil, err
+ }
+ initialState := guiState{
+ Repositories: rs,
+ }
gui := &Gui{
- Repositories: entities,
+ State: initialState,
}
return gui, nil
}
+// Run setup the gui with keybindings and start the mainloop
+func (gui *Gui) Run() error {
+
+ g, err := gocui.NewGui(gocui.OutputNormal)
+ if err != nil {
+ return err
+ }
+ defer g.Close()
+
+ g.SetManagerFunc(gui.layout)
+
+ if err := gui.keybindings(g); err != nil {
+ return err
+ }
+
+ if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
+ return err
+ }
+ return nil
+}
+
+// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
+// if the error returned from a run is a ErrSubProcess, it runs the subprocess
+// otherwise it handles the error, possibly by quitting the application
+func (gui *Gui) RunWithSubprocesses() {
+ for {
+ if err := gui.Run(); err != nil {
+ if err == gocui.ErrQuit {
+ break
+ } else if err == gui.Errors.ErrSubProcess {
+ gui.SubProcess.Stdin = os.Stdin
+ gui.SubProcess.Stdout = os.Stdout
+ gui.SubProcess.Stderr = os.Stderr
+ gui.SubProcess.Run()
+ gui.SubProcess.Stdout = ioutil.Discard
+ gui.SubProcess.Stderr = ioutil.Discard
+ gui.SubProcess.Stdin = nil
+ gui.SubProcess = nil
+ } else {
+ log.Fatal(err)
+ }
+ }
+ }
+}
+
+func (gui *Gui) goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) {
+ go func() {
+ for range time.Tick(interval) {
+ function(g)
+ }
+ }()
+}
func (gui *Gui) layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
@@ -37,8 +112,8 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.SelBgColor = gocui.ColorWhite
v.SelFgColor = gocui.ColorBlack
v.Overwrite = true
- for _, r := range gui.Repositories {
- fmt.Fprintln(v, r.Name)
+ for _, r := range gui.State.Repositories {
+ fmt.Fprintln(v, r.GetDisplayString())
}
if _, err = gui.setCurrentViewOnTop(g, "main"); err != nil {
@@ -89,39 +164,11 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.BgColor = gocui.ColorWhite
v.FgColor = gocui.ColorBlack
v.Frame = false
- fmt.Fprintln(v, "q: quit ↑ ↓: navigate space: select")
+ fmt.Fprintln(v, "q: quit | ↑ ↓: navigate | space: select/deselect | a: select all | r: clear selection | enter: execute")
}
return nil
}
-func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
-
- if e, err := gui.getSelectedRepository(g, v); err != nil {
- return err
- } else {
- mainView, err := g.View("main")
- if err != nil {
- return err
- }
- if e.Marked != true {
- e.Mark()
- } else {
- e.UnMark()
- }
- mainView.Clear()
- for _, r := range gui.Repositories {
- if r.Marked {
- fmt.Fprintln(mainView, utils.ColoredString(r.Name, color.FgGreen))
- } else {
- fmt.Fprintln(mainView, r.Name)
- }
- }
- gui.updateSchedule(g)
- }
-
- return nil
-}
-
func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
@@ -133,24 +180,17 @@ func (gui *Gui) setCurrentViewOnTop(g *gocui.Gui, name string) (*gocui.View, err
return g.SetViewOnTop(name)
}
-// Run setup the gui with keybindings and start the mainloop
-func (gui *Gui) Run() error {
+func (gui *Gui) updateKeyBindingsViewForMainView(g *gocui.Gui) error {
- g, err := gocui.NewGui(gocui.OutputNormal)
+ v, err := g.View("keybindings")
if err != nil {
return err
}
- defer g.Close()
-
- g.SetManagerFunc(gui.layout)
-
- if err := gui.keybindings(g); err != nil {
- return err
- }
- if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
- return err
- }
+ v.Clear()
+ v.BgColor = gocui.ColorWhite
+ v.FgColor = gocui.ColorBlack
+ v.Frame = false
+ fmt.Fprintln(v, "q: quit | ↑ ↓: navigate | space: select/deselect | a: select all | r: clear selection | enter: execute")
return nil
-}
-
+} \ No newline at end of file