Disable all battery code if battery not selected in options. Refactors widgetCount to localize use.
This commit is contained in:
commit
2a6a479d11
10
README.md
10
README.md
|
@ -115,11 +115,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)
|
||||
- [battery](https://github.com/distatus/battery)
|
||||
|
||||
## Stargazers over time
|
||||
|
|
11
go.mod
11
go.mod
|
@ -1,22 +1,17 @@
|
|||
module github.com/cjbassi/gotop
|
||||
|
||||
require (
|
||||
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 // indirect
|
||||
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/distatus/battery v0.0.0-20170521010419-916919eb43bd
|
||||
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815
|
||||
github.com/gizak/termui v0.0.0-20190101100649-ffdef4cb72e9
|
||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.2 // indirect
|
||||
github.com/nexulh/batmond v0.0.0-20180213215845-395ac7fdba8c // indirect
|
||||
github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443 // 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
|
||||
github.com/stretchr/testify v1.2.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 // indirect
|
||||
golang.org/x/sys v0.0.0-20180406135729-3b87a42e500a // indirect
|
||||
)
|
||||
|
|
33
go.sum
33
go.sum
|
@ -1,48 +1,35 @@
|
|||
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 h1:moSC7ACaTejHmVRRwfDTMgByRSwjg2vZooncdWLj7o8=
|
||||
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
|
||||
github.com/ProtonMail/go-appdir v0.0.0-20180220133335-7c788d1b45c6 h1:de/SvQsi6Oou9TJYp6Kp17S+JjXGn1w8XVYWFlE0z/U=
|
||||
github.com/ProtonMail/go-appdir v0.0.0-20180220133335-7c788d1b45c6/go.mod h1:3d8Y9F5mbEUjrYbcJ3rcDxcWbqbttF+011nVZmdRdzc=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
|
||||
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/distatus/battery v0.0.0-20170521010419-916919eb43bd h1:rxw7AZpSwNgPPFdxDNSwQ+TfvOjmSGDK6tlpY7vw9bw=
|
||||
github.com/distatus/battery v0.0.0-20170521010419-916919eb43bd/go.mod h1:gGO7GxHTi1zlRT+cAj8uGG0/8HFiqAeH0TJvoipnuPs=
|
||||
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/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
github.com/gizak/termui v0.0.0-20190101100649-ffdef4cb72e9 h1:h5eo3CW6c9WMG+rN8cVxf25v8bSWFjuaDJdvtEWc61E=
|
||||
github.com/gizak/termui v0.0.0-20190101100649-ffdef4cb72e9/go.mod h1:S3xz8JHXNDPSNFsvXCdG7bHlEGrwvUG3a0joR/xYZ5M=
|
||||
github.com/gizak/termui v2.3.0+incompatible h1:S8wJoNumYfc/rR5UezUM4HsPEo3RJh0LKdiuDWQpjqw=
|
||||
github.com/gizak/termui v2.3.0+incompatible/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/maruel/panicparse v1.1.1 h1:k62YPcEoLncEEpjMt92GtG5ugb8WL/510Ys3/h5IkRc=
|
||||
github.com/maruel/panicparse v1.1.1/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
|
||||
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/nexulh/batmond v0.0.0-20180213215845-395ac7fdba8c h1:Hiq+wfawWPyyX2AVpIhEiVsoKVQdc8zQwAwiKiVZbTI=
|
||||
github.com/nexulh/batmond v0.0.0-20180213215845-395ac7fdba8c/go.mod h1:Ho2yA2Aa5zD+GEgmhFdLLpHVFoGJXF/Et15iRydTFtY=
|
||||
github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443 h1:+2OJrU8cmOstEoh0uQvYemRGVH1O6xtO2oANUWHFnP0=
|
||||
github.com/nightlyone/lockfile v0.0.0-20180618180623-0ad87eef1443/go.mod h1:JbxfV1Iifij2yhRjXai0oFrbpxszXHRx1E5RuM26o4Y=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/serussell/battery v0.0.0-20170521010419-b399f895029c/go.mod h1:0eSBUZHzM+0VCcUzFSkpxGxOg+jkMTT2cr4U/zupwsk=
|
||||
github.com/shirou/gopsutil v2.18.11+incompatible h1:PMFTKnFTr/YTRW5rbLK4vWALV3a+IGXse5nvhSjztmg=
|
||||
github.com/shirou/gopsutil v2.18.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180406135729-3b87a42e500a h1:DwI0ihryIiWlRUKL/ii7Snvn4LiL9TvMoVZq3qMbffg=
|
||||
golang.org/x/sys v0.0.0-20180406135729-3b87a42e500a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 h1:IcgEB62HYgAhX0Nd/QrVgZlxlcyxbGQHElLUhW2X4Fo=
|
||||
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
|
||||
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
|
||||
|
|
186
main.go
186
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"
|
||||
|
@ -34,11 +34,13 @@ var (
|
|||
averageLoad = false
|
||||
battery = false
|
||||
percpuLoad = false
|
||||
widgetCount = 7
|
||||
fahrenheit = false
|
||||
configDir = appdir.New("gotop").UserConfig()
|
||||
logPath = filepath.Join(configDir, "errors.log")
|
||||
stderrLogger = log.New(os.Stderr, "", 0)
|
||||
statusbar = false
|
||||
termWidth int
|
||||
termHeight int
|
||||
|
||||
cpu *w.CPU
|
||||
batt *w.Batt
|
||||
|
@ -48,6 +50,7 @@ var (
|
|||
disk *w.Disk
|
||||
temp *w.Temp
|
||||
help *w.HelpMenu
|
||||
grid *ui.Grid
|
||||
)
|
||||
|
||||
func cliArguments() error {
|
||||
|
@ -63,7 +66,8 @@ Options:
|
|||
-p, --percpu Show each CPU in the CPU widget.
|
||||
-a, --averagecpu Show average CPU in the CPU widget.
|
||||
-f, --fahrenheit Show temperatures in fahrenheit.
|
||||
-b, --battery Show battery charge over time (minimal overrides & sets false)
|
||||
-t, --battery Show battery charge over time ('minimal' disables; widget updates slowly)
|
||||
-b, --bar Show a statusbar with the time.
|
||||
|
||||
Colorschemes:
|
||||
default
|
||||
|
@ -87,9 +91,8 @@ Colorschemes:
|
|||
battery, _ = args["--battery"].(bool)
|
||||
|
||||
minimal, _ = args["--minimal"].(bool)
|
||||
if minimal {
|
||||
widgetCount = 3
|
||||
}
|
||||
|
||||
statusbar, _ = args["--bar"].(bool)
|
||||
|
||||
rateStr, _ := args["--rate"].(string)
|
||||
rate, err := strconv.ParseFloat(rateStr, 64)
|
||||
|
@ -141,46 +144,68 @@ 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)
|
||||
|
||||
var barRow interface{}
|
||||
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)
|
||||
} else {
|
||||
if battery {
|
||||
ui.Body.Set(0, 0, 8, 4, cpu)
|
||||
ui.Body.Set(8, 0, 12, 4, batt)
|
||||
} else {
|
||||
ui.Body.Set(0, 0, 12, 4, cpu)
|
||||
rowHeight := 1.0 / 2
|
||||
if statusbar {
|
||||
rowHeight = 50.0 / 101
|
||||
barRow = ui.NewRow(1.0/101, w.NewStatusBar())
|
||||
}
|
||||
|
||||
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(rowHeight, cpu),
|
||||
ui.NewRow(rowHeight,
|
||||
ui.NewCol(1.0/2, mem),
|
||||
ui.NewCol(1.0/2, proc),
|
||||
),
|
||||
barRow,
|
||||
)
|
||||
} else {
|
||||
rowHeight := 1.0 / 3
|
||||
if statusbar {
|
||||
rowHeight = 50.0 / 151
|
||||
barRow = ui.NewRow(1.0/151, w.NewStatusBar())
|
||||
}
|
||||
var cpuRow ui.GridItem
|
||||
if battery {
|
||||
cpuRow = ui.NewRow(rowHeight,
|
||||
ui.NewCol(2.0/3, cpu),
|
||||
ui.NewCol(1.0/3, batt),
|
||||
)
|
||||
} else {
|
||||
cpuRow = ui.NewRow(rowHeight, cpu)
|
||||
}
|
||||
grid.Set(
|
||||
cpuRow,
|
||||
ui.NewRow(rowHeight,
|
||||
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(rowHeight,
|
||||
ui.NewCol(1.0/2, net),
|
||||
ui.NewCol(1.0/2, proc),
|
||||
),
|
||||
barRow,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -194,60 +219,76 @@ 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)
|
||||
var battKeys []string
|
||||
for key := range batt.Data {
|
||||
battKeys = append(battKeys, key)
|
||||
}
|
||||
sort.Strings(battKeys)
|
||||
bi := 0
|
||||
for _, v := range battKeys {
|
||||
if bi >= len(colorscheme.BattLines) {
|
||||
// assuming colorscheme for CPU lines is not empty
|
||||
bi = 0
|
||||
if battery {
|
||||
var battKeys []string
|
||||
for key := range batt.Data {
|
||||
battKeys = append(battKeys, key)
|
||||
}
|
||||
sort.Strings(battKeys)
|
||||
i = 0 // Re-using variable from CPU
|
||||
for _, v := range battKeys {
|
||||
if i >= len(colorscheme.BattLines) {
|
||||
// assuming colorscheme for battery lines is not empty
|
||||
i = 0
|
||||
}
|
||||
c := colorscheme.BattLines[i]
|
||||
batt.LineColor[v] = ui.Attribute(c)
|
||||
i++
|
||||
}
|
||||
c := colorscheme.BattLines[bi]
|
||||
batt.LineColor[v] = ui.Color(c)
|
||||
bi++
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func initWidgets() {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(widgetCount)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
cpu = w.NewCPU(interval, zoom, averageLoad, percpuLoad)
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
mem = w.NewMem(interval, zoom)
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
proc = w.NewProc()
|
||||
wg.Done()
|
||||
}()
|
||||
if !minimal {
|
||||
go func() {
|
||||
batt = w.NewBatt(time.Minute, zoom)
|
||||
wg.Done()
|
||||
}()
|
||||
if battery {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
batt = w.NewBatt(time.Minute, zoom)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
net = w.NewNet()
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
disk = w.NewDisk()
|
||||
wg.Done()
|
||||
}()
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
temp = w.NewTemp(fahrenheit)
|
||||
wg.Done()
|
||||
|
@ -274,7 +315,7 @@ func eventLoop() {
|
|||
return
|
||||
case <-drawTicker:
|
||||
if !helpVisible {
|
||||
ui.Render(ui.Body)
|
||||
ui.Render(grid)
|
||||
}
|
||||
case e := <-uiEvents:
|
||||
switch e.ID {
|
||||
|
@ -286,7 +327,7 @@ func eventLoop() {
|
|||
ui.Clear()
|
||||
ui.Render(help)
|
||||
} else {
|
||||
ui.Render(ui.Body)
|
||||
ui.Render(grid)
|
||||
}
|
||||
case "h":
|
||||
if !helpVisible {
|
||||
|
@ -307,27 +348,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>":
|
||||
|
@ -401,11 +442,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)
|
||||
}
|
||||
|
@ -413,8 +449,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()
|
||||
}
|
||||
|
|
131
src/termui/linegraph.go
Normal file
131
src/termui/linegraph.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
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]Attribute
|
||||
Zoom int
|
||||
Labels map[string]string
|
||||
|
||||
DefaultLineColor Attribute
|
||||
}
|
||||
|
||||
// NewLineGraph returns a new LineGraph with current theme.
|
||||
func NewLineGraph() *LineGraph {
|
||||
return &LineGraph{
|
||||
Block: NewBlock(),
|
||||
Data: make(map[string][]float64),
|
||||
LineColor: make(map[string]Attribute),
|
||||
Labels: make(map[string]string),
|
||||
Zoom: 5,
|
||||
}
|
||||
}
|
||||
|
||||
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([][]Attribute, self.Inner.Dx()+2)
|
||||
for i := range colors {
|
||||
colors[i] = make([]Attribute, self.Inner.Dy()+2)
|
||||
}
|
||||
|
||||
// sort the series so that overlapping data will overlap the same way each time
|
||||
seriesList := make([]string, len(self.Data))
|
||||
i := 0
|
||||
for seriesName := range self.Data {
|
||||
seriesList[i] = seriesName
|
||||
i++
|
||||
}
|
||||
sort.Strings(seriesList)
|
||||
|
||||
// draw lines in reverse order so that the first color defined in the colorscheme is on top
|
||||
for i := len(seriesList) - 1; i >= 0; i-- {
|
||||
seriesName := seriesList[i]
|
||||
seriesData := self.Data[seriesName]
|
||||
seriesLineColor, ok := self.LineColor[seriesName]
|
||||
if !ok {
|
||||
seriesLineColor = self.DefaultLineColor
|
||||
}
|
||||
|
||||
// coordinates of last point
|
||||
lastY, lastX := -1, -1
|
||||
// assign colors to `colors` and lines/points to the canvas
|
||||
for i := len(seriesData) - 1; i >= 0; i-- {
|
||||
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 {
|
||||
for _, p := range drawille.Line(lastX, lastY, x, y) {
|
||||
if p.X > 0 {
|
||||
c.Set(p.X, p.Y)
|
||||
colors[p.X/2][p.Y/4] = seriesLineColor
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
if lastY == -1 { // if this is the first point
|
||||
c.Set(x, y)
|
||||
colors[x/2][y/4] = seriesLineColor
|
||||
} else {
|
||||
c.DrawLine(lastX, lastY, x, y)
|
||||
for _, p := range drawille.Line(lastX, lastY, x, y) {
|
||||
colors[p.X/2][p.Y/4] = seriesLineColor
|
||||
}
|
||||
}
|
||||
lastX, lastY = x, y
|
||||
}
|
||||
|
||||
// copy braille and colors to buffer
|
||||
for y, line := range c.Rows(c.MinX(), c.MinY(), c.MaxX(), c.MaxY()) {
|
||||
for x, char := range line {
|
||||
x /= 3 // idk why but it works
|
||||
if x == 0 {
|
||||
continue
|
||||
}
|
||||
if char != 10240 { // empty braille character
|
||||
buf.SetCell(
|
||||
Cell{char, AttrPair{colors[x][y], -1}},
|
||||
image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+y-1),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// renders key/label ontop
|
||||
for i, seriesName := range seriesList {
|
||||
if i+2 > self.Inner.Dy() {
|
||||
continue
|
||||
}
|
||||
seriesLineColor, ok := self.LineColor[seriesName]
|
||||
if !ok {
|
||||
seriesLineColor = self.DefaultLineColor
|
||||
}
|
||||
|
||||
// render key ontop, but let braille be drawn over space characters
|
||||
str := seriesName + " " + self.Labels[seriesName]
|
||||
for k, char := range str {
|
||||
if char != ' ' {
|
||||
buf.SetCell(
|
||||
Cell{char, AttrPair{seriesLineColor, -1}},
|
||||
image.Pt(self.Inner.Min.X+2+k, self.Inner.Min.Y+i+1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
99
src/termui/sparkline.go
Normal file
99
src/termui/sparkline.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package termui
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
. "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
var SPARKS = [8]rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}
|
||||
|
||||
// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
|
||||
type Sparkline struct {
|
||||
Data []int
|
||||
Title1 string
|
||||
Title2 string
|
||||
TitleColor Attribute
|
||||
LineColor Attribute
|
||||
}
|
||||
|
||||
// Sparklines is a renderable widget which groups together the given sparklines.
|
||||
type Sparklines struct {
|
||||
*Block
|
||||
Lines []*Sparkline
|
||||
}
|
||||
|
||||
// Add appends a given Sparkline to the *Sparklines.
|
||||
func (self *Sparklines) Add(sl Sparkline) {
|
||||
self.Lines = append(self.Lines, &sl)
|
||||
}
|
||||
|
||||
// NewSparkline returns an unrenderable single sparkline that intended to be added into a Sparklines.
|
||||
func NewSparkline() *Sparkline {
|
||||
return &Sparkline{}
|
||||
}
|
||||
|
||||
// NewSparklines return a new *Sparklines with given Sparklines, you can always add a new Sparkline later.
|
||||
func NewSparklines(ss ...*Sparkline) *Sparklines {
|
||||
return &Sparklines{
|
||||
Block: NewBlock(),
|
||||
Lines: ss,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Sparklines) Draw(buf *Buffer) {
|
||||
self.Block.Draw(buf)
|
||||
|
||||
lc := len(self.Lines) // lineCount
|
||||
|
||||
// renders each sparkline and its titles
|
||||
for i, line := range self.Lines {
|
||||
|
||||
// prints titles
|
||||
title1Y := self.Inner.Min.Y + 1 + (self.Inner.Dy()/lc)*i
|
||||
title2Y := self.Inner.Min.Y + 2 + (self.Inner.Dy()/lc)*i
|
||||
title1 := TrimString(line.Title1, self.Inner.Dx())
|
||||
title2 := TrimString(line.Title2, self.Inner.Dx())
|
||||
if self.Inner.Dy() > 5 {
|
||||
buf.SetString(
|
||||
title1,
|
||||
image.Pt(self.Inner.Min.X, title1Y),
|
||||
AttrPair{line.TitleColor | AttrBold, -1},
|
||||
)
|
||||
}
|
||||
if self.Inner.Dy() > 6 {
|
||||
buf.SetString(
|
||||
title2,
|
||||
image.Pt(self.Inner.Min.X, title2Y),
|
||||
AttrPair{line.TitleColor | AttrBold, -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.Inner.Dx()-((len(line.Data)-1)-i) >= 1; i-- {
|
||||
if line.Data[i] > max {
|
||||
max = line.Data[i]
|
||||
}
|
||||
}
|
||||
// prints sparkline
|
||||
for x := self.Inner.Dx(); x >= 1; x-- {
|
||||
char := SPARKS[0]
|
||||
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) {
|
||||
panic("TODO")
|
||||
}
|
||||
char = SPARKS[index]
|
||||
}
|
||||
buf.SetCell(
|
||||
Cell{char, AttrPair{line.LineColor, -1}},
|
||||
image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+sparkY-1),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
206
src/termui/table.go
Normal file
206
src/termui/table.go
Normal file
|
@ -0,0 +1,206 @@
|
|||
package termui
|
||||
|
||||
import (
|
||||
"image"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
. "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
// Table tracks all the attributes of a Table instance
|
||||
type Table struct {
|
||||
*Block
|
||||
|
||||
sync.Mutex
|
||||
|
||||
Header []string
|
||||
Rows [][]string
|
||||
|
||||
ColWidths []int
|
||||
CellXPos []int // column position
|
||||
ColResizer func() // for widgets that inherit a Table and want to overload the ColResize method
|
||||
Gap int // gap between columns
|
||||
PadLeft int
|
||||
|
||||
Cursor bool
|
||||
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
|
||||
SelectedRow int
|
||||
TopRow int // used to indicate where in the table we are scrolled at
|
||||
}
|
||||
|
||||
// NewTable returns a new Table instance
|
||||
func NewTable() *Table {
|
||||
self := &Table{
|
||||
Block: NewBlock(),
|
||||
// CursorColor: Theme.TableCursor,
|
||||
SelectedRow: 0,
|
||||
TopRow: 0,
|
||||
UniqueCol: 0,
|
||||
}
|
||||
self.ColResizer = self.ColResize
|
||||
return self
|
||||
}
|
||||
|
||||
// ColResize is the default column resizer, but can be overriden.
|
||||
// ColResize calculates the width of each column.
|
||||
func (self *Table) ColResize() {
|
||||
}
|
||||
|
||||
func (self *Table) Draw(buf *Buffer) {
|
||||
self.Lock()
|
||||
|
||||
self.Block.Draw(buf)
|
||||
|
||||
self.ColResizer()
|
||||
|
||||
// finds exact column starting position
|
||||
self.CellXPos = []int{}
|
||||
cur := 1 + self.PadLeft
|
||||
for _, w := range self.ColWidths {
|
||||
self.CellXPos = append(self.CellXPos, cur)
|
||||
cur += w
|
||||
cur += self.Gap
|
||||
}
|
||||
|
||||
// prints header
|
||||
for i, h := range self.Header {
|
||||
width := self.ColWidths[i]
|
||||
if width == 0 {
|
||||
continue
|
||||
}
|
||||
// don't render column if it doesn't fit in widget
|
||||
if width > (self.Inner.Dx()-self.CellXPos[i])+1 {
|
||||
continue
|
||||
}
|
||||
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.Inner.Dy()-1 && rowNum < len(self.Rows); rowNum++ {
|
||||
if rowNum < 0 || rowNum >= len(self.Rows) {
|
||||
panic("TODO")
|
||||
}
|
||||
row := self.Rows[rowNum]
|
||||
y := (rowNum + 2) - self.TopRow
|
||||
|
||||
// prints cursor
|
||||
fg := Theme.Default.Fg
|
||||
if self.Cursor {
|
||||
if (self.SelectedItem == "" && rowNum == self.SelectedRow) || (self.SelectedItem != "" && self.SelectedItem == row[self.UniqueCol]) {
|
||||
fg = self.CursorColor | AttrReverse
|
||||
for _, width := range self.ColWidths {
|
||||
if width == 0 {
|
||||
continue
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// prints each col of the row
|
||||
for i, width := range self.ColWidths {
|
||||
if width == 0 {
|
||||
continue
|
||||
}
|
||||
// don't render column if width is greater than distance to end of widget
|
||||
if width > (self.Inner.Dx()-self.CellXPos[i])+1 {
|
||||
continue
|
||||
}
|
||||
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},
|
||||
)
|
||||
}
|
||||
}
|
||||
self.Unlock()
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Cursor Movement //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// calcPos is used to calculate the cursor position and the current view.
|
||||
func (self *Table) calcPos() {
|
||||
self.SelectedItem = ""
|
||||
|
||||
if self.SelectedRow < 0 {
|
||||
self.SelectedRow = 0
|
||||
}
|
||||
if self.SelectedRow < self.TopRow {
|
||||
self.TopRow = self.SelectedRow
|
||||
}
|
||||
|
||||
if self.SelectedRow > len(self.Rows)-1 {
|
||||
self.SelectedRow = len(self.Rows) - 1
|
||||
}
|
||||
if self.SelectedRow > self.TopRow+(self.Inner.Dy()-2) {
|
||||
self.TopRow = self.SelectedRow - (self.Inner.Dy() - 2)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Table) Up() {
|
||||
self.SelectedRow -= 1
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) Down() {
|
||||
self.SelectedRow += 1
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) Top() {
|
||||
self.SelectedRow = 0
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) Bottom() {
|
||||
self.SelectedRow = len(self.Rows) - 1
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
// The number of lines in a page is equal to the height of the widgeself.
|
||||
|
||||
func (self *Table) HalfPageUp() {
|
||||
self.SelectedRow = self.SelectedRow - (self.Inner.Dy()-2)/2
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) HalfPageDown() {
|
||||
self.SelectedRow = self.SelectedRow + (self.Inner.Dy()-2)/2
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) PageUp() {
|
||||
self.SelectedRow -= (self.Inner.Dy() - 2)
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) PageDown() {
|
||||
self.SelectedRow += (self.Inner.Dy() - 2)
|
||||
self.calcPos()
|
||||
}
|
||||
|
||||
func (self *Table) Click(x, y int) {
|
||||
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()
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
ui "github.com/cjbassi/termui"
|
||||
ui "github.com/cjbassi/gotop/src/termui"
|
||||
"github.com/distatus/battery"
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,7 @@ func NewBatt(interval time.Duration, zoom int) *Batt {
|
|||
Count: len(batts),
|
||||
interval: interval,
|
||||
}
|
||||
self.Label = "Battery Status"
|
||||
self.Title = "Battery Status"
|
||||
self.Zoom = zoom
|
||||
if err != nil {
|
||||
log.Printf("failed to get battery info from system: %v", err)
|
||||
|
|
|
@ -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
|
||||
|
@ -65,7 +66,9 @@ func NewProc() *Proc {
|
|||
go func() {
|
||||
ticker := time.NewTicker(self.interval)
|
||||
for range ticker.C {
|
||||
self.Lock()
|
||||
self.update()
|
||||
self.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -108,11 +111,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()
|
||||
|
|
50
src/widgets/statusbar.go
Normal file
50
src/widgets/statusbar.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package widgets
|
||||
|
||||
import (
|
||||
"image"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
ui "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
type StatusBar struct {
|
||||
ui.Block
|
||||
}
|
||||
|
||||
func NewStatusBar() *StatusBar {
|
||||
self := &StatusBar{*ui.NewBlock()}
|
||||
self.Border = false
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *StatusBar) Draw(buf *ui.Buffer) {
|
||||
self.Block.Draw(buf)
|
||||
|
||||
hostname, _ := os.Hostname()
|
||||
buf.SetString(
|
||||
hostname,
|
||||
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+(self.Inner.Dy()/2)),
|
||||
ui.AttrPair{ui.Attribute(7), -1},
|
||||
)
|
||||
|
||||
t := time.Now()
|
||||
_time := t.Format("15:04:05")
|
||||
buf.SetString(
|
||||
_time,
|
||||
image.Pt(
|
||||
self.Inner.Min.X+(self.Inner.Dx()/2)-len(_time)/2,
|
||||
self.Inner.Min.Y+(self.Inner.Dy()/2),
|
||||
),
|
||||
ui.AttrPair{7, -1},
|
||||
)
|
||||
|
||||
buf.SetString(
|
||||
"gotop",
|
||||
image.Pt(
|
||||
self.Inner.Max.X-6,
|
||||
self.Inner.Min.Y+(self.Inner.Dy()/2),
|
||||
),
|
||||
ui.AttrPair{7, -1},
|
||||
)
|
||||
}
|
|
@ -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
|
||||
|
@ -47,9 +48,8 @@ func NewTemp(fahrenheit bool) *Temp {
|
|||
return self
|
||||
}
|
||||
|
||||
// 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 +58,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 +67,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