Port to termui 2.0

This commit is contained in:
Caleb Bassi 2018-12-31 16:55:50 -08:00
parent b73fe56e94
commit 2e48524cc9
14 changed files with 220 additions and 182 deletions

View File

@ -113,11 +113,11 @@ This will place the built packages into the `dist` folder.
## Built With
- [cjbassi/termui](https://github.com/cjbassi/termui)
- [drawille-go](https://github.com/exrook/drawille-go)
- [termbox](https://github.com/nsf/termbox-go)
- [gopsutil](https://github.com/shirou/gopsutil)
- [goreleaser](https://github.com/goreleaser/goreleaser)
- [gizak/termui](https://github.com/gizak/termui)
- [nsf/termbox](https://github.com/nsf/termbox-go)
- [exrook/drawille-go](https://github.com/exrook/drawille-go)
- [shirou/gopsutil](https://github.com/shirou/gopsutil)
- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
## Stargazers over time

7
go.mod
View File

@ -3,14 +3,11 @@ module github.com/cjbassi/gotop
require (
github.com/ProtonMail/go-appdir v0.0.0-20180220133335-7c788d1b45c6
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd // indirect
github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c
github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815
github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/mattn/go-runewidth v0.0.2 // indirect
github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shirou/gopsutil v2.18.11+incompatible
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect

12
go.sum
View File

@ -4,20 +4,20 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIO
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd h1:nSJpATLVvFa19BEHX4ys+VGNWfI4FUGMweEI6QXs8wg=
github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd/go.mod h1:vjcQJUZJYD3MeVGhtZXSMnCHfUNZxsyYzJt90eCYxK4=
github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c h1:vcaCtK8ObawtpQRW8GdbKZ+eJGEUn41xJ8Snagd/c6I=
github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c/go.mod h1:rqXckrwz+i0fH/zNwU6AdBNULHwmZsgehnSlhKP5i2Q=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 h1:HMAfwOa33y82IaQEKQDfUCiwNlxtM1iw7HLM9ru0RNc=
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:l7JNRynTRuqe45tpIyItHNqZWTxywYjp87MWTOnU5cg=
github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480 h1:+NHS7QUnQqEwIuhrHaFT6R78LMGbja4fYTu6wny7Q4s=
github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480/go.mod h1:S3xz8JHXNDPSNFsvXCdG7bHlEGrwvUG3a0joR/xYZ5M=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e h1:w2JDz0jtOlFFdvtUXISyYPFwmbZnwKL1mRDT0tKDvuk=
github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/nsf/termbox-go v0.0.0-20180613055208-5c94acc5e6eb h1:YahEjAGkJtCrkqgVHhX6n8ZX+CZ3hDRL9fjLYugLfSs=
github.com/nsf/termbox-go v0.0.0-20180613055208-5c94acc5e6eb/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v2.18.11+incompatible h1:PMFTKnFTr/YTRW5rbLK4vWALV3a+IGXse5nvhSjztmg=

102
main.go
View File

@ -18,8 +18,8 @@ import (
"github.com/cjbassi/gotop/colorschemes"
"github.com/cjbassi/gotop/src/logging"
w "github.com/cjbassi/gotop/src/widgets"
ui "github.com/cjbassi/termui"
docopt "github.com/docopt/docopt.go"
ui "github.com/gizak/termui"
)
var version = "1.7.1"
@ -38,6 +38,8 @@ var (
configDir = appdir.New("gotop").UserConfig()
logPath = filepath.Join(configDir, "errors.log")
stderrLogger = log.New(os.Stderr, "", 0)
termWidth int
termHeight int
cpu *w.CPU
mem *w.Mem
@ -46,6 +48,7 @@ var (
disk *w.Disk
temp *w.Temp
help *w.HelpMenu
grid *ui.Grid
)
func cliArguments() error {
@ -137,41 +140,46 @@ func getCustomColorscheme(name string) (colorschemes.Colorscheme, error) {
}
func setupGrid() {
ui.Body.Cols = 12
ui.Body.Rows = 12
grid = ui.NewGrid()
grid.SetRect(0, 0, termWidth, termHeight)
if minimal {
ui.Body.Set(0, 0, 12, 6, cpu)
ui.Body.Set(0, 6, 6, 12, mem)
ui.Body.Set(6, 6, 12, 12, proc)
grid.Set(
ui.NewRow(1.0/2, cpu),
ui.NewRow(1.0/2,
ui.NewCol(1.0/2, mem),
ui.NewCol(1.0/2, proc),
),
)
} else {
ui.Body.Set(0, 0, 12, 4, cpu)
ui.Body.Set(0, 4, 4, 6, disk)
ui.Body.Set(0, 6, 4, 8, temp)
ui.Body.Set(4, 4, 12, 8, mem)
ui.Body.Set(0, 8, 6, 12, net)
ui.Body.Set(6, 8, 12, 12, proc)
grid.Set(
ui.NewRow(1.0/3, cpu),
ui.NewRow(1.0/3,
ui.NewCol(1.0/3,
ui.NewRow(1.0/2, disk),
ui.NewRow(1.0/2, temp),
),
ui.NewCol(2.0/3, mem),
),
ui.NewRow(1.0/3,
ui.NewCol(1.0/2, net),
ui.NewCol(1.0/2, proc),
),
)
}
}
func termuiColors() {
ui.Theme.Fg = ui.Color(colorscheme.Fg)
ui.Theme.Bg = ui.Color(colorscheme.Bg)
ui.Theme.LabelFg = ui.Color(colorscheme.BorderLabel)
ui.Theme.LabelBg = ui.Color(colorscheme.Bg)
ui.Theme.BorderFg = ui.Color(colorscheme.BorderLine)
ui.Theme.BorderBg = ui.Color(colorscheme.Bg)
ui.Theme.TableCursor = ui.Color(colorscheme.ProcCursor)
ui.Theme.Sparkline = ui.Color(colorscheme.Sparkline)
ui.Theme.GaugeColor = ui.Color(colorscheme.DiskBar)
ui.Theme.Default = ui.AttrPair{ui.Attribute(colorscheme.Fg), ui.Attribute(colorscheme.Bg)}
ui.Theme.Block.Title = ui.AttrPair{ui.Attribute(colorscheme.BorderLabel), ui.Attribute(colorscheme.Bg)}
ui.Theme.Block.Border = ui.AttrPair{ui.Attribute(colorscheme.BorderLine), ui.Attribute(colorscheme.Bg)}
}
func widgetColors() {
mem.LineColor["Main"] = ui.Color(colorscheme.MainMem)
mem.LineColor["Swap"] = ui.Color(colorscheme.SwapMem)
mem.LineColor["Main"] = ui.Attribute(colorscheme.MainMem)
mem.LineColor["Swap"] = ui.Attribute(colorscheme.SwapMem)
proc.CursorColor = ui.Attribute(colorscheme.ProcCursor)
var keys []string
for key := range cpu.Data {
@ -185,13 +193,18 @@ func widgetColors() {
i = 0
}
c := colorscheme.CPULines[i]
cpu.LineColor[v] = ui.Color(c)
cpu.LineColor[v] = ui.Attribute(c)
i++
}
if !minimal {
temp.TempLow = ui.Color(colorscheme.TempLow)
temp.TempHigh = ui.Color(colorscheme.TempHigh)
temp.TempLow = ui.Attribute(colorscheme.TempLow)
temp.TempHigh = ui.Attribute(colorscheme.TempHigh)
net.Lines[0].LineColor = ui.Attribute(colorscheme.Sparkline)
net.Lines[0].TitleColor = ui.Attribute(colorscheme.BorderLabel)
net.Lines[1].LineColor = ui.Attribute(colorscheme.Sparkline)
net.Lines[1].TitleColor = ui.Attribute(colorscheme.BorderLabel)
}
}
@ -246,7 +259,7 @@ func eventLoop() {
return
case <-drawTicker:
if !helpVisible {
ui.Render(ui.Body)
ui.Render(grid)
}
case e := <-uiEvents:
switch e.ID {
@ -258,7 +271,7 @@ func eventLoop() {
ui.Clear()
ui.Render(help)
} else {
ui.Render(ui.Body)
ui.Render(grid)
}
case "h":
if !helpVisible {
@ -279,27 +292,27 @@ func eventLoop() {
case "<Escape>":
if helpVisible {
helpVisible = false
ui.Render(ui.Body)
ui.Render(grid)
}
case "<Resize>":
payload := e.Payload.(ui.Resize)
ui.Body.Width, ui.Body.Height = payload.Width, payload.Height
ui.Body.Resize()
grid.SetRect(0, 0, payload.Width, payload.Height)
help.Resize(payload.Width, payload.Height)
ui.Clear()
if helpVisible {
ui.Render(help)
} else {
ui.Render(ui.Body)
ui.Render(grid)
}
case "<MouseLeft>":
payload := e.Payload.(ui.Mouse)
proc.Click(payload.X, payload.Y)
ui.Render(proc)
case "<MouseWheelUp>", "<Up>", "k":
case "k", "<Up>", "<MouseWheelUp>":
proc.Up()
ui.Render(proc)
case "<MouseWheelDown>", "<Down>", "j":
case "j", "<Down>", "<MouseWheelDown>":
proc.Down()
ui.Render(proc)
case "g", "<Home>":
@ -373,11 +386,6 @@ func main() {
stderrLogger.Fatalf("failed to parse cli args: %v", err)
}
termuiColors() // need to do this before initializing widgets so that they can inherit the colors
initWidgets()
widgetColors()
help = w.NewHelpMenu()
if err := ui.Init(); err != nil {
stderrLogger.Fatalf("failed to initialize termui: %v", err)
}
@ -385,8 +393,16 @@ func main() {
logging.StderrToLogfile(lf)
termWidth, termHeight = ui.TerminalSize()
termuiColors() // need to do this before initializing widgets so that they can inherit the colors
initWidgets()
widgetColors()
help = w.NewHelpMenu()
help.Resize(termWidth, termHeight)
setupGrid()
ui.Render(ui.Body)
ui.Render(grid)
eventLoop()
}

View File

@ -1,20 +1,22 @@
package termui
import (
"image"
"sort"
drawille "github.com/cjbassi/drawille-go"
. "github.com/gizak/termui"
)
// LineGraph implements a line graph of data points.
type LineGraph struct {
*Block
Data map[string][]float64
LineColor map[string]Color
LineColor map[string]Attribute
Zoom int
Labels map[string]string
DefaultLineColor Color
DefaultLineColor Attribute
}
// NewLineGraph returns a new LineGraph with current theme.
@ -22,24 +24,22 @@ func NewLineGraph() *LineGraph {
return &LineGraph{
Block: NewBlock(),
Data: make(map[string][]float64),
LineColor: make(map[string]Color),
LineColor: make(map[string]Attribute),
Labels: make(map[string]string),
Zoom: 5,
DefaultLineColor: Theme.LineGraph,
}
}
// Buffer implements Bufferer interface.
func (self *LineGraph) Buffer() *Buffer {
buf := self.Block.Buffer()
func (self *LineGraph) Draw(buf *Buffer) {
self.Block.Draw(buf)
// we render each data point on to the canvas then copy over the braille to the buffer at the end
// fyi braille characters have 2x4 dots for each character
c := drawille.NewCanvas()
// used to keep track of the braille colors until the end when we render the braille to the buffer
colors := make([][]Color, self.X+2)
colors := make([][]Attribute, self.Inner.Dx()+2)
for i := range colors {
colors[i] = make([]Color, self.Y+2)
colors[i] = make([]Attribute, self.Inner.Dy()+2)
}
// sort the series so that overlapping data will overlap the same way each time
@ -64,8 +64,8 @@ func (self *LineGraph) Buffer() *Buffer {
lastY, lastX := -1, -1
// assign colors to `colors` and lines/points to the canvas
for i := len(seriesData) - 1; i >= 0; i-- {
x := ((self.X + 1) * 2) - 1 - (((len(seriesData) - 1) - i) * self.Zoom)
y := ((self.Y + 1) * 4) - 1 - int((float64((self.Y)*4)-1)*(seriesData[i]/100))
x := ((self.Inner.Dx() + 1) * 2) - 1 - (((len(seriesData) - 1) - i) * self.Zoom)
y := ((self.Inner.Dy() + 1) * 4) - 1 - int((float64((self.Inner.Dy())*4)-1)*(seriesData[i]/100))
if x < 0 {
// render the line to the last point up to the wall
if x > 0-self.Zoom {
@ -98,7 +98,10 @@ func (self *LineGraph) Buffer() *Buffer {
continue
}
if char != 10240 { // empty braille character
buf.SetCell(x, y, Cell{char, colors[x][y], self.Bg})
buf.SetCell(
Cell{char, AttrPair{colors[x][y], -1}},
image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+y-1),
)
}
}
}
@ -106,7 +109,7 @@ func (self *LineGraph) Buffer() *Buffer {
// renders key/label ontop
for i, seriesName := range seriesList {
if i+2 > self.Y {
if i+2 > self.Inner.Dy() {
continue
}
seriesLineColor, ok := self.LineColor[seriesName]
@ -118,11 +121,12 @@ func (self *LineGraph) Buffer() *Buffer {
str := seriesName + " " + self.Labels[seriesName]
for k, char := range str {
if char != ' ' {
buf.SetCell(3+k, i+2, Cell{char, seriesLineColor, self.Bg})
buf.SetCell(
Cell{char, AttrPair{seriesLineColor, -1}},
image.Pt(self.Inner.Min.X+2+k, self.Inner.Min.Y+i+1),
)
}
}
}
return buf
}

View File

@ -1,7 +1,9 @@
package termui
import (
"fmt"
"image"
. "github.com/gizak/termui"
)
var SPARKS = [8]rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}
@ -11,8 +13,8 @@ type Sparkline struct {
Data []int
Title1 string
Title2 string
TitleColor Color
LineColor Color
TitleColor Attribute
LineColor Attribute
}
// Sparklines is a renderable widget which groups together the given sparklines.
@ -28,10 +30,7 @@ func (self *Sparklines) Add(sl Sparkline) {
// NewSparkline returns an unrenderable single sparkline that intended to be added into a Sparklines.
func NewSparkline() *Sparkline {
return &Sparkline{
TitleColor: Theme.Fg,
LineColor: Theme.Sparkline,
}
return &Sparkline{}
}
// NewSparklines return a new *Sparklines with given Sparklines, you can always add a new Sparkline later.
@ -43,8 +42,8 @@ func NewSparklines(ss ...*Sparkline) *Sparklines {
}
// Buffer implements Bufferer interface.
func (self *Sparklines) Buffer() *Buffer {
buf := self.Block.Buffer()
func (self *Sparklines) Draw(buf *Buffer) {
self.Block.Draw(buf)
lc := len(self.Lines) // lineCount
@ -52,48 +51,46 @@ func (self *Sparklines) Buffer() *Buffer {
for i, line := range self.Lines {
// prints titles
title1Y := 2 + (self.Y/lc)*i
title2Y := (2 + (self.Y/lc)*i) + 1
title1 := MaxString(line.Title1, self.X)
title2 := MaxString(line.Title2, self.X)
buf.SetString(1, title1Y, title1, line.TitleColor|AttrBold, self.Bg)
buf.SetString(1, title2Y, title2, line.TitleColor|AttrBold, self.Bg)
title1Y := 2 + (self.Inner.Dy()/lc)*i
title2Y := (2 + (self.Inner.Dy()/lc)*i) + 1
title1 := TrimString(line.Title1, self.Inner.Dx())
title2 := TrimString(line.Title2, self.Inner.Dx())
buf.SetString(
title1,
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+title1Y-1),
AttrPair{line.TitleColor | AttrBold, -1},
)
buf.SetString(
title2,
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+title2Y-1),
AttrPair{line.TitleColor | AttrBold, -1},
)
sparkY := (self.Y / lc) * (i + 1)
sparkY := (self.Inner.Dy() / lc) * (i + 1)
// finds max data in current view used for relative heights
max := 1
for i := len(line.Data) - 1; i >= 0 && self.X-((len(line.Data)-1)-i) >= 1; i-- {
for i := len(line.Data) - 1; i >= 0 && self.Inner.Dx()-((len(line.Data)-1)-i) >= 1; i-- {
if line.Data[i] > max {
max = line.Data[i]
}
}
// prints sparkline
for x := self.X; x >= 1; x-- {
for x := self.Inner.Dx(); x >= 1; x-- {
char := SPARKS[0]
if (self.X - x) < len(line.Data) {
offset := self.X - x
if (self.Inner.Dx() - x) < len(line.Data) {
offset := self.Inner.Dx() - x
cur_item := line.Data[(len(line.Data)-1)-offset]
percent := float64(cur_item) / float64(max)
index := int(percent * 7)
if index < 0 || index >= len(SPARKS) {
Error("sparkline",
fmt.Sprint(
"len(line.Data): ", len(line.Data), "\n",
"max: ", max, "\n",
"x: ", x, "\n",
"self.X: ", self.X, "\n",
"offset: ", offset, "\n",
"cur_item: ", cur_item, "\n",
"percent: ", percent, "\n",
"index: ", index, "\n",
"len(SPARKS): ", len(SPARKS),
))
panic("TODO")
}
char = SPARKS[index]
}
buf.SetCell(x, sparkY, Cell{char, line.LineColor, self.Bg})
buf.SetCell(
Cell{char, AttrPair{line.LineColor, -1}},
image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+sparkY-1),
)
}
}
return buf
}

View File

@ -1,8 +1,10 @@
package termui
import (
"fmt"
"image"
"strings"
. "github.com/gizak/termui"
)
// Table tracks all the attributes of a Table instance
@ -19,7 +21,7 @@ type Table struct {
PadLeft int
Cursor bool
CursorColor Color
CursorColor Attribute
UniqueCol int // the column used to identify the selected item
SelectedItem string // used to keep the cursor on the correct item if the data changes
@ -30,8 +32,8 @@ type Table struct {
// NewTable returns a new Table instance
func NewTable() *Table {
self := &Table{
Block: NewBlock(),
CursorColor: Theme.TableCursor,
Block: NewBlock(),
// CursorColor: Theme.TableCursor,
SelectedRow: 0,
TopRow: 0,
UniqueCol: 0,
@ -46,8 +48,8 @@ func (self *Table) ColResize() {
}
// Buffer implements the Bufferer interface.
func (self *Table) Buffer() *Buffer {
buf := self.Block.Buffer()
func (self *Table) Draw(buf *Buffer) {
self.Block.Draw(buf)
self.ColResizer()
@ -67,28 +69,26 @@ func (self *Table) Buffer() *Buffer {
continue
}
// don't render column if it doesn't fit in widget
if width > (self.X-self.CellXPos[i])+1 {
if width > (self.Inner.Dx()-self.CellXPos[i])+1 {
continue
}
buf.SetString(self.CellXPos[i], 1, h, self.Fg|AttrBold, self.Bg)
buf.SetString(
h,
image.Pt(self.Inner.Min.X+self.CellXPos[i]-1, self.Inner.Min.Y),
AttrPair{Theme.Default.Fg | AttrBold, -1},
)
}
// prints each row
for rowNum := self.TopRow; rowNum < self.TopRow+self.Y-1 && rowNum < len(self.Rows); rowNum++ {
for rowNum := self.TopRow; rowNum < self.TopRow+self.Inner.Dy()-1 && rowNum < len(self.Rows); rowNum++ {
if rowNum < 0 || rowNum >= len(self.Rows) {
Error("table rows",
fmt.Sprint(
"rowNum: ", rowNum, "\n",
"self.TopRow: ", self.TopRow, "\n",
"len(self.Rows): ", len(self.Rows), "\n",
"self.Y: ", self.Y,
))
panic("TODO")
}
row := self.Rows[rowNum]
y := (rowNum + 2) - self.TopRow
// prints cursor
fg := self.Fg
fg := Theme.Default.Fg
if self.Cursor {
if (self.SelectedItem == "" && rowNum == self.SelectedRow) || (self.SelectedItem != "" && self.SelectedItem == row[self.UniqueCol]) {
fg = self.CursorColor | AttrReverse
@ -96,7 +96,11 @@ func (self *Table) Buffer() *Buffer {
if width == 0 {
continue
}
buf.SetString(1, y, strings.Repeat(" ", self.X), fg, self.Bg)
buf.SetString(
strings.Repeat(" ", self.Inner.Dx()),
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y-1),
AttrPair{fg, -1},
)
}
self.SelectedItem = row[self.UniqueCol]
self.SelectedRow = rowNum
@ -109,15 +113,17 @@ func (self *Table) Buffer() *Buffer {
continue
}
// don't render column if width is greater than distance to end of widget
if width > (self.X-self.CellXPos[i])+1 {
if width > (self.Inner.Dx()-self.CellXPos[i])+1 {
continue
}
r := MaxString(row[i], width)
buf.SetString(self.CellXPos[i], y, r, fg, self.Bg)
r := TrimString(row[i], width)
buf.SetString(
r,
image.Pt(self.Inner.Min.X+self.CellXPos[i]-1, self.Inner.Min.Y+y-1),
AttrPair{fg, -1},
)
}
}
return buf
}
/////////////////////////////////////////////////////////////////////////////////
@ -138,8 +144,8 @@ func (self *Table) calcPos() {
if self.SelectedRow > len(self.Rows)-1 {
self.SelectedRow = len(self.Rows) - 1
}
if self.SelectedRow > self.TopRow+(self.Y-2) {
self.TopRow = self.SelectedRow - (self.Y - 2)
if self.SelectedRow > self.TopRow+(self.Inner.Dy()-2) {
self.TopRow = self.SelectedRow - (self.Inner.Dy() - 2)
}
}
@ -166,29 +172,29 @@ func (self *Table) Bottom() {
// The number of lines in a page is equal to the height of the widgeself.
func (self *Table) HalfPageUp() {
self.SelectedRow = self.SelectedRow - (self.Y-2)/2
self.SelectedRow = self.SelectedRow - (self.Inner.Dy()-2)/2
self.calcPos()
}
func (self *Table) HalfPageDown() {
self.SelectedRow = self.SelectedRow + (self.Y-2)/2
self.SelectedRow = self.SelectedRow + (self.Inner.Dy()-2)/2
self.calcPos()
}
func (self *Table) PageUp() {
self.SelectedRow -= (self.Y - 2)
self.SelectedRow -= (self.Inner.Dy() - 2)
self.calcPos()
}
func (self *Table) PageDown() {
self.SelectedRow += (self.Y - 2)
self.SelectedRow += (self.Inner.Dy() - 2)
self.calcPos()
}
func (self *Table) Click(x, y int) {
x = x - self.XOffset
y = y - self.YOffset
if (x > 0 && x <= self.X) && (y > 0 && y <= self.Y) {
x = x - self.Min.X
y = y - self.Min.Y
if (x > 0 && x <= self.Inner.Dx()) && (y > 0 && y <= self.Inner.Dy()) {
self.SelectedRow = (self.TopRow + y) - 2
self.calcPos()
}

View File

@ -5,7 +5,7 @@ import (
"log"
"time"
ui "github.com/cjbassi/termui"
ui "github.com/cjbassi/gotop/src/termui"
psCPU "github.com/shirou/gopsutil/cpu"
)
@ -35,7 +35,7 @@ func NewCPU(interval time.Duration, zoom int, average bool, percpu bool) *CPU {
PerCPU: percpu,
formatString: formatString,
}
self.Label = "CPU Usage"
self.Title = " CPU Usage "
self.Zoom = zoom
if !(self.Average || self.PerCPU) {

View File

@ -7,8 +7,8 @@ import (
"strings"
"time"
ui "github.com/cjbassi/gotop/src/termui"
"github.com/cjbassi/gotop/src/utils"
ui "github.com/cjbassi/termui"
psDisk "github.com/shirou/gopsutil/disk"
)
@ -35,7 +35,7 @@ func NewDisk() *Disk {
interval: time.Second,
Partitions: make(map[string]*Partition),
}
self.Label = "Disk Usage"
self.Title = " Disk Usage "
self.Header = []string{"Disk", "Mount", "Used", "Free", "R/s", "W/s"}
self.Gap = 2
self.ColResizer = self.ColResize
@ -154,8 +154,8 @@ func (self *Disk) update() {
// ColResize overrides the default ColResize in the termui table.
func (self *Disk) ColResize() {
self.ColWidths = []int{
utils.Max(4, (self.X-29)/2),
utils.Max(5, (self.X-29)/2),
utils.Max(4, (self.Inner.Dx()-29)/2),
utils.Max(5, (self.Inner.Dx()-29)/2),
4, 5, 5, 5,
}

View File

@ -1,9 +1,10 @@
package widgets
import (
"image"
"strings"
ui "github.com/cjbassi/termui"
ui "github.com/gizak/termui"
)
const KEYBINDS = `
@ -34,27 +35,33 @@ CPU and Mem graph scaling:
`
type HelpMenu struct {
*ui.Block
ui.Block
}
func NewHelpMenu() *HelpMenu {
block := ui.NewBlock()
block.X = 51 // width - 1
block.Y = 24 // height - 1
return &HelpMenu{block}
return &HelpMenu{
Block: *ui.NewBlock(),
}
}
func (self *HelpMenu) Buffer() *ui.Buffer {
buf := self.Block.Buffer()
func (self *HelpMenu) Resize(termWidth, termHeight int) {
textWidth := 53
textHeight := 22
x := (termWidth - textWidth) / 2
y := (termHeight - textHeight) / 2
self.Block.XOffset = (ui.Body.Width - self.Block.X) / 2 // X coordinate
self.Block.YOffset = (ui.Body.Height - self.Block.Y) / 2 // Y coordinate
self.Block.SetRect(x, y, textWidth+x, textHeight+y)
}
func (self *HelpMenu) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
for y, line := range strings.Split(KEYBINDS, "\n") {
for x, char := range line {
buf.SetCell(x+1, y, ui.NewCell(char, ui.Color(7), self.Bg))
buf.SetCell(
ui.Cell{char, ui.AttrPair{ui.Attribute(7), -1}},
image.Pt(self.Inner.Min.X+x, self.Inner.Min.Y+y-1),
)
}
}
return buf
}

View File

@ -5,8 +5,8 @@ import (
"log"
"time"
ui "github.com/cjbassi/gotop/src/termui"
"github.com/cjbassi/gotop/src/utils"
ui "github.com/cjbassi/termui"
psMem "github.com/shirou/gopsutil/mem"
)
@ -20,7 +20,7 @@ func NewMem(interval time.Duration, zoom int) *Mem {
LineGraph: ui.NewLineGraph(),
interval: interval,
}
self.Label = "Memory Usage"
self.Title = " Memory Usage "
self.Zoom = zoom
self.Data["Main"] = []float64{0}
self.Data["Swap"] = []float64{0}

View File

@ -5,8 +5,8 @@ import (
"log"
"time"
ui "github.com/cjbassi/gotop/src/termui"
"github.com/cjbassi/gotop/src/utils"
ui "github.com/cjbassi/termui"
psNet "github.com/shirou/gopsutil/net"
)
@ -30,7 +30,7 @@ func NewNet() *Net {
Sparklines: spark,
interval: time.Second,
}
self.Label = "Network Usage"
self.Title = " Network Usage "
self.update()

View File

@ -8,8 +8,9 @@ import (
"strconv"
"time"
ui "github.com/cjbassi/gotop/src/termui"
"github.com/cjbassi/gotop/src/utils"
ui "github.com/cjbassi/termui"
"github.com/gizak/termui"
psCPU "github.com/shirou/gopsutil/cpu"
)
@ -49,7 +50,7 @@ func NewProc() *Proc {
sortMethod: "c",
group: true,
}
self.Label = "Processes"
self.Title = " Processes "
self.ColResizer = self.ColResize
self.Cursor = true
self.Gap = 3
@ -108,11 +109,11 @@ func (self *Proc) Sort() {
// ColResize overrides the default ColResize in the termui table.
func (self *Proc) ColResize() {
self.ColWidths = []int{
5, utils.Max(self.X-26, 10), 4, 4,
5, utils.Max(self.Inner.Dx()-26, 10), 4, 4,
}
}
func (self *Proc) ChangeSort(e ui.Event) {
func (self *Proc) ChangeSort(e termui.Event) {
if self.sortMethod != e.ID {
self.sortMethod = e.ID
self.Top()

View File

@ -5,10 +5,11 @@ package widgets
import (
"fmt"
"image"
"sort"
"time"
ui "github.com/cjbassi/termui"
ui "github.com/gizak/termui"
)
type Temp struct {
@ -16,8 +17,8 @@ type Temp struct {
interval time.Duration
Data map[string]int
Threshold int
TempLow ui.Color
TempHigh ui.Color
TempLow ui.Attribute
TempHigh ui.Attribute
Fahrenheit bool
}
@ -28,7 +29,7 @@ func NewTemp(fahrenheit bool) *Temp {
Data: make(map[string]int),
Threshold: 80, // temp at which color should change
}
self.Label = "Temperatures"
self.Title = " Temperatures "
if fahrenheit {
self.Fahrenheit = true
@ -48,8 +49,8 @@ func NewTemp(fahrenheit bool) *Temp {
}
// Buffer implements ui.Bufferer interface and renders the widget.
func (self *Temp) Buffer() *ui.Buffer {
buf := self.Block.Buffer()
func (self *Temp) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
var keys []string
for key := range self.Data {
@ -58,7 +59,7 @@ func (self *Temp) Buffer() *ui.Buffer {
sort.Strings(keys)
for y, key := range keys {
if y+1 > self.Y {
if y+1 > self.Inner.Dy() {
break
}
@ -67,14 +68,23 @@ func (self *Temp) Buffer() *ui.Buffer {
fg = self.TempHigh
}
s := ui.MaxString(key, (self.X - 4))
buf.SetString(1, y+1, s, self.Fg, self.Bg)
s := ui.TrimString(key, (self.Inner.Dx() - 4))
buf.SetString(s,
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y),
ui.Theme.Default,
)
if self.Fahrenheit {
buf.SetString(self.X-3, y+1, fmt.Sprintf("%3dF", self.Data[key]), fg, self.Bg)
buf.SetString(
fmt.Sprintf("%3dF", self.Data[key]),
image.Pt(self.Inner.Dx()-3, y+1),
ui.AttrPair{fg, -1},
)
} else {
buf.SetString(self.X-3, y+1, fmt.Sprintf("%3dC", self.Data[key]), fg, self.Bg)
buf.SetString(
fmt.Sprintf("%3dC", self.Data[key]),
image.Pt(self.Inner.Max.X-4, self.Inner.Min.Y+y),
ui.AttrPair{fg, -1},
)
}
}
return buf
}