git-bug/termui/termui.go

155 lines
2.5 KiB
Go
Raw Normal View History

2018-07-30 18:00:10 +03:00
package termui
import (
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/input"
2018-07-30 18:00:10 +03:00
"github.com/MichaelMure/git-bug/repository"
"github.com/jroimartin/gocui"
"github.com/pkg/errors"
2018-07-30 18:00:10 +03:00
)
var errTerminateMainloop = errors.New("terminate gocui mainloop")
2018-07-30 18:00:10 +03:00
type termUI struct {
g *gocui.Gui
gError chan error
cache cache.RepoCacher
activeWindow window
2018-07-30 18:00:10 +03:00
bugTable *bugTable
}
var ui *termUI
type window interface {
keybindings(g *gocui.Gui) error
layout(g *gocui.Gui) error
}
2018-07-30 18:00:10 +03:00
func Run(repo repository.Repo) error {
c := cache.NewRepoCache(repo)
ui = &termUI{
gError: make(chan error, 1),
2018-07-30 18:00:10 +03:00
cache: c,
bugTable: newBugTable(c),
}
ui.activeWindow = ui.bugTable
initGui()
err := <-ui.gError
if err != nil && err != gocui.ErrQuit {
return err
}
return nil
}
func initGui() {
2018-07-30 18:00:10 +03:00
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
ui.gError <- err
return
2018-07-30 18:00:10 +03:00
}
ui.g = g
2018-07-30 18:00:10 +03:00
ui.g.SetManagerFunc(layout)
2018-07-30 18:00:10 +03:00
err = keybindings(ui.g)
2018-07-30 18:00:10 +03:00
if err != nil {
ui.g.Close()
ui.gError <- err
return
2018-07-30 18:00:10 +03:00
}
err = g.MainLoop()
if err != nil && err != errTerminateMainloop {
ui.g.Close()
ui.gError <- err
2018-07-30 18:00:10 +03:00
}
return
2018-07-30 18:00:10 +03:00
}
func layout(g *gocui.Gui) error {
//maxX, maxY := g.Size()
g.Cursor = false
2018-07-30 18:00:10 +03:00
if err := ui.activeWindow.layout(g); err != nil {
2018-07-30 18:00:10 +03:00
return err
}
return nil
}
func keybindings(g *gocui.Gui) error {
// Quit
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
2018-07-30 18:00:10 +03:00
return err
}
if err := ui.bugTable.keybindings(g); err != nil {
return err
}
2018-07-30 18:00:10 +03:00
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func newBugWithEditor(g *gocui.Gui, v *gocui.View) error {
// This is somewhat hacky.
// As there is no way to pause gocui, run the editor, restart gocui,
// we have to stop it entirely and start a new one later.
//
// - an error channel is used to route the returned error of this new
// instance into the original launch function
// - a custom error (errTerminateMainloop) is used to terminate the original
// instance's mainLoop. This error is then filtered.
2018-07-30 18:00:10 +03:00
ui.g.Close()
2018-07-30 18:00:10 +03:00
title, message, err := input.BugCreateEditorInput(ui.cache.Repository(), "", "")
2018-07-30 18:00:10 +03:00
if err == input.ErrEmptyTitle {
// TODO: display proper error
return err
}
2018-07-30 18:00:10 +03:00
if err != nil {
return err
}
_, err = ui.cache.NewBug(title, message)
2018-07-30 18:00:10 +03:00
if err != nil {
return err
}
initGui()
return errTerminateMainloop
2018-07-30 18:00:10 +03:00
}
func maxInt(a, b int) int {
if a > b {
return a
}
return b
}
func minInt(a, b int) int {
if a > b {
return b
}
return a
}