From 5ada5315d940038fcd83777b1e73797bbbada108 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Thu, 23 Apr 2020 10:41:20 -0500 Subject: [PATCH] Fixes #92, configurable temps; help text & docs clean-up; versions are now built into binaries at compile time; clean up old extensions params; adds --list command; adds --write-config command; fixes bug in colorscheme loading; fixes bug in Colorschemes -- all had empty Name attrs; adds ability to list devices. --- .github/workflows/release.yml | 2 - CHANGELOG.md | 2 + README.md | 61 +++++++++++++++++ cmd/gotop/main.go | 120 +++++++++++++++++++--------------- colorschemes/registry.go | 1 + config.go | 103 ++++++++++++++++++++++------- devices/devices.go | 21 ++++++ devices/temp_darwin.go | 15 ++++- devices/temp_freebsd.go | 12 ++++ devices/temp_linux.go | 30 +++++++-- devices/temp_openbsd.go | 5 +- devices/temp_windows.go | 19 +++++- layout/layout.go | 2 +- widgets/disk.go | 2 + widgets/temp.go | 11 +++- 15 files changed, 316 insertions(+), 90 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 191b144..6390f46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,5 +29,3 @@ jobs: repository: xxxserxxx/gotop-linux event-type: my-release client-payload: '{"tag": "${{ steps.tag_name.outputs.tag }}"}' - -# TODO: Build the plugins too diff --git a/CHANGELOG.md b/CHANGELOG.md index f61b2c9..5b67eab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ignore lines matching `/^#.*/` in layout files. - Instructions for Gentoo (thanks @tormath1!) - Graph labels that don't fit (vertically) in the window are now drawn in additional columns (#40) +- Adds ability to filter reported temperatures (#92) ### Changed @@ -44,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Memory line colors were inconsistently assigned (#91) - The disk code was truncating values instead of rounding (#90) - Temperatures on Darwin were all over the place, and wrong (#48) +- Config file loading from `~/.config/gotop` wasn't working ## [3.5.1] - 2020-04-09 diff --git a/README.md b/README.md index 5b3ce0f..fd37437 100644 --- a/README.md +++ b/README.md @@ -127,12 +127,30 @@ Move `gotop` to somewhere in your `$PATH`. - click to select process - mouse wheel to scroll through processes +### Config file + +Most command-line settings can be persisted into a configuration file. The config file is named `gotop.conf` and can be located in several places. The first place gotop will look is in the current directory; after this, the locations depend on the OS and distribution. On Linux using XDG, for instance, the home location of `~/.config/gotop/gotop.conf` is the second location. The last location is a system-wide global location, such as `/etc/gotop/gotop.conf`. The `-h` help command will print out all of the locations, in order. Command-line options override values in any config files, and only the first config file found is loaded. + +A configuration file can be created using the `--write-config` command-line argument. This will try to place the config file in the home config directory (the second location), but if it's unable to do so it'll write a file to the current directory. + +Config file changes can be made by combining command-line arguments with `--write-config`. For example, to persist the `solarized` theme, call: + +``` +gotop -c solarized --write-config +``` + ### Colorschemes gotop ships with a few colorschemes which can be set with the `-c` flag followed by the name of one. You can find all the colorschemes in the [colorschemes folder](./colorschemes). To make a custom colorscheme, check out the [template](./colorschemes/template.go) for instructions and then use [default.json](./colorschemes/default.json) as a starter. Then put the file at `~/.config/gotop/.json` and load it with `gotop -c `. Colorschemes PR's are welcome! +To list all built-in color schemes, call: + +``` +gotop --list colorschemes +``` + ### Layouts gotop can parse and render layouts from a specification file. The format is @@ -206,6 +224,49 @@ and these are separated by spaces. Yes, you're clever enough to break the layout algorithm, but if you try to build massive edifices, you're in for disappointment. +To list all built-in color schemes, call: + +``` +gotop --list layouts +``` + +### Device filtering + +Some devices have quite a number of data points; on OSX, for instance, there are dozens of temperature readings. These can be filtered through a configuration file. There is no command-line argument for this filter. + +The list will grow, but for now the only device that supports filtering is the temperature widget. The configuration entry is called `temperature`, and it contains an exact-match list of comma-separated values with no spaces. To see the list of valid values, run gotop with the `--list devices` command. Gotop will print out the type of device and the legal values. For example, on Linux: + +``` +$ gotop --list devices +Temperatures: + acpitz + nvme_composite + nvme_sensor1 + nvme_sensor2 + pch_cannonlake + coretemp_packageid0 + coretemp_core0 + coretemp_core1 + coretemp_core2 + coretemp_core3 + ath10k_hwmon +``` +You might then add the following line to the config file. First, find where gotop looks for config files: +``` +$ gotop -h | tail -n 6 +Colorschemes & layouts that are not built-in are searched for (in order) in: +/home/USER/workspace/gotop.d/gotop, /home/USER/.config/gotop, /etc/xdg/gotop +The first path in this list is always the cwd. The config file +'gotop.config' can also reside in one of these directories. + +Log files are stored in /home/ser/.cache/gotop/errors.log +``` +So you might use `/home/YOU/.config/gotop.conf`, and add (or modify) this line: +``` +temperatures=acpitz,coretemp_core0,ath10k_hwmon +``` +This will cause the temp widget to show only four of the eleven temps. + ### CLI Options Run `gotop -h` to see the list of all command line options. diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index f44d7a2..18525c6 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -8,6 +8,7 @@ import ( "os" "os/signal" "path/filepath" + "sort" "strconv" "strings" "syscall" @@ -20,6 +21,7 @@ import ( "github.com/xxxserxxx/gotop/v3" "github.com/xxxserxxx/gotop/v3/colorschemes" + "github.com/xxxserxxx/gotop/v3/devices" "github.com/xxxserxxx/gotop/v3/layout" "github.com/xxxserxxx/gotop/v3/logging" w "github.com/xxxserxxx/gotop/v3/widgets" @@ -37,8 +39,8 @@ const ( ) var ( - // TODO: Set this at compile time; having to check this in sucks. - Version = "3.6.dev" + Version = "0.0.0" + BuildDate = "Hadean" conf gotop.Config help *w.HelpMenu bar *w.StatusBar @@ -48,17 +50,14 @@ var ( // TODO: Add tab completion for Linux https://gist.github.com/icholy/5314423 // TODO: state:merge #135 linux console font (cmatsuoka/console-font) -// TODO: state:deferred 157 FreeBSD fixes & Nvidia GPU support (kraust/master). Significant CPU use impact for NVidia changes. -// TODO: Virtual devices from Prometeus metrics @feature // TODO: Abstract out the UI toolkit. mum4k/termdash, VladimirMarkelov/clui, gcla/gowid, rivo/tview, marcusolsson/tui-go might work better for some OS/Archs. Performance/memory use comparison would be interesting. -// TODO: Add fans func parseArgs(conf *gotop.Config) error { cds := conf.ConfigDir.QueryFolders(configdir.All) cpaths := make([]string, len(cds)) for i, p := range cds { cpaths[i] = p.Path } - usage := fmt.Sprintf(` + usage := fmt.Sprintln(` Usage: gotop [options] Options: @@ -77,40 +76,15 @@ Options: -l, --layout=NAME Name of layout spec file for the UI. Looks first in $XDG_CONFIG_HOME/gotop, then as a path. Use "-" to pipe. -i, --interface=NAME Select network interface [default: all]. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using ! -x, --export=PORT Enable metrics for export on the specified port. - -X, --extensions=NAMES Enables the listed extensions. This is a comma-separated list without the .so suffix. The current and config directories will be searched. --mbps Net widget shows mb(its)ps for RX/TX instead of scaled bytes per second. --test Runs tests and exits with success/failure code. - --print-paths List out the paths that gotop will look for gotop.conf, layouts, color schemes, and extensions. - --print-keys Show the keyboard bindings. - -Built-in layouts: - default - minimal - battery - kitchensink - -Colorschemes: - default - default-dark (for white background) - solarized - solarized16-dark - solarized16-light - monokai - vice - -Colorschemes and layouts that are not built-in are searched for (in order) in: -%s -The first path in this list is always the cwd. - -Log files are stored in %s - -`, strings.Join(cpaths, ", "), filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE)) - - var err error - conf.Colorscheme, err = colorschemes.FromName(conf.ConfigDir, "default") - if err != nil { - return err - } + --list + devices: Prints out device names for widgets supporting filters. + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out the paths that gotop will look for gotop.conf, layouts, and color schemes. + keys: Show the keyboard bindings. + --write-config Write out a sample config file, either to the home config location, or current directory. Command-line arguments specificed at the same time will overwrite values in the config file.`) args, err := docopt.ParseArgs(usage, os.Args[1:], Version) if err != nil { @@ -127,6 +101,7 @@ Log files are stored in %s } conf.Colorscheme = cs } + if args["--averagecpu"].(bool) { conf.AverageLoad, _ = args["--averagecpu"].(bool) } @@ -166,10 +141,6 @@ Log files are stored in %s if val, _ := args["--interface"]; val != nil { conf.NetInterface, _ = args["--interface"].(string) } - if val, _ := args["--extensions"]; val != nil { - exs, _ := args["--extensions"].(string) - conf.Extensions = strings.Split(exs, ",") - } if val, _ := args["--test"]; val != nil { conf.Test = val.(bool) } @@ -189,16 +160,35 @@ Log files are stored in %s if args["--mbps"].(bool) { conf.Mbps = true } - if args["--print-paths"].(bool) { - paths := make([]string, 0) - for _, d := range conf.ConfigDir.QueryFolders(configdir.All) { - paths = append(paths, d.Path) - } - fmt.Println(strings.Join(paths, "\n")) - os.Exit(0) - } - if args["--print-keys"].(bool) { - fmt.Println(` + if val, _ := args["--list"]; val != nil { + switch val { + case "layouts": + fmt.Println("Built-in layouts:") + fmt.Println("\tdefault") + fmt.Println("\tminimal") + fmt.Println("\tbattery") + fmt.Println("\tkitchensink") + case "colorschemes": + fmt.Println("Built-in colorschemes:") + fmt.Println("\tdefault") + fmt.Println("\tdefault-dark (for white background)") + fmt.Println("\tsolarized") + fmt.Println("\tsolarized16-dark") + fmt.Println("\tsolarized16-light") + fmt.Println("\tmonokai") + fmt.Println("\tvice") + case "paths": + fmt.Println("Loadable colorschemes & layouts, and the config file, are searched for, in order:") + paths := make([]string, 0) + for _, d := range conf.ConfigDir.QueryFolders(configdir.All) { + paths = append(paths, d.Path) + } + fmt.Println(strings.Join(paths, "\n")) + fmt.Printf("\nThe log file is in %s\n", filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE)) + case "devices": + listDevices() + case "keys": + fmt.Println(` Quit: q or Process navigation: k and : up @@ -227,6 +217,19 @@ CPU and Mem graph scaling: h: scale in l: scale out ?: toggles keybind help menu`) + default: + fmt.Printf("Unknown option \"%s\"; try layouts, colorschemes, or devices\n", val) + os.Exit(1) + } + os.Exit(0) + } + if args["--write-config"].(bool) { + path, err := conf.Write() + if err != nil { + fmt.Printf("Failed to write configuration file: %s\n", err) + os.Exit(1) + } + fmt.Printf("Config written to %s\n", path) os.Exit(0) } @@ -437,9 +440,11 @@ func makeConfig() gotop.Config { MaxLogSize: 5000000, Layout: "default", } + conf.Colorscheme, _ = colorschemes.FromName(conf.ConfigDir, "default") return conf } +// TODO: Add fans // TODO: mpd visualizer widget func main() { // This is just to make sure gotop returns a useful exit code, but also @@ -567,3 +572,14 @@ func runTests(conf gotop.Config) int { fmt.Printf("PASS") return 0 } + +func listDevices() { + ms := devices.Domains + sort.Strings(ms) + for _, m := range ms { + fmt.Printf("%s:\n", m) + for _, d := range devices.Devices(m) { + fmt.Printf("\t%s\n", d) + } + } +} diff --git a/colorschemes/registry.go b/colorschemes/registry.go index b6263c9..d120eb8 100644 --- a/colorschemes/registry.go +++ b/colorschemes/registry.go @@ -29,6 +29,7 @@ func register(name string, c Colorscheme) { if registry == nil { registry = make(map[string]Colorscheme) } + c.Name = name registry[name] = c } diff --git a/config.go b/config.go index 3d1ae38..7809918 100644 --- a/config.go +++ b/config.go @@ -2,10 +2,10 @@ package gotop import ( "bufio" + "bytes" "fmt" - "io" "log" - "os" + "path/filepath" "strconv" "strings" "time" @@ -15,7 +15,6 @@ import ( "github.com/xxxserxxx/gotop/v3/widgets" ) -// TODO: test, build, release [#119] [#120] [#121] type Config struct { ConfigDir configdir.ConfigDir @@ -32,30 +31,31 @@ type Config struct { Layout string MaxLogSize int64 ExportPort string - Extensions []string Mbps bool + Temps []string Test bool } func (conf *Config) Load() error { - var in io.Reader + var in []byte + var err error cfn := "gotop.conf" folder := conf.ConfigDir.QueryFolderContainsFile(cfn) if folder != nil { - // FIXME: Shouldn't this be looking in folder?? - if cf, err := os.Open(cfn); err == nil { - defer cf.Close() - } else { + if in, err = folder.ReadFile(cfn); err != nil { return err } } else { return nil } - r := bufio.NewScanner(in) + r := bufio.NewScanner(bytes.NewReader(in)) var lineNo int for r.Scan() { l := strings.TrimSpace(r.Text()) + if l[0] == '#' { + continue + } kv := strings.Split(l, "=") if len(kv) != 2 { return fmt.Errorf("bad config file syntax; should be KEY=VALUE, was %s", l) @@ -70,72 +70,125 @@ func (conf *Config) Load() error { log.Printf("logdir is deprecated. Ignored logdir=%s", kv[1]) case "logfile": log.Printf("logfile is deprecated. Ignored logfile=%s", kv[1]) - case "graphhorizontalscale": + case graphhorizontalscale: iv, err := strconv.Atoi(kv[1]) if err != nil { return err } conf.GraphHorizontalScale = iv - case "helpvisible": + case helpvisible: bv, err := strconv.ParseBool(kv[1]) if err != nil { return fmt.Errorf("line %d: %v", lineNo, err) } conf.HelpVisible = bv - case "colorscheme": + 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": + case updateinterval: iv, err := strconv.Atoi(kv[1]) if err != nil { return err } conf.UpdateInterval = time.Duration(iv) - case "averagecpu": + case averagecpu: bv, err := strconv.ParseBool(kv[1]) if err != nil { return fmt.Errorf("line %d: %v", lineNo, err) } conf.AverageLoad = bv - case "percpuload": + case percpuload: bv, err := strconv.ParseBool(kv[1]) if err != nil { return fmt.Errorf("line %d: %v", lineNo, err) } conf.PercpuLoad = bv - case "tempscale": + case tempscale: iv, err := strconv.Atoi(kv[1]) if err != nil { return err } conf.TempScale = widgets.TempScale(iv) - case "statusbar": + case statusbar: bv, err := strconv.ParseBool(kv[1]) if err != nil { return fmt.Errorf("line %d: %v", lineNo, err) } conf.Statusbar = bv - case "netinterface": + case netinterface: conf.NetInterface = kv[1] - case "layout": + case layout: conf.Layout = kv[1] - case "maxlogsize": + case maxlogsize: iv, err := strconv.Atoi(kv[1]) if err != nil { return err } conf.MaxLogSize = int64(iv) - case "export": + case export: conf.ExportPort = kv[1] - case "extensions": - conf.Extensions = strings.Split(kv[1], ",") - case "mbps": + case mbps: conf.Mbps = true + case temperatures: + conf.Temps = strings.Split(kv[1], ",") } } return nil } + +func (c *Config) Write() (string, error) { + cfn := "gotop.conf" + ds := c.ConfigDir.QueryFolders(configdir.Global) + if len(ds) == 0 { + ds = c.ConfigDir.QueryFolders(configdir.Local) + if len(ds) == 0 { + return "", fmt.Errorf("error locating config folders") + } + } + marshalled := marshal(c) + err := ds[0].WriteFile(cfn, marshalled) + if err != nil { + return "", err + } + return filepath.Join(ds[0].Path, cfn), nil +} + +func marshal(c *Config) []byte { + buff := bytes.NewBuffer(nil) + fmt.Fprintf(buff, "%s=%d\n", graphhorizontalscale, c.GraphHorizontalScale) + fmt.Fprintf(buff, "%s=%t\n", helpvisible, c.HelpVisible) + fmt.Fprintf(buff, "%s=%s\n", colorscheme, c.Colorscheme.Name) + fmt.Fprintf(buff, "%s=%d\n", updateinterval, c.UpdateInterval) + fmt.Fprintf(buff, "%s=%t\n", averagecpu, c.AverageLoad) + fmt.Fprintf(buff, "%s=%t\n", percpuload, c.PercpuLoad) + fmt.Fprintf(buff, "%s=%d\n", tempscale, c.TempScale) + fmt.Fprintf(buff, "%s=%t\n", statusbar, c.Statusbar) + fmt.Fprintf(buff, "%s=%s\n", netinterface, c.NetInterface) + fmt.Fprintf(buff, "%s=%s\n", layout, c.Layout) + fmt.Fprintf(buff, "%s=%d\n", maxlogsize, c.MaxLogSize) + fmt.Fprintf(buff, "%s=%s\n", export, c.ExportPort) + fmt.Fprintf(buff, "%s=%t\n", mbps, c.Mbps) + fmt.Fprintf(buff, "%s=%s\n", temperatures, strings.Join(c.Temps, ",")) + return buff.Bytes() +} + +const ( + graphhorizontalscale = "graphhorizontalscale" + helpvisible = "helpvisible" + colorscheme = "colorscheme" + updateinterval = "updateinterval" + averagecpu = "averagecpu" + percpuload = "percpuload" + tempscale = "tempscale" + statusbar = "statusbar" + netinterface = "netinterface" + layout = "layout" + maxlogsize = "maxlogsize" + export = "metricsexportport" + mbps = "mbps" + temperatures = "temperatures" +) diff --git a/devices/devices.go b/devices/devices.go index 91a8815..efdc404 100644 --- a/devices/devices.go +++ b/devices/devices.go @@ -2,7 +2,13 @@ package devices import "log" +const ( + Temperatures = "Temperatures" +) + +var Domains []string = []string{Temperatures} var shutdownFuncs []func() error +var _devs map[string][]string // RegisterShutdown stores a function to be called by gotop on exit, allowing // extensions to properly release resources. Extensions should register a @@ -24,3 +30,18 @@ func Shutdown() { } } } + +func RegisterDeviceList(typ string, f func() []string) { + if _devs == nil { + _devs = make(map[string][]string) + } + if ls, ok := _devs[typ]; ok { + _devs[typ] = append(ls, f()...) + return + } + _devs[typ] = f() +} + +func Devices(domain string) []string { + return _devs[domain] +} diff --git a/devices/temp_darwin.go b/devices/temp_darwin.go index 4e068a4..fe98fc2 100644 --- a/devices/temp_darwin.go +++ b/devices/temp_darwin.go @@ -6,6 +6,7 @@ import smc "github.com/xxxserxxx/iSMC" func init() { RegisterTemp(update) + RegisterDeviceList(Temperatures, devs) ts = make(map[string]float32) } @@ -17,7 +18,19 @@ func update(temps map[string]int) map[string]error { return map[string]error{"temps": err} } for k, v := range ts { - temps[k] = int(v + 0.5) + if _, ok := temps[k]; ok { + temps[k] = int(v + 0.5) + } } return nil } + +// TODO: Set reasonable default devices +// CPU (TC[01]P), GPU (TG0P), Memory (Ts0S) and Disk (TH0P) +func devs() []string { + rv := make([]string, len(smc.AppleTemp)) + for i, v := range smc.AppleTemp { + rv[i] = v.Desc + } + return rv +} diff --git a/devices/temp_freebsd.go b/devices/temp_freebsd.go index 54355fc..a0277a6 100644 --- a/devices/temp_freebsd.go +++ b/devices/temp_freebsd.go @@ -12,6 +12,7 @@ import ( func init() { RegisterTemp(update) + RegisterDeviceList(Temperatures, devs) } var sensorOIDS = map[string]string{ @@ -23,6 +24,9 @@ func update(temps map[string]int) map[string]error { var errors map[string]error for k, v := range sensorOIDS { + if _, ok := temps[k]; !ok { + continue + } output, err := exec.Command("sysctl", "-n", k).Output() if err != nil { errors[v] = err @@ -43,3 +47,11 @@ func update(temps map[string]int) map[string]error { return errors } + +func devs() []string { + rv := make([]string, 0, len(sensorOIDS)) + for k, _ := range sensorOIDS { + rv = append(rv, k) + } + return rv +} diff --git a/devices/temp_linux.go b/devices/temp_linux.go index ec4ff95..2ca01f5 100644 --- a/devices/temp_linux.go +++ b/devices/temp_linux.go @@ -10,6 +10,7 @@ import ( func init() { RegisterTemp(getTemps) + RegisterDeviceList(Temperatures, devs) } func getTemps(temps map[string]int) map[string]error { @@ -18,12 +19,31 @@ func getTemps(temps map[string]int) map[string]error { return map[string]error{"psHost": err} } for _, sensor := range sensors { - // only sensors with input in their name are giving us live temp info - if strings.Contains(sensor.SensorKey, "input") && sensor.Temperature != 0 { - // removes '_input' from the end of the sensor name - label := sensor.SensorKey[:strings.Index(sensor.SensorKey, "_input")] - temps[label] = int(sensor.Temperature) + // removes '_input' from the end of the sensor name + idx := strings.Index(sensor.SensorKey, "_input") + if idx >= 0 { + label := sensor.SensorKey[:idx] + if _, ok := temps[label]; ok { + temps[label] = int(sensor.Temperature) + } } } return nil } + +func devs() []string { + sensors, err := psHost.SensorsTemperatures() + if err != nil { + return []string{} + } + rv := make([]string, 0, len(sensors)) + for _, sensor := range sensors { + // only sensors with input in their name are giving us live temp info + if strings.Contains(sensor.SensorKey, "input") && sensor.Temperature != 0 { + // removes '_input' from the end of the sensor name + label := sensor.SensorKey[:strings.Index(sensor.SensorKey, "_input")] + rv = append(rv, label) + } + } + return rv +} diff --git a/devices/temp_openbsd.go b/devices/temp_openbsd.go index 410cc4a..d889d78 100644 --- a/devices/temp_openbsd.go +++ b/devices/temp_openbsd.go @@ -15,6 +15,7 @@ import ( "unsafe" ) +// TODO: Add filtering. Getting the temperature sensor names is non-trivial for OpenBSD, and until I can test it, leave it unimplemented func init() { RegisterTemp(update) } @@ -66,7 +67,9 @@ func getTemp(temps map[string]int, mib []C.int, mlen int, snsrdev *C.struct_sens key := C.GoString(&snsrdev.xname[0]) + ".temp" + strconv.Itoa(index) temp := int((snsr.value - 273150000.0) / 1000000.0) - temps[key] = temp + if _, ok := temps[key]; ok { + temps[key] = temp + } } } } diff --git a/devices/temp_windows.go b/devices/temp_windows.go index 230e902..54fe0eb 100644 --- a/devices/temp_windows.go +++ b/devices/temp_windows.go @@ -8,6 +8,7 @@ import ( func init() { RegisterTemp(update) + RegisterDeviceList(Temperatures, devs) } func update(temps map[string]int) map[string]error { @@ -16,9 +17,23 @@ func update(temps map[string]int) map[string]error { return map[string]error{"gopsutil": err} } for _, sensor := range sensors { - if sensor.Temperature != 0 { - temps[sensor.SensorKey] = int(sensor.Temperature) + if _, ok := temps[sensor.SensorKey]; ok { + temps[sensor.SensorKey] = int(sensor.Temperature + 0.5) } } return nil } + +func devs() []string { + sensors, err := psHost.SensorsTemperatures() + if err != nil { + return []string{} + } + rv := make([]string, 0, len(sensors)) + for _, sensor := range sensors { + if sensor.Temperature != 0 { + rv = append(rv, sensor.SensorKey) + } + } + return rv +} diff --git a/layout/layout.go b/layout/layout.go index c59e718..6fb7c58 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -177,7 +177,7 @@ func makeWidget(c gotop.Config, widRule widgetRule) interface{} { assignColors(b.Data, c.Colorscheme.BattLines, b.LineColors) w = b case "temp": - t := widgets.NewTempWidget(c.TempScale) + t := widgets.NewTempWidget(c.TempScale, c.Temps) t.TempLowColor = ui.Color(c.Colorscheme.TempLow) t.TempHighColor = ui.Color(c.Colorscheme.TempHigh) w = t diff --git a/widgets/disk.go b/widgets/disk.go index b53df9d..e2b3eb2 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -32,6 +32,8 @@ type DiskWidget struct { metric map[string]prometheus.Gauge } +// TODO: Add filtering +// TODO: Abstract out device from widget func NewDiskWidget() *DiskWidget { self := &DiskWidget{ Table: ui.NewTable(), diff --git a/widgets/temp.go b/widgets/temp.go index 1b9f650..3e1b067 100644 --- a/widgets/temp.go +++ b/widgets/temp.go @@ -32,7 +32,7 @@ type TempWidget struct { } // TODO: state:deferred 156 Added temperatures for NVidia GPUs (azak-azkaran/master). Crashes on non-nvidia machines. -func NewTempWidget(tempScale TempScale) *TempWidget { +func NewTempWidget(tempScale TempScale, filter []string) *TempWidget { self := &TempWidget{ Block: ui.NewBlock(), updateInterval: time.Second * 5, @@ -41,6 +41,15 @@ func NewTempWidget(tempScale TempScale) *TempWidget { TempScale: tempScale, } self.Title = " Temperatures " + if len(filter) > 0 { + for _, t := range filter { + self.Data[t] = 0 + } + } else { + for _, t := range devices.Devices(devices.Temperatures) { + self.Data[t] = 0 + } + } if tempScale == Fahrenheit { self.TempThreshold = utils.CelsiusToFahrenheit(self.TempThreshold)