summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean E. Russell <ser@ser1.net>2020-04-29 10:25:21 -0500
committerSean E. Russell <ser@ser1.net>2020-04-29 10:26:14 -0500
commit3f26ebef76575849f99c2097d38152317746b8e0 (patch)
tree210ebcc3018cdcf2a157ad7ceb6939dbf67b4f49
parent3487bbfaed43d53faf8d80c0fce488f113820660 (diff)
Mostly adds the -C option. KNOWN: it must be the first argument.
Doc
-rw-r--r--CHANGELOG.md1
-rw-r--r--cmd/gotop/main.go78
-rw-r--r--config.go52
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--widgets/temp.go1
6 files changed, 90 insertions, 48 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b40b415..3f6ac8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adds ability to filter reported temperatures (#92)
- Command line option to list layouts, paths, colorschemes, hotkeys, and filterable devices
- Adds ability to write out a configuration file
+- Adds a command for specifying the configuration file to use
### Changed
diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go
index 1cbc50d..25dd5b8 100644
--- a/cmd/gotop/main.go
+++ b/cmd/gotop/main.go
@@ -1,6 +1,8 @@
package main
import (
+ "bufio"
+ "flag"
"fmt"
"io"
"log"
@@ -18,7 +20,7 @@ import (
ui "github.com/gizak/termui/v3"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/shibukawa/configdir"
- flag "github.com/xxxserxxx/opflag"
+ "github.com/xxxserxxx/opflag"
"github.com/xxxserxxx/gotop/v4"
"github.com/xxxserxxx/gotop/v4/colorschemes"
@@ -50,49 +52,50 @@ var (
stderrLogger = log.New(os.Stderr, "", 0)
)
-func parseArgs(conf *gotop.Config) error {
+func parseArgs() error {
cds := conf.ConfigDir.QueryFolders(configdir.All)
cpaths := make([]string, len(cds))
for i, p := range cds {
cpaths[i] = p.Path
}
- help := flag.BoolP("help", "h", false, "Show this screen.")
- color := flag.StringP("color", "c", conf.Colorscheme.Name, "Set a colorscheme.")
- flag.IntVarP(&conf.GraphHorizontalScale, "graphscale", "S", conf.GraphHorizontalScale, "Graph scale factor, >0")
- version := flag.BoolP("version", "v", false, "Print version and exit.")
- versioN := flag.BoolP("", "V", false, "Print version and exit.")
- flag.BoolVarP(&conf.PercpuLoad, "percpu", "p", conf.PercpuLoad, "Show each CPU in the CPU widget.")
- flag.BoolVarP(&conf.AverageLoad, "averagecpu", "a", conf.AverageLoad, "Show average CPU in the CPU widget.")
- fahrenheit := flag.BoolP("fahrenheit", "f", conf.TempScale == 'F', "Show temperatures in fahrenheit.Show temperatures in fahrenheit.")
- flag.BoolVarP(&conf.Statusbar, "statusbar", "s", conf.Statusbar, "Show a statusbar with the time.")
- flag.DurationVarP(&conf.UpdateInterval, "rate", "r", conf.UpdateInterval, "Number of times per second to update CPU and Mem widgets.")
- flag.StringVarP(&conf.Layout, "layout", "l", conf.Layout, `Name of layout spec file for the UI. Use "-" to pipe.`)
- flag.StringVarP(&conf.NetInterface, "interface", "i", "all", "Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using `!`")
- flag.StringVarP(&conf.ExportPort, "export", "x", conf.ExportPort, "Enable metrics for export on the specified port.")
- flag.BoolVarP(&conf.Mbps, "mbps", "", conf.Mbps, "Show network rate as mbps.")
+ help := opflag.BoolP("help", "h", false, "Show this screen.")
+ color := opflag.StringP("color", "c", conf.Colorscheme.Name, "Set a colorscheme.")
+ opflag.IntVarP(&conf.GraphHorizontalScale, "graphscale", "S", conf.GraphHorizontalScale, "Graph scale factor, >0")
+ version := opflag.BoolP("version", "v", false, "Print version and exit.")
+ versioN := opflag.BoolP("", "V", false, "Print version and exit.")
+ opflag.BoolVarP(&conf.PercpuLoad, "percpu", "p", conf.PercpuLoad, "Show each CPU in the CPU widget.")
+ opflag.BoolVarP(&conf.AverageLoad, "averagecpu", "a", conf.AverageLoad, "Show average CPU in the CPU widget.")
+ fahrenheit := opflag.BoolP("fahrenheit", "f", conf.TempScale == 'F', "Show temperatures in fahrenheit.Show temperatures in fahrenheit.")
+ opflag.BoolVarP(&conf.Statusbar, "statusbar", "s", conf.Statusbar, "Show a statusbar with the time.")
+ opflag.DurationVarP(&conf.UpdateInterval, "rate", "r", conf.UpdateInterval, "Number of times per second to update CPU and Mem widgets.")
+ opflag.StringVarP(&conf.Layout, "layout", "l", conf.Layout, `Name of layout spec file for the UI. Use "-" to pipe.`)
+ opflag.StringVarP(&conf.NetInterface, "interface", "i", "all", "Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using `!`")
+ opflag.StringVarP(&conf.ExportPort, "export", "x", conf.ExportPort, "Enable metrics for export on the specified port.")
+ opflag.BoolVarP(&conf.Mbps, "mbps", "", conf.Mbps, "Show network rate as mbps.")
// FIXME Where did this go??
- //conf.Band = flag.IntP("bandwidth", "B", 100, "Specify the number of bits per seconds.")
- flag.BoolVar(&conf.Test, "test", conf.Test, "Runs tests and exits with success/failure code.")
- list := flag.String("list", "", `List <devices|layouts|colorschemes|paths|keys>
+ //conf.Band = opflag.IntP("bandwidth", "B", 100, "Specify the number of bits per seconds.")
+ opflag.BoolVar(&conf.Test, "test", conf.Test, "Runs tests and exits with success/failure code.")
+ opflag.StringP("", "C", "", "Config file to use instead of default (MUST BE FIRST ARGUMENT)")
+ list := opflag.String("list", "", `List <devices|layouts|colorschemes|paths|keys>
devices: Prints out device names for filterable widgets
layouts: Lists build-in layouts
colorschemes: Lists built-in colorschemes
paths: List out configuration file search paths
- widgets: Widgets that can be used in a layout
+ widgets: Widgets that can be used in a layout
keys: Show the keyboard bindings.`)
- wc := flag.Bool("write-config", false, "Write out a default config file.")
- flag.SortFlags = false
- flag.Usage = func() {
+ wc := opflag.Bool("write-config", false, "Write out a default config file.")
+ opflag.SortFlags = false
+ opflag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options]\n\nOptions:\n", os.Args[0])
- flag.PrintDefaults()
+ opflag.PrintDefaults()
}
- flag.Parse()
+ opflag.Parse()
if *version || *versioN {
fmt.Printf("gotop %s (%s)\n", Version, BuildDate)
os.Exit(0)
}
if *help {
- flag.Usage()
+ opflag.Usage()
os.Exit(0)
}
cs, err := colorschemes.FromName(conf.ConfigDir, *color)
@@ -331,14 +334,17 @@ func eventLoop(c gotop.Config, grid *layout.MyGrid) {
}
}
-// TODO: Add fans
-// TODO: mpd visualizer widget
+// TODO: @devices fans
+// TODO: @devices mpd visualizer
+// TODO: @devices color bars for memory, a-la bashtop
// TODO: Add tab completion for Linux https://gist.github.com/icholy/5314423
// TODO: state:merge #135 linux console font (cmatsuoka/console-font)
// 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: all of the go vet stuff, more unit tests, benchmarks, finish remote.
-// TODO: color bars for memory, a-la bashtop
+// TODO: more unit tests, benchmarks
+// TODO: README is getting long. Move to wiki.
// TODO: add verbose debugging option
+// TODO: find VMs for FreeBSD, etc for testing gotop
+// TODO: add README about extensions, and wiki page for writing extensions
func main() {
// For performance testing
//go func() {
@@ -359,15 +365,23 @@ func main() {
}
func run() int {
- conf := gotop.NewConfig()
+ conf = gotop.NewConfig()
// Find the config file; look in (1) local, (2) user, (3) global
+ // Check the last argument first
+ fs := flag.NewFlagSet("config", flag.ContinueOnError)
+ cfg := fs.String("C", "", "Config file")
+ fs.SetOutput(bufio.NewWriter(nil))
+ fs.Parse(os.Args[1:])
+ if *cfg != "" {
+ conf.ConfigFile = *cfg
+ }
err := conf.Load()
if err != nil {
fmt.Printf("failed to parse config file: %s\n", err)
return 2
}
// Override with command line arguments
- err = parseArgs(&conf)
+ err = parseArgs()
if err != nil {
fmt.Printf("parsing CLI args: %s\n", err)
return 2
diff --git a/config.go b/config.go
index 6a109e0..0cc5e61 100644
--- a/config.go
+++ b/config.go
@@ -5,7 +5,9 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"log"
+ "os"
"path/filepath"
"strconv"
"strings"
@@ -16,6 +18,9 @@ import (
"github.com/xxxserxxx/gotop/v4/widgets"
)
+// CONFFILE is the name of the default config file
+const CONFFILE = "gotop.conf"
+
type Config struct {
ConfigDir configdir.ConfigDir
GraphHorizontalScale int
@@ -34,6 +39,7 @@ type Config struct {
Temps []string
Test bool
ExtensionVars map[string]string
+ ConfigFile string
}
func NewConfig() Config {
@@ -54,21 +60,25 @@ func NewConfig() Config {
ExtensionVars: make(map[string]string),
}
conf.Colorscheme, _ = colorschemes.FromName(conf.ConfigDir, "default")
+ folder := conf.ConfigDir.QueryFolderContainsFile(CONFFILE)
+ if folder != nil {
+ conf.ConfigFile = filepath.Join(folder.Path, CONFFILE)
+ }
return conf
}
func (conf *Config) Load() error {
var in []byte
+ if conf.ConfigFile == "" {
+ return nil
+ }
var err error
- cfn := "gotop.conf"
- folder := conf.ConfigDir.QueryFolderContainsFile(cfn)
- if folder != nil {
- if in, err = folder.ReadFile(cfn); err != nil {
- return err
- }
- } else {
+ if _, err = os.Stat(conf.ConfigFile); os.IsNotExist(err) {
return nil
}
+ if in, err = ioutil.ReadFile(conf.ConfigFile); err != nil {
+ return err
+ }
return load(bytes.NewReader(in), conf)
}
@@ -169,21 +179,35 @@ func load(in io.Reader, conf *Config) error {
return nil
}
+// Write serializes the configuration to a file.
+// The configuration written is based on the loaded configuration, plus any
+// command-line changes, so it can be used to update an existing configuration
+// file. The file will be written to the specificed `--config` argument file,
+// if one is set; otherwise, it'll create one in the user's config directory.
func (conf *Config) Write() (string, error) {
- cfn := "gotop.conf"
- ds := conf.ConfigDir.QueryFolders(configdir.Global)
- if len(ds) == 0 {
- ds = conf.ConfigDir.QueryFolders(configdir.Local)
+ var dir *configdir.Config
+ var file string = CONFFILE
+ if conf.ConfigFile == "" {
+ ds := conf.ConfigDir.QueryFolders(configdir.Global)
if len(ds) == 0 {
- return "", fmt.Errorf("error locating config folders")
+ ds = conf.ConfigDir.QueryFolders(configdir.Local)
+ if len(ds) == 0 {
+ return "", fmt.Errorf("error locating config folders")
+ }
}
+ ds[0].CreateParentDir(CONFFILE)
+ dir = ds[0]
+ } else {
+ dir = &configdir.Config{}
+ dir.Path = filepath.Dir(conf.ConfigFile)
+ file = filepath.Base(conf.ConfigFile)
}
marshalled := marshal(conf)
- err := ds[0].WriteFile(cfn, marshalled)
+ err := dir.WriteFile(file, marshalled)
if err != nil {
return "", err
}
- return filepath.Join(ds[0].Path, cfn), nil
+ return filepath.Join(dir.Path, file), nil
}
func marshal(c *Config) []byte {
diff --git a/go.mod b/go.mod
index 29a5919..d0867eb 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
github.com/stretchr/testify v1.4.0
github.com/xxxserxxx/iSMC v1.0.1
- github.com/xxxserxxx/opflag v1.0.3
+ github.com/xxxserxxx/opflag v1.0.5
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c // indirect
golang.org/x/tools/gopls v0.4.0 // indirect
diff --git a/go.sum b/go.sum
index 2410a27..f165c4a 100644
--- a/go.sum
+++ b/go.sum
@@ -119,6 +119,10 @@ github.com/xxxserxxx/opflag v1.0.2 h1:TanW4Ck/RNal4fP2VVAvhEu7eBq4z+9hhGq9Q8OTq6
github.com/xxxserxxx/opflag v1.0.2/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4=
github.com/xxxserxxx/opflag v1.0.3 h1:ugsBWZtSXUaMLEjPLW0WKGjq/gsrc0GpZYbCJY6ZHVY=
github.com/xxxserxxx/opflag v1.0.3/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4=
+github.com/xxxserxxx/opflag v1.0.4 h1:g979b8oReAERfDKFTTwdvAYIarFxpVYOzYrHa/hMvNs=
+github.com/xxxserxxx/opflag v1.0.4/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4=
+github.com/xxxserxxx/opflag v1.0.5 h1:2H4Qtl1qe+dSkEcGt+fBe2mQ8z14MgkWPqcLaoa6k90=
+github.com/xxxserxxx/opflag v1.0.5/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
diff --git a/widgets/temp.go b/widgets/temp.go
index 05ad3c1..f2b0f93 100644
--- a/widgets/temp.go
+++ b/widgets/temp.go
@@ -31,7 +31,6 @@ type TempWidget struct {
tempsMetric map[string]prometheus.Gauge
}
-// TODO: state:deferred 156 Added temperatures for NVidia GPUs (azak-azkaran/master). Crashes on non-nvidia machines.
func NewTempWidget(tempScale TempScale, filter []string) *TempWidget {
self := &TempWidget{
Block: ui.NewBlock(),