Port to termui 2.0
This commit is contained in:
parent
b73fe56e94
commit
2e48524cc9
10
README.md
10
README.md
|
@ -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
7
go.mod
|
@ -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
12
go.sum
|
@ -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
102
main.go
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user