diff --git a/Gopkg.lock b/Gopkg.lock index bc65dc14d..0a050a548 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -197,11 +197,11 @@ [[projects]] branch = "master" - digest = "1:a783e08c25b01d2b1b447469bc6e80a666ddac91087fb286864a81c34d9da99d" + digest = "1:b44cde97053119000e1295929118f935a59787e41c1b4b7db8e7bfdb11db5be1" name = "github.com/jesseduffield/gocui" packages = ["."] pruneopts = "NUT" - revision = "985c2f8d59e55de7e78b1ecf72277041df7dd44d" + revision = "e70eea43593b15d0f70e802771b871c08dacd5ee" [[projects]] branch = "master" diff --git a/go.mod b/go.mod index 505827242..f06e2edec 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/heroku/rollrus v0.0.0-20180515183152-fc0cef2ff331 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63 - github.com/jesseduffield/gocui v0.0.0-20190211105959-985c2f8d59e5 + github.com/jesseduffield/gocui v0.0.0-20190215095146-e70eea43593b github.com/jesseduffield/pty v0.0.0-20181218102224-02db52c7e406 github.com/jesseduffield/termbox-go v0.0.0-20180919093808-1e272ff78dcb github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go index a50d0c522..41599a9be 100644 --- a/vendor/github.com/jesseduffield/gocui/gui.go +++ b/vendor/github.com/jesseduffield/gocui/gui.go @@ -5,6 +5,9 @@ package gocui import ( + standardErrors "errors" + "time" + "github.com/go-errors/errors" "github.com/jesseduffield/termbox-go" @@ -12,10 +15,10 @@ import ( var ( // ErrQuit is used to decide if the MainLoop finished successfully. - ErrQuit = errors.New("quit") + ErrQuit = standardErrors.New("quit") // ErrUnknownView allows to assert if a View must be initialized. - ErrUnknownView = errors.New("unknown view") + ErrUnknownView = standardErrors.New("unknown view") ) // OutputMode represents the terminal's output mode (8 or 256 colors). @@ -163,7 +166,7 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er v.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor v.Overlaps = overlaps g.views = append(g.views, v) - return v, ErrUnknownView + return v, errors.Wrap(ErrUnknownView, 0) } // SetViewOnTop sets the given view on top of the existing ones. @@ -175,7 +178,7 @@ func (g *Gui) SetViewOnTop(name string) (*View, error) { return v, nil } } - return nil, ErrUnknownView + return nil, errors.Wrap(ErrUnknownView, 0) } // SetViewOnBottom sets the given view on bottom of the existing ones. @@ -187,7 +190,7 @@ func (g *Gui) SetViewOnBottom(name string) (*View, error) { return v, nil } } - return nil, ErrUnknownView + return nil, errors.Wrap(ErrUnknownView, 0) } // Views returns all the views in the GUI. @@ -203,7 +206,7 @@ func (g *Gui) View(name string) (*View, error) { return v, nil } } - return nil, ErrUnknownView + return nil, errors.Wrap(ErrUnknownView, 0) } // ViewByPosition returns a pointer to a view matching the given position, or @@ -216,7 +219,7 @@ func (g *Gui) ViewByPosition(x, y int) (*View, error) { return v, nil } } - return nil, ErrUnknownView + return nil, errors.Wrap(ErrUnknownView, 0) } // ViewPosition returns the coordinates of the view with the given name, or @@ -227,7 +230,7 @@ func (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error) { return v.x0, v.y0, v.x1, v.y1, nil } } - return 0, 0, 0, 0, ErrUnknownView + return 0, 0, 0, 0, errors.Wrap(ErrUnknownView, 0) } // DeleteView deletes a view by name. @@ -238,7 +241,7 @@ func (g *Gui) DeleteView(name string) error { return nil } } - return ErrUnknownView + return errors.Wrap(ErrUnknownView, 0) } // SetCurrentView gives the focus to a given view. @@ -249,7 +252,7 @@ func (g *Gui) SetCurrentView(name string) (*View, error) { return v, nil } } - return nil, ErrUnknownView + return nil, errors.Wrap(ErrUnknownView, 0) } // CurrentView returns the currently focused view, or nil if no view @@ -364,6 +367,7 @@ func (g *Gui) SetManagerFunc(manager func(*Gui) error) { // MainLoop runs the main loop until an error is returned. A successful // finish should return ErrQuit. func (g *Gui) MainLoop() error { + g.loaderTick() if err := g.flush(); err != nil { return err } @@ -705,3 +709,16 @@ func (g *Gui) execKeybinding(v *View, kb *keybinding) (bool, error) { } return true, nil } + +func (g *Gui) loaderTick() { + go func() { + for range time.Tick(time.Millisecond) { + for _, view := range g.Views() { + if view.HasLoader { + g.userEvents <- userEvent{func(g *Gui) error { return nil }} + break + } + } + } + }() +} diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go index f691960b4..7cf632c84 100644 --- a/vendor/github.com/jesseduffield/gocui/view.go +++ b/vendor/github.com/jesseduffield/gocui/view.go @@ -8,6 +8,7 @@ import ( "bytes" "io" "strings" + "time" "github.com/go-errors/errors" @@ -87,6 +88,9 @@ type View struct { // Overlaps describes which edges are overlapping with another view's edges Overlaps byte + + // If HasLoader is true, the message will be appended with a spinning loader animation + HasLoader bool } type viewLine struct { @@ -322,7 +326,11 @@ func (v *View) draw() error { } if v.tainted { v.viewLines = nil - for i, line := range v.lines { + lines := v.lines + if v.HasLoader { + lines = v.loaderLines() + } + for i, line := range lines { wrap := 0 if v.Wrap { wrap = maxX @@ -334,7 +342,9 @@ func (v *View) draw() error { v.viewLines = append(v.viewLines, vline) } } - v.tainted = false + if !v.HasLoader { + v.tainted = false + } } if v.Autoscroll && len(v.viewLines) > maxY { @@ -564,3 +574,32 @@ func linesToString(lines [][]cell) string { return strings.Join(str, "\n") } + +func (v *View) loaderLines() [][]cell { + duplicate := make([][]cell, len(v.lines)) + for i := range v.lines { + if i < len(v.lines)-1 { + duplicate[i] = make([]cell, len(v.lines[i])) + copy(duplicate[i], v.lines[i]) + } else { + duplicate[i] = make([]cell, len(v.lines[i])+2) + copy(duplicate[i], v.lines[i]) + duplicate[i][len(duplicate[i])-2] = cell{chr: ' '} + duplicate[i][len(duplicate[i])-1] = Loader() + } + } + + return duplicate +} + +func Loader() cell { + characters := "|/-\\" + now := time.Now() + nanos := now.UnixNano() + index := nanos / 50000000 % int64(len(characters)) + str := characters[index : index+1] + chr := []rune(str)[0] + return cell{ + chr: chr, + } +}