diff options
Diffstat (limited to 'pkg/gui/gui.go')
| -rw-r--r-- | pkg/gui/gui.go | 142 |
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 |
