Adds log rotation, config file support, and refactoring. Colorschemes are self-registered. Merge remote-tracking branch 'jrswab/configFile111' into config_file; drastically refactored, and am not sure how much original code from the patch was used.
This commit is contained in:
commit
2a53398681
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -15,10 +15,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [3.3.0] -
|
||||
|
||||
- Changed: Logs are now rotated. Settings are currently hard-coded at 4 files of 5MB
|
||||
- Added: Logs are now rotated. Settings are currently hard-coded at 4 files of 5MB
|
||||
each, so logs shouldn't take up more than 20MB. I'm going to see how many
|
||||
complain about wanting to configure these settings before I add code to do
|
||||
that.
|
||||
- Added: Config file support. \$XDG_CONFIG_HOME/gotop/gotop.conf can now
|
||||
contain any field in Config. Syntax is simply KEY=VALUE. Values in config
|
||||
file are overridden by command-line arguments (although, there's a weakness
|
||||
in that there's no way to disable boolean fields enabled in the config).
|
||||
- Changed: Colorscheme registration is changed to be less hard-coded.
|
||||
Colorschemes can now be created and added to the repo, without having to also
|
||||
add hard-coded references elsewhere.
|
||||
- Changed: Minor code refactoring to support Config file changes has resulted
|
||||
in better isolation.
|
||||
|
||||
## [3.2.0] - 2020-02-14
|
||||
|
||||
|
|
|
@ -149,14 +149,14 @@ build massive edifices, you're in for disappointment.
|
|||
### CLI Options
|
||||
|
||||
`-c`, `--color=NAME` Set a colorscheme.
|
||||
`-m`, `--minimal` Only show CPU, Mem and Process widgets.
|
||||
`-m`, `--minimal` Only show CPU, Mem and Process widgets. (DEPRECATED for `-l minimal`)
|
||||
`-r`, `--rate=RATE` Number of times per second to update CPU and Mem widgets [default: 1].
|
||||
`-V`, `--version` Print version and exit.
|
||||
`-p`, `--percpu` Show each CPU in the CPU widget.
|
||||
`-a`, `--averagecpu` Show average CPU in the CPU widget.
|
||||
`-f`, `--fahrenheit` Show temperatures in fahrenheit.
|
||||
`-s`, `--statusbar` Show a statusbar with the time.
|
||||
`-b`, `--battery` Show battery level widget (`minimal` turns off). [preview](./assets/screenshots/battery.png)
|
||||
`-b`, `--battery` Show battery level widget (`minimal` turns off). [preview](./assets/screenshots/battery.png) (DEPRECATED for `-l battery`)
|
||||
`-i`, `--interface=NAME` Select network interface [default: all].
|
||||
`-l`, `--layout=NAME` Choose a layout. gotop searches for a file by NAME in \$XDG_CONFIG_HOME/gotop, then relative to the current path. "-" reads a layout from stdin, allowing for simple, one-off layouts such as `echo net | gotop -l -`
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -42,7 +41,7 @@ var (
|
|||
stderrLogger = log.New(os.Stderr, "", 0)
|
||||
)
|
||||
|
||||
func parseArgs() (gotop.Config, error) {
|
||||
func parseArgs(conf *gotop.Config) error {
|
||||
usage := `
|
||||
Usage: gotop [options]
|
||||
|
||||
|
@ -75,133 +74,65 @@ Colorschemes:
|
|||
vice
|
||||
`
|
||||
|
||||
ld := utils.GetLogDir(appName)
|
||||
cd := utils.GetConfigDir(appName)
|
||||
conf = gotop.Config{
|
||||
ConfigDir: cd,
|
||||
LogDir: ld,
|
||||
LogFile: "errors.log",
|
||||
GraphHorizontalScale: 7,
|
||||
HelpVisible: false,
|
||||
Colorscheme: colorschemes.Default,
|
||||
UpdateInterval: time.Second,
|
||||
AverageLoad: false,
|
||||
PercpuLoad: false,
|
||||
TempScale: w.Celsius,
|
||||
Statusbar: false,
|
||||
NetInterface: w.NET_INTERFACE_ALL,
|
||||
MaxLogSize: 5000000,
|
||||
var err error
|
||||
conf.Colorscheme, err = colorschemes.FromName(conf.ConfigDir, "default")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args, err := docopt.ParseArgs(usage, os.Args[1:], version)
|
||||
if err != nil {
|
||||
return conf, err
|
||||
return err
|
||||
}
|
||||
|
||||
if val, _ := args["--layout"]; val != nil {
|
||||
s := val.(string)
|
||||
switch s {
|
||||
case "-":
|
||||
conf.Layout = os.Stdin
|
||||
case "default":
|
||||
conf.Layout = strings.NewReader(defaultUI)
|
||||
case "minimal":
|
||||
conf.Layout = strings.NewReader(minimalUI)
|
||||
case "battery":
|
||||
conf.Layout = strings.NewReader(batteryUI)
|
||||
default:
|
||||
fp := filepath.Join(cd, s)
|
||||
conf.Layout, err = os.Open(fp)
|
||||
if err != nil {
|
||||
conf.Layout, err = os.Open(s)
|
||||
if err != nil {
|
||||
stderrLogger.Fatalf("Unable to open layout file %s or ./%s", fp, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
conf.Layout = strings.NewReader(defaultUI)
|
||||
conf.Layout = val.(string)
|
||||
}
|
||||
|
||||
if val, _ := args["--color"]; val != nil {
|
||||
cs, err := handleColorscheme(val.(string))
|
||||
cs, err := colorschemes.FromName(conf.ConfigDir, val.(string))
|
||||
if err != nil {
|
||||
return conf, err
|
||||
return err
|
||||
}
|
||||
conf.Colorscheme = cs
|
||||
}
|
||||
conf.AverageLoad, _ = args["--averagecpu"].(bool)
|
||||
conf.PercpuLoad, _ = args["--percpu"].(bool)
|
||||
statusbar, _ = args["--statusbar"].(bool)
|
||||
|
||||
if args["--averagecpu"].(bool) {
|
||||
conf.AverageLoad, _ = args["--averagecpu"].(bool)
|
||||
}
|
||||
if args["--percpu"].(bool) {
|
||||
conf.PercpuLoad, _ = args["--percpu"].(bool)
|
||||
}
|
||||
if args["--statusbar"].(bool) {
|
||||
statusbar, _ = args["--statusbar"].(bool)
|
||||
}
|
||||
if args["--battery"].(bool) {
|
||||
log.Printf("BATTERY %s", batteryUI)
|
||||
conf.Layout = strings.NewReader(batteryUI)
|
||||
conf.Layout = "battery"
|
||||
}
|
||||
if args["--minimal"].(bool) {
|
||||
conf.Layout = strings.NewReader(minimalUI)
|
||||
conf.Layout = "minimal"
|
||||
}
|
||||
rateStr, _ := args["--rate"].(string)
|
||||
rate, err := strconv.ParseFloat(rateStr, 64)
|
||||
if err != nil {
|
||||
return conf, fmt.Errorf("invalid rate parameter")
|
||||
}
|
||||
if rate < 1 {
|
||||
conf.UpdateInterval = time.Second * time.Duration(1/rate)
|
||||
} else {
|
||||
conf.UpdateInterval = time.Second / time.Duration(rate)
|
||||
}
|
||||
fahrenheit, _ := args["--fahrenheit"].(bool)
|
||||
if fahrenheit {
|
||||
conf.TempScale = w.Fahrenheit
|
||||
}
|
||||
conf.NetInterface, _ = args["--interface"].(string)
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func handleColorscheme(c string) (colorschemes.Colorscheme, error) {
|
||||
var cs colorschemes.Colorscheme
|
||||
switch c {
|
||||
case "default":
|
||||
cs = colorschemes.Default
|
||||
case "solarized":
|
||||
cs = colorschemes.Solarized
|
||||
case "solarized16-light":
|
||||
cs = colorschemes.Solarized16Light
|
||||
case "solarized16-dark":
|
||||
cs = colorschemes.Solarized16Dark
|
||||
case "monokai":
|
||||
cs = colorschemes.Monokai
|
||||
case "vice":
|
||||
cs = colorschemes.Vice
|
||||
case "default-dark":
|
||||
cs = colorschemes.DefaultDark
|
||||
case "nord":
|
||||
cs = colorschemes.Nord
|
||||
default:
|
||||
custom, err := getCustomColorscheme(conf, c)
|
||||
if val, _ := args["--statusbar"]; val != nil {
|
||||
rateStr, _ := args["--rate"].(string)
|
||||
rate, err := strconv.ParseFloat(rateStr, 64)
|
||||
if err != nil {
|
||||
return cs, err
|
||||
return fmt.Errorf("invalid rate parameter")
|
||||
}
|
||||
if rate < 1 {
|
||||
conf.UpdateInterval = time.Second * time.Duration(1/rate)
|
||||
} else {
|
||||
conf.UpdateInterval = time.Second / time.Duration(rate)
|
||||
}
|
||||
cs = custom
|
||||
}
|
||||
return cs, nil
|
||||
}
|
||||
if val, _ := args["--fahrenheit"]; val != nil {
|
||||
fahrenheit, _ := val.(bool)
|
||||
if fahrenheit {
|
||||
conf.TempScale = w.Fahrenheit
|
||||
}
|
||||
}
|
||||
if val, _ := args["--interface"]; val != nil {
|
||||
conf.NetInterface, _ = args["--interface"].(string)
|
||||
}
|
||||
|
||||
// getCustomColorscheme tries to read a custom json colorscheme from <configDir>/<name>.json
|
||||
func getCustomColorscheme(c gotop.Config, name string) (colorschemes.Colorscheme, error) {
|
||||
var cs colorschemes.Colorscheme
|
||||
filePath := filepath.Join(c.ConfigDir, name+".json")
|
||||
dat, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return cs, fmt.Errorf("failed to read colorscheme file: %v", err)
|
||||
}
|
||||
err = json.Unmarshal(dat, &cs)
|
||||
if err != nil {
|
||||
return cs, fmt.Errorf("failed to parse colorscheme file: %v", err)
|
||||
}
|
||||
return cs, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDefaultTermuiColors(c gotop.Config) {
|
||||
|
@ -388,8 +319,40 @@ func eventLoop(c gotop.Config, grid *layout.MyGrid) {
|
|||
}
|
||||
}
|
||||
|
||||
func makeConfig() gotop.Config {
|
||||
ld := utils.GetLogDir(appName)
|
||||
cd := utils.GetConfigDir(appName)
|
||||
conf = gotop.Config{
|
||||
ConfigDir: cd,
|
||||
LogDir: ld,
|
||||
LogFile: "errors.log",
|
||||
GraphHorizontalScale: 7,
|
||||
HelpVisible: false,
|
||||
UpdateInterval: time.Second,
|
||||
AverageLoad: false,
|
||||
PercpuLoad: false,
|
||||
TempScale: w.Celsius,
|
||||
Statusbar: false,
|
||||
NetInterface: w.NET_INTERFACE_ALL,
|
||||
MaxLogSize: 5000000,
|
||||
Layout: "default",
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
func main() {
|
||||
conf, err := parseArgs()
|
||||
// Set up default config
|
||||
conf := makeConfig()
|
||||
// Parse the config file
|
||||
cfn := filepath.Join(conf.ConfigDir, "gotop.conf")
|
||||
if cf, err := os.Open(cfn); err == nil {
|
||||
err := gotop.Parse(cf, &conf)
|
||||
if err != nil {
|
||||
stderrLogger.Fatalf("error parsing config file %v", err)
|
||||
}
|
||||
}
|
||||
// Override with command line arguments
|
||||
err := parseArgs(&conf)
|
||||
if err != nil {
|
||||
stderrLogger.Fatalf("failed to parse cli args: %v", err)
|
||||
}
|
||||
|
@ -411,7 +374,8 @@ func main() {
|
|||
bar = w.NewStatusBar()
|
||||
}
|
||||
|
||||
ly := layout.ParseLayout(conf.Layout)
|
||||
lstream := getLayout(conf)
|
||||
ly := layout.ParseLayout(lstream)
|
||||
grid, err := layout.Layout(ly, conf)
|
||||
if err != nil {
|
||||
stderrLogger.Fatalf("failed to initialize termui: %v", err)
|
||||
|
@ -433,3 +397,27 @@ func main() {
|
|||
|
||||
eventLoop(conf, grid)
|
||||
}
|
||||
|
||||
func getLayout(conf gotop.Config) io.Reader {
|
||||
switch conf.Layout {
|
||||
case "-":
|
||||
return os.Stdin
|
||||
case "default":
|
||||
return strings.NewReader(defaultUI)
|
||||
case "minimal":
|
||||
return strings.NewReader(minimalUI)
|
||||
case "battery":
|
||||
return strings.NewReader(batteryUI)
|
||||
default:
|
||||
log.Printf("layout = %s", conf.Layout)
|
||||
fp := filepath.Join(conf.ConfigDir, conf.Layout)
|
||||
fin, err := os.Open(fp)
|
||||
if err != nil {
|
||||
fin, err = os.Open(conf.Layout)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to open layout file %s or ./%s", fp, conf.Layout)
|
||||
}
|
||||
}
|
||||
return fin
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
package colorschemes
|
||||
|
||||
var Default = Colorscheme{
|
||||
Fg: 7,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("default", Colorscheme{
|
||||
Fg: 7,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: 7,
|
||||
BorderLine: 6,
|
||||
BorderLabel: 7,
|
||||
BorderLine: 6,
|
||||
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
MainMem: 5,
|
||||
SwapMem: 11,
|
||||
MainMem: 5,
|
||||
SwapMem: 11,
|
||||
|
||||
ProcCursor: 4,
|
||||
ProcCursor: 4,
|
||||
|
||||
Sparkline: 4,
|
||||
Sparkline: 4,
|
||||
|
||||
DiskBar: 7,
|
||||
DiskBar: 7,
|
||||
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
package colorschemes
|
||||
|
||||
var DefaultDark = Colorscheme{
|
||||
Fg: 235,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("defaultdark", Colorscheme{
|
||||
Fg: 235,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: 235,
|
||||
BorderLine: 6,
|
||||
BorderLabel: 235,
|
||||
BorderLine: 6,
|
||||
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
MainMem: 5,
|
||||
SwapMem: 3,
|
||||
MainMem: 5,
|
||||
SwapMem: 3,
|
||||
|
||||
ProcCursor: 33,
|
||||
ProcCursor: 33,
|
||||
|
||||
Sparkline: 4,
|
||||
Sparkline: 4,
|
||||
|
||||
DiskBar: 252,
|
||||
DiskBar: 252,
|
||||
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
package colorschemes
|
||||
|
||||
var Monokai = Colorscheme{
|
||||
Fg: 249,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("monokai", Colorscheme{
|
||||
Fg: 249,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: 249,
|
||||
BorderLine: 239,
|
||||
BorderLabel: 249,
|
||||
BorderLine: 239,
|
||||
|
||||
CPULines: []int{81, 70, 208, 197, 249, 141, 221, 186},
|
||||
CPULines: []int{81, 70, 208, 197, 249, 141, 221, 186},
|
||||
|
||||
BattLines: []int{81, 70, 208, 197, 249, 141, 221, 186},
|
||||
BattLines: []int{81, 70, 208, 197, 249, 141, 221, 186},
|
||||
|
||||
MainMem: 208,
|
||||
SwapMem: 186,
|
||||
MainMem: 208,
|
||||
SwapMem: 186,
|
||||
|
||||
ProcCursor: 197,
|
||||
ProcCursor: 197,
|
||||
|
||||
Sparkline: 81,
|
||||
Sparkline: 81,
|
||||
|
||||
DiskBar: 102,
|
||||
DiskBar: 102,
|
||||
|
||||
TempLow: 70,
|
||||
TempHigh: 208,
|
||||
TempLow: 70,
|
||||
TempHigh: 208,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,28 +11,30 @@
|
|||
|
||||
package colorschemes
|
||||
|
||||
var Nord = Colorscheme{
|
||||
Name: "A Nord Approximation",
|
||||
Author: "@jrswab",
|
||||
Fg: 254, // lightest
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("nord", Colorscheme{
|
||||
Name: "A Nord Approximation",
|
||||
Author: "@jrswab",
|
||||
Fg: 254, // lightest
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: 254,
|
||||
BorderLine: 96, // Purple
|
||||
BorderLabel: 254,
|
||||
BorderLine: 96, // Purple
|
||||
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
CPULines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
BattLines: []int{4, 3, 2, 1, 5, 6, 7, 8},
|
||||
|
||||
MainMem: 172, // Orange
|
||||
SwapMem: 221, // yellow
|
||||
MainMem: 172, // Orange
|
||||
SwapMem: 221, // yellow
|
||||
|
||||
ProcCursor: 31, // blue (nord9)
|
||||
ProcCursor: 31, // blue (nord9)
|
||||
|
||||
Sparkline: 31,
|
||||
Sparkline: 31,
|
||||
|
||||
DiskBar: 254,
|
||||
DiskBar: 254,
|
||||
|
||||
TempLow: 64, // green
|
||||
TempHigh: 167, // red
|
||||
TempLow: 64, // green
|
||||
TempHigh: 167, // red
|
||||
})
|
||||
}
|
||||
|
|
43
colorschemes/registry.go
Normal file
43
colorschemes/registry.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package colorschemes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var registry map[string]Colorscheme
|
||||
|
||||
func FromName(confDir string, c string) (Colorscheme, error) {
|
||||
cs, ok := registry[c]
|
||||
if !ok {
|
||||
cs, err := getCustomColorscheme(confDir, c)
|
||||
if err != nil {
|
||||
return cs, err
|
||||
}
|
||||
}
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func register(name string, c Colorscheme) {
|
||||
if registry == nil {
|
||||
registry = make(map[string]Colorscheme)
|
||||
}
|
||||
registry[name] = c
|
||||
}
|
||||
|
||||
// getCustomColorscheme tries to read a custom json colorscheme from <configDir>/<name>.json
|
||||
func getCustomColorscheme(confDir string, name string) (Colorscheme, error) {
|
||||
var cs Colorscheme
|
||||
filePath := filepath.Join(confDir, name+".json")
|
||||
dat, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
return cs, fmt.Errorf("failed to read colorscheme file: %v", err)
|
||||
}
|
||||
err = json.Unmarshal(dat, &cs)
|
||||
if err != nil {
|
||||
return cs, fmt.Errorf("failed to parse colorscheme file: %v", err)
|
||||
}
|
||||
return cs, nil
|
||||
}
|
|
@ -3,26 +3,28 @@ package colorschemes
|
|||
// This is a neutral version of the Solarized 256-color palette. The exception
|
||||
// is that the one grey color uses the average of base0 and base00, which are
|
||||
// already middle of the road.
|
||||
var Solarized = Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("solarized", Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: -1,
|
||||
BorderLine: 37,
|
||||
BorderLabel: -1,
|
||||
BorderLine: 37,
|
||||
|
||||
CPULines: []int{61, 33, 37, 64, 125, 160, 166, 136},
|
||||
CPULines: []int{61, 33, 37, 64, 125, 160, 166, 136},
|
||||
|
||||
BattLines: []int{61, 33, 37, 64, 125, 160, 166, 136},
|
||||
BattLines: []int{61, 33, 37, 64, 125, 160, 166, 136},
|
||||
|
||||
MainMem: 125,
|
||||
SwapMem: 166,
|
||||
MainMem: 125,
|
||||
SwapMem: 166,
|
||||
|
||||
ProcCursor: 136,
|
||||
ProcCursor: 136,
|
||||
|
||||
Sparkline: 33,
|
||||
Sparkline: 33,
|
||||
|
||||
DiskBar: 243,
|
||||
DiskBar: 243,
|
||||
|
||||
TempLow: 64,
|
||||
TempHigh: 160,
|
||||
TempLow: 64,
|
||||
TempHigh: 160,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,26 +2,28 @@ package colorschemes
|
|||
|
||||
// This scheme assumes the terminal already uses Solarized. Only DiskBar is
|
||||
// different between dark/light.
|
||||
var Solarized16Dark = Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("solarized16dark", Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: -1,
|
||||
BorderLine: 6,
|
||||
BorderLabel: -1,
|
||||
BorderLine: 6,
|
||||
|
||||
CPULines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
CPULines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
|
||||
BattLines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
BattLines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
|
||||
MainMem: 5,
|
||||
SwapMem: 9,
|
||||
MainMem: 5,
|
||||
SwapMem: 9,
|
||||
|
||||
ProcCursor: 4,
|
||||
ProcCursor: 4,
|
||||
|
||||
Sparkline: 4,
|
||||
Sparkline: 4,
|
||||
|
||||
DiskBar: 12, // base0
|
||||
DiskBar: 12, // base0
|
||||
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,26 +2,28 @@ package colorschemes
|
|||
|
||||
// This scheme assumes the terminal already uses Solarized. Only DiskBar is
|
||||
// different between dark/light.
|
||||
var Solarized16Light = Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("solarized16light", Colorscheme{
|
||||
Fg: -1,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: -1,
|
||||
BorderLine: 6,
|
||||
BorderLabel: -1,
|
||||
BorderLine: 6,
|
||||
|
||||
CPULines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
CPULines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
|
||||
BattLines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
BattLines: []int{13, 4, 6, 2, 5, 1, 9, 3},
|
||||
|
||||
MainMem: 5,
|
||||
SwapMem: 9,
|
||||
MainMem: 5,
|
||||
SwapMem: 9,
|
||||
|
||||
ProcCursor: 4,
|
||||
ProcCursor: 4,
|
||||
|
||||
Sparkline: 4,
|
||||
Sparkline: 4,
|
||||
|
||||
DiskBar: 11, // base00
|
||||
DiskBar: 11, // base00
|
||||
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
TempLow: 2,
|
||||
TempHigh: 1,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
package colorschemes
|
||||
|
||||
var Vice = Colorscheme{
|
||||
Fg: 231,
|
||||
Bg: -1,
|
||||
func init() {
|
||||
register("vice", Colorscheme{
|
||||
Fg: 231,
|
||||
Bg: -1,
|
||||
|
||||
BorderLabel: 123,
|
||||
BorderLine: 102,
|
||||
BorderLabel: 123,
|
||||
BorderLine: 102,
|
||||
|
||||
CPULines: []int{212, 218, 123, 159, 229, 158, 183, 146},
|
||||
CPULines: []int{212, 218, 123, 159, 229, 158, 183, 146},
|
||||
|
||||
BattLines: []int{212, 218, 123, 159, 229, 158, 183, 146},
|
||||
BattLines: []int{212, 218, 123, 159, 229, 158, 183, 146},
|
||||
|
||||
MainMem: 201,
|
||||
SwapMem: 97,
|
||||
MainMem: 201,
|
||||
SwapMem: 97,
|
||||
|
||||
ProcCursor: 159,
|
||||
ProcCursor: 159,
|
||||
|
||||
Sparkline: 183,
|
||||
Sparkline: 183,
|
||||
|
||||
DiskBar: 158,
|
||||
DiskBar: 158,
|
||||
|
||||
TempLow: 49,
|
||||
TempHigh: 197,
|
||||
TempLow: 49,
|
||||
TempHigh: 197,
|
||||
})
|
||||
}
|
||||
|
|
91
config.go
91
config.go
|
@ -1,7 +1,11 @@
|
|||
package gotop
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xxxserxxx/gotop/colorschemes"
|
||||
|
@ -29,9 +33,92 @@ type Config struct {
|
|||
UpdateInterval time.Duration
|
||||
AverageLoad bool
|
||||
PercpuLoad bool
|
||||
TempScale widgets.TempScale
|
||||
Statusbar bool
|
||||
TempScale widgets.TempScale
|
||||
NetInterface string
|
||||
Layout io.Reader
|
||||
Layout string
|
||||
MaxLogSize int64
|
||||
}
|
||||
|
||||
func Parse(in io.Reader, conf *Config) error {
|
||||
r := bufio.NewScanner(in)
|
||||
var lineNo int
|
||||
for r.Scan() {
|
||||
l := strings.TrimSpace(r.Text())
|
||||
kv := strings.Split(l, "=")
|
||||
if len(kv) != 2 {
|
||||
return fmt.Errorf("bad config file syntax; should be KEY=VALUE, was %s", l)
|
||||
}
|
||||
key := strings.ToLower(kv[0])
|
||||
switch key {
|
||||
default:
|
||||
return fmt.Errorf("invalid config option %s", key)
|
||||
case "configdir":
|
||||
conf.ConfigDir = kv[1]
|
||||
case "logdir":
|
||||
conf.LogDir = kv[1]
|
||||
case "logfile":
|
||||
conf.LogFile = kv[1]
|
||||
case "graphhorizontalscale":
|
||||
iv, err := strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.GraphHorizontalScale = iv
|
||||
case "helpvisible":
|
||||
bv, err := strconv.ParseBool(kv[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("line %d: %v", lineNo, err)
|
||||
}
|
||||
conf.HelpVisible = bv
|
||||
case "colorscheme":
|
||||
cs, err := colorschemes.FromName(conf.ConfigDir, kv[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("line %d: %v", lineNo, err)
|
||||
}
|
||||
conf.Colorscheme = cs
|
||||
case "updateinterval":
|
||||
iv, err := strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.UpdateInterval = time.Duration(iv)
|
||||
case "averagecpu":
|
||||
bv, err := strconv.ParseBool(kv[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("line %d: %v", lineNo, err)
|
||||
}
|
||||
conf.AverageLoad = bv
|
||||
case "percpuload":
|
||||
bv, err := strconv.ParseBool(kv[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("line %d: %v", lineNo, err)
|
||||
}
|
||||
conf.PercpuLoad = bv
|
||||
case "tempscale":
|
||||
iv, err := strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.TempScale = widgets.TempScale(iv)
|
||||
case "statusbar":
|
||||
bv, err := strconv.ParseBool(kv[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("line %d: %v", lineNo, err)
|
||||
}
|
||||
conf.Statusbar = bv
|
||||
case "netinterface":
|
||||
conf.NetInterface = kv[1]
|
||||
case "layout":
|
||||
conf.Layout = kv[1]
|
||||
case "maxlogsize":
|
||||
iv, err := strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.MaxLogSize = int64(iv)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
11
config.json
Normal file
11
config.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"colorscheme": "default",
|
||||
"updateInterval": 1,
|
||||
"minimalMode": false,
|
||||
"averageLoad": false,
|
||||
"percpuLoad": false,
|
||||
"isFahrenheit": false,
|
||||
"battery": false,
|
||||
"statusbar": false,
|
||||
"netInterface": "NET_INTERFACE_ALL"
|
||||
}
|
87
config_test.go
Normal file
87
config_test.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package gotop
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/xxxserxxx/gotop/widgets"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
i string
|
||||
f func(c Config, e error)
|
||||
}{
|
||||
{
|
||||
i: "logdir",
|
||||
f: func(c Config, e error) {
|
||||
assert.Error(t, e, "invalid config syntax")
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "logdir=foo=bar",
|
||||
f: func(c Config, e error) {
|
||||
assert.NotNil(t, e)
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "foo=bar",
|
||||
f: func(c Config, e error) {
|
||||
assert.NotNil(t, e)
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "configdir=abc\nlogdir=bar\nlogfile=errors",
|
||||
f: func(c Config, e error) {
|
||||
assert.Nil(t, e, "unexpected error")
|
||||
assert.Equal(t, "abc", c.ConfigDir)
|
||||
assert.Equal(t, "bar", c.LogDir)
|
||||
assert.Equal(t, "errors", c.LogFile)
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "CONFIGDIR=abc\nloGdir=bar\nlogFILe=errors",
|
||||
f: func(c Config, e error) {
|
||||
assert.Nil(t, e, "unexpected error")
|
||||
assert.Equal(t, "abc", c.ConfigDir)
|
||||
assert.Equal(t, "bar", c.LogDir)
|
||||
assert.Equal(t, "errors", c.LogFile)
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "graphhorizontalscale=a",
|
||||
f: func(c Config, e error) {
|
||||
assert.Error(t, e, "expected invalid value for graphhorizontalscale")
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "helpvisible=a",
|
||||
f: func(c Config, e error) {
|
||||
assert.Error(t, e, "expected invalid value for helpvisible")
|
||||
},
|
||||
},
|
||||
{
|
||||
i: "helpvisible=true\nupdateinterval=30\naveragecpu=true\nPerCPULoad=true\ntempscale=100\nstatusbar=true\nnetinterface=eth0\nlayout=minimal\nmaxlogsize=200",
|
||||
f: func(c Config, e error) {
|
||||
assert.Nil(t, e, "unexpected error")
|
||||
assert.Equal(t, true, c.HelpVisible)
|
||||
assert.Equal(t, time.Duration(30), c.UpdateInterval)
|
||||
assert.Equal(t, true, c.AverageLoad)
|
||||
assert.Equal(t, true, c.PercpuLoad)
|
||||
assert.Equal(t, widgets.TempScale(100), c.TempScale)
|
||||
assert.Equal(t, true, c.Statusbar)
|
||||
assert.Equal(t, "eth0", c.NetInterface)
|
||||
assert.Equal(t, "minimal", c.Layout)
|
||||
assert.Equal(t, int64(200), c.MaxLogSize)
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
in := strings.NewReader(tc.i)
|
||||
c := Config{}
|
||||
e := Parse(in, &c)
|
||||
tc.f(c, e)
|
||||
}
|
||||
}
|
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
|||
github.com/gizak/termui/v3 v3.0.0
|
||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.4
|
||||
github.com/mitchellh/go-wordwrap 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.4.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -26,6 +26,8 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
|
|||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
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/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
|
Loading…
Reference in New Issue
Block a user