summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--go.sum7
-rw-r--r--vendor/github.com/jesseduffield/gocui/gui.go139
-rw-r--r--vendor/github.com/jesseduffield/gocui/gui_notwin.go61
-rw-r--r--vendor/github.com/jesseduffield/gocui/gui_win.go10
-rw-r--r--vendor/github.com/jesseduffield/gocui/view.go41
-rw-r--r--vendor/modules.txt2
7 files changed, 230 insertions, 32 deletions
diff --git a/go.mod b/go.mod
index 4ab3ae48a..eabf54077 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63
- github.com/jesseduffield/gocui v0.0.0-20190526022629-625842035f05
+ github.com/jesseduffield/gocui v0.3.1-0.20190908012510-092b2290ee54
github.com/jesseduffield/pty v0.0.0-20181218102224-02db52c7e406
github.com/jesseduffield/rollrus v0.0.0-20190701125922-dd028cb0bfd7
github.com/jesseduffield/termbox-go v0.0.0-20180919093808-1e272ff78dcb // indirect
diff --git a/go.sum b/go.sum
index 3b667ee61..ca84aaaa9 100644
--- a/go.sum
+++ b/go.sum
@@ -38,7 +38,7 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 h1:URgjUo+bs1KwatoNbwG0uCO4dHN4r1jsp4a5AGgHRjo=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001 h1:qC+3MHkvfCXb1cA9YDpWZ7np8tPOXZceLrW+xyqOgmk=
+github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001 h1:MFPzqpPED05pFyGjNPJEC2sXM6EHTzFyvX+0s0JoZ48=
github.com/hashicorp/go-getter v0.0.0-20180809191950-4bda8fa99001/go.mod h1:6rdJFnhkXnzGOJbvkrdv4t9nLwKcVA+tmbQeUlkIzrU=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc h1:wAa9fGALVHfjYxZuXRnmuJG2CnwRpJYOTvY6YdErAh0=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
@@ -50,10 +50,12 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
-github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63 h1:tbm85YuPi3d1LFAUr6yZyzZ4vR96ygV98rezZZ+ywbg=
+github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63 h1:Nrr/yUxNjXWYK0B3IqcFlYh1ICnesJDB4ogcfOVc5Ns=
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63/go.mod h1:fNqjRf+4XnTo2PrGN1JRb79b/BeoHwP4lU00f39SQY0=
github.com/jesseduffield/gocui v0.0.0-20190526022629-625842035f05 h1:SMWr70VU5rthPPUtWgYdHvqLLabhvWgvJ3JpkytLV1c=
github.com/jesseduffield/gocui v0.0.0-20190526022629-625842035f05/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
+github.com/jesseduffield/gocui v0.3.1-0.20190908012510-092b2290ee54 h1:zK8KCB55hNdBadw5iJll46xQL6WXEwEXbt9B+QyYswo=
+github.com/jesseduffield/gocui v0.3.1-0.20190908012510-092b2290ee54/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
github.com/jesseduffield/pty v0.0.0-20181218102224-02db52c7e406 h1:iYMH6h6SuWuBkIzRtymosE8NpSgTK0oRMfyTdVWgxzc=
github.com/jesseduffield/pty v0.0.0-20181218102224-02db52c7e406/go.mod h1:7jlS40+UhOqkZJDIG1B/H21xnuET/+fvbbnHCa8wSIo=
github.com/jesseduffield/roll v0.0.0-20190629104057-695be2e62b00 h1:+JaOkfBNYQYlGD7dgru8mCwYNEc5tRRI8mThlVANhSM=
@@ -154,7 +156,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go
index 37e46cc0f..e917b3cf0 100644
--- a/vendor/github.com/jesseduffield/gocui/gui.go
+++ b/vendor/github.com/jesseduffield/gocui/gui.go
@@ -6,6 +6,7 @@ package gocui
import (
standardErrors "errors"
+ "strings"
"time"
"github.com/go-errors/errors"
@@ -38,18 +39,26 @@ const (
Output216 = OutputMode(termbox.Output216)
)
+type tabClickHandler func(int) error
+
+type tabClickBinding struct {
+ viewName string
+ handler tabClickHandler
+}
+
// Gui represents the whole User Interface, including the views, layouts
// and keybindings.
type Gui struct {
- tbEvents chan termbox.Event
- userEvents chan userEvent
- views []*View
- currentView *View
- managers []Manager
- keybindings []*keybinding
- maxX, maxY int
- outputMode OutputMode
- stop chan struct{}
+ tbEvents chan termbox.Event
+ userEvents chan userEvent
+ views []*View
+ currentView *View
+ managers []Manager
+ keybindings []*keybinding
+ tabClickBindings []*tabClickBinding
+ maxX, maxY int
+ outputMode OutputMode
+ stop chan struct{}
// BgColor and FgColor allow to configure the background and foreground
// colors of the GUI.
@@ -84,11 +93,16 @@ type Gui struct {
// NewGui returns a new Gui object with a given output mode.
func NewGui(mode OutputMode, supportOverlaps bool) (*Gui, error) {
- if err := termbox.Init(); err != nil {
+ g := &Gui{}
+
+ var err error
+ if g.maxX, g.maxY, err = g.getTermWindowSize(); err != nil {
return nil, err
}
- g := &Gui{}
+ if err := termbox.Init(); err != nil {
+ return nil, err
+ }
g.outputMode = mode
termbox.SetOutputMode(termbox.OutputMode(mode))
@@ -98,8 +112,6 @@ func NewGui(mode OutputMode, supportOverlaps bool) (*Gui, error) {
g.tbEvents = make(chan termbox.Event, 20)
g.userEvents = make(chan userEvent, 20)
- g.maxX, g.maxY = termbox.Size()
-
g.BgColor, g.FgColor = ColorDefault, ColorDefault
g.SelBgColor, g.SelFgColor = ColorDefault, ColorDefault
@@ -129,7 +141,8 @@ func (g *Gui) Size() (x, y int) {
// the given colors.
func (g *Gui) SetRune(x, y int, ch rune, fgColor, bgColor Attribute) error {
if x < 0 || y < 0 || x >= g.maxX || y >= g.maxY {
- return errors.New("invalid point")
+ // swallowing error because it's not that big of a deal
+ return nil
}
termbox.SetCell(x, y, ch, termbox.Attribute(fgColor), termbox.Attribute(bgColor))
return nil
@@ -232,7 +245,11 @@ func (g *Gui) ViewByPosition(x, y int) (*View, error) {
// traverse views in reverse order checking top views first
for i := len(g.views); i > 0; i-- {
v := g.views[i-1]
- if x > v.x0 && x < v.x1 && y > v.y0 && y < v.y1 {
+ frameOffset := 0
+ if v.Frame {
+ frameOffset = 1
+ }
+ if x > v.x0-frameOffset && x < v.x1+frameOffset && y > v.y0-frameOffset && y < v.y1+frameOffset {
return v, nil
}
}
@@ -320,6 +337,16 @@ func (g *Gui) DeleteKeybindings(viewname string) {
g.keybindings = s
}
+// SetTabClickBinding sets a binding for a tab click event
+func (g *Gui) SetTabClickBinding(viewName string, handler tabClickHandler) error {
+ g.tabClickBindings = append(g.tabClickBindings, &tabClickBinding{
+ viewName: viewName,
+ handler: handler,
+ })
+
+ return nil
+}
+
// getKey takes an empty interface with a key and returns the corresponding
// typed Key or rune.
func getKey(key interface{}) (Key, rune, error) {
@@ -371,6 +398,7 @@ func (g *Gui) SetManager(managers ...Manager) {
g.currentView = nil
g.views = nil
g.keybindings = nil
+ g.tabClickBindings = nil
go func() { g.tbEvents <- termbox.Event{Type: termbox.EventResize} }()
}
@@ -486,14 +514,7 @@ func (g *Gui) flush() error {
continue
}
if v.Frame {
- var fgColor, bgColor Attribute
- if g.Highlight && v == g.currentView {
- fgColor = g.SelFgColor
- bgColor = g.SelBgColor
- } else {
- fgColor = g.FgColor
- bgColor = g.BgColor
- }
+ fgColor, bgColor := g.viewColors(v)
if err := g.drawFrameEdges(v, fgColor, bgColor); err != nil {
return err
@@ -501,7 +522,7 @@ func (g *Gui) flush() error {
if err := g.drawFrameCorners(v, fgColor, bgColor); err != nil {
return err
}
- if v.Title != "" {
+ if v.Title != "" || len(v.Tabs) > 0 {
if err := g.drawTitle(v, fgColor, bgColor); err != nil {
return err
}
@@ -520,6 +541,13 @@ func (g *Gui) flush() error {
return nil
}
+func (g *Gui) viewColors(v *View) (Attribute, Attribute) {
+ if g.Highlight && v == g.currentView {
+ return g.SelFgColor, g.SelBgColor
+ }
+ return g.FgColor, g.BgColor
+}
+
// drawFrameEdges draws the horizontal and vertical edges of a view.
func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {
runeH, runeV := '─', '│'
@@ -615,17 +643,57 @@ func (g *Gui) drawTitle(v *View, fgColor, bgColor Attribute) error {
return nil
}
- for i, ch := range v.Title {
+ tabs := v.Tabs
+ separator := " - "
+ charIndex := 0
+ currentTabStart := -1
+ currentTabEnd := -1
+ if len(tabs) == 0 {
+ tabs = []string{v.Title}
+ } else {
+ for i, tab := range tabs {
+ if i == v.TabIndex {
+ currentTabStart = charIndex
+ currentTabEnd = charIndex + len(tab)
+ break
+ }
+ charIndex += len(tab)
+ if i < len(tabs)-1 {
+ charIndex += len(separator)
+ }
+ }
+ }
+
+ str := strings.Join(tabs, separator)
+
+ for i, ch := range str {
x := v.x0 + i + 2
if x < 0 {
continue
} else if x > v.x1-2 || x >= g.maxX {
break
}
- if err := g.SetRune(x, v.y0, ch, fgColor, bgColor); err != nil {
+
+ currentFgColor := fgColor
+ currentBgColor := bgColor
+ // if you are the current view and you have multiple tabs, de-highlight the non-selected tabs
+ if v == g.currentView && len(v.Tabs) > 0 {
+ currentFgColor = v.FgColor
+ currentBgColor = v.BgColor
+ }
+
+ if i >= currentTabStart && i <= currentTabEnd {
+ currentFgColor = v.SelFgColor
+ if v != g.currentView {
+ currentFgColor -= AttrBold
+ }
+ currentBgColor = v.SelBgColor
+ }
+ if err := g.SetRune(x, v.y0, ch, currentFgColor, currentBgColor); err != nil {
return err
}
}
+
return nil
}
@@ -708,6 +776,17 @@ func (g *Gui) onKey(ev *termbox.Event) error {
if err != nil {
break
}
+ if v.Frame && my == v.y0 {
+ if len(v.Tabs) > 0 {
+ tabIndex := v.GetClickedTabIndex(mx - v.x0)
+
+ for _, binding := range g.tabClickBindings {
+ if binding.viewName == v.Name() {
+ return binding.handler(tabIndex)
+ }
+ }
+ }
+ }
if err := v.SetCursor(mx-v.x0-1, my-v.y0-1); err != nil {
return err
}
@@ -723,6 +802,8 @@ func (g *Gui) onKey(ev *termbox.Event) error {
// and event. The value of matched is true if there is a match and no errors.
func (g *Gui) execKeybindings(v *View, ev *termbox.Event) (matched bool, err error) {
var globalKb *keybinding
+ var matchingParentViewKb *keybinding
+
for _, kb := range g.keybindings {
if kb.handler == nil {
continue
@@ -733,10 +814,16 @@ func (g *Gui) execKeybindings(v *View, ev *termbox.Event) (matched bool, err err
if kb.matchView(v) {
return g.execKeybinding(v, kb)
}
+ if kb.matchView(v.ParentView) {
+ matchingParentViewKb = kb
+ }
if kb.viewName == "" && ((v != nil && !v.Editable) || (kb.ch == 0 && kb.key != KeyCtrlU && kb.key != KeyCtrlA && kb.key != KeyCtrlE)) {
globalKb = kb
}
}
+ if matchingParentViewKb != nil {
+ return g.execKeybinding(v.ParentView, matchingParentViewKb)
+ }
if globalKb != nil {
return g.execKeybinding(v, globalKb)
}
diff --git a/vendor/github.com/jesseduffield/gocui/gui_notwin.go b/vendor/github.com/jesseduffield/gocui/gui_notwin.go
new file mode 100644
index 000000000..dc445b938
--- /dev/null
+++ b/vendor/github.com/jesseduffield/gocui/gui_notwin.go
@@ -0,0 +1,61 @@
+// +build !windows
+
+package gocui
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+ "unsafe"
+
+ "github.com/go-errors/errors"
+)
+
+type windowSize struct {
+ rows uint16
+ cols uint16
+ xpixels uint16
+ ypixels uint16
+}
+
+// getTermWindowSize is get terminal window size on linux or unix.
+// When gocui run inside the docker contaienr need to check and get the window size.
+func (g *Gui) getTermWindowSize() (int, int, error) {
+ out, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
+ if err != nil {
+ return 0, 0, err
+ }
+ defer out.Close()
+
+ signalCh := make(chan os.Signal, 1)
+ signal.Notify(signalCh, syscall.SIGWINCH, syscall.SIGINT)
+ defer signal.Stop(signalCh)
+
+ var sz windowSize
+
+ for {
+ _, _, err = syscall.Syscall(
+ syscall.SYS_IOCTL,
+ out.Fd(),
+ uintptr(syscall.TIOCGWINSZ),
+ uintptr(unsafe.Pointer(&sz)),
+ )
+
+ // check terminal window size
+ if sz.cols > 0 && sz.rows > 0 {
+ return int(sz.cols), int(sz.rows), nil
+ }
+
+ select {
+ case signal := <-signalCh:
+ switch signal {
+ // when the terminal window size is changed
+ case syscall.SIGWINCH:
+ continue
+ // ctrl + c to cancel
+ case syscall.SIGINT:
+ return 0, 0, errors.New("There was not enough window space to start the application")
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/jesseduffield/gocui/gui_win.go b/vendor/github.com/jesseduffield/gocui/gui_win.go
new file mode 100644
index 000000000..2a19775e7
--- /dev/null
+++ b/vendor/github.com/jesseduffield/gocui/gui_win.go
@@ -0,0 +1,10 @@
+// +build windows
+
+package gocui
+
+import "github.com/jesseduffield/termbox-go"
+
+func (g *Gui) getTermWindowSize() (int, int, error) {
+ x, y := termbox.Size()
+ return x, y, nil
+}
diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go
index 9d6553cbc..35ffa71ba 100644
--- a/vendor/github.com/jesseduffield/gocui/view.go
+++ b/vendor/github.com/jesseduffield/gocui/view.go
@@ -80,6 +80,9 @@ type View struct {
// If Frame is true, Title allows to configure a title for the view.
Title string
+ Tabs []string
+ TabIndex int
+
// If Frame is true, Subtitle allows to configure a subtitle for the view.
Subtitle string
@@ -94,6 +97,12 @@ type View struct {
HasLoader bool
writeMutex sync.Mutex
+
+ // IgnoreCarriageReturns tells us whether to ignore '\r' characters
+ IgnoreCarriageReturns bool
+
+ // ParentView is the view which catches events bubbled up from the given view if there's no matching handler
+ ParentView *View
}
type viewLine struct {
@@ -190,7 +199,7 @@ func (v *View) setRune(x, y int, ch rune, fgColor, bgColor Attribute) error {
func (v *View) SetCursor(x, y int) error {
maxX, maxY := v.Size()
if x < 0 || x >= maxX || y < 0 || y >= maxY {
- return errors.New("invalid point")
+ return nil
}
v.cx = x
v.cy = y
@@ -235,6 +244,9 @@ func (v *View) Write(p []byte) (n int, err error) {
case '\n':
v.lines = append(v.lines, nil)
case '\r':
+ if v.IgnoreCarriageReturns {
+ continue
+ }
nl := len(v.lines)
if nl > 0 {
v.lines[nl-1] = nil
@@ -421,7 +433,11 @@ func (v *View) realPosition(vx, vy int) (x, y int, err error) {
// Clear empties the view's internal buffer.
func (v *View) Clear() {
+ v.writeMutex.Lock()
+ defer v.writeMutex.Unlock()
+
v.tainted = true
+ v.ei.reset()
v.lines = nil
v.viewLines = nil
@@ -470,10 +486,16 @@ func (v *View) ViewBufferLines() []string {
return lines
}
+// LinesHeight is the count of view lines (i.e. lines excluding wrapping)
func (v *View) LinesHeight() int {
return len(v.lines)
}
+// ViewLinesHeight is the count of view lines (i.e. lines including wrapping)
+func (v *View) ViewLinesHeight() int {
+ return len(v.viewLines)
+}
+
// ViewBuffer returns a string with the contents of the view's buffer that is
// shown to the user.
func (v *View) ViewBuffer() string {
@@ -614,3 +636,20 @@ func Loader() cell {
func (v *View) IsTainted() bool {
return v.tainted
}
+
+// GetClickedTabIndex tells us which tab was clicked
+func (v *View) GetClickedTabIndex(x int) int {
+ if len(v.Tabs) <= 1 {
+ return 0
+ }
+
+ charIndex := 0
+ for i, tab := range v.Tabs {
+ charIndex += len(tab + " - ")
+ if x < charIndex {
+ return i
+ }
+ }
+
+ return 0
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index b32bf9709..9a8f42fe9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -76,7 +76,7 @@ github.com/hashicorp/hcl/json/token
github.com/jbenet/go-context/io
# github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63
github.com/jesseduffield/go-getter
-# github.com/jesseduffield/gocui v0.0.0-20190526022629-625842035f05
+# github.com/jesseduffield/gocui v0.3.1-0.20190908012510-092b2290ee54
github.com/jesseduffield/gocui
# github.com/jesseduffield/pty v0.0.0-20181218102224-02db52c7e406
github.com/jesseduffield/pty