Mostly adds the -C option. KNOWN: it must be the first argument.
Doc
This commit is contained in:
parent
3487bbfaed
commit
3f26ebef76
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
54
config.go
54
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
|
||||
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 conf.ConfigFile == "" {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
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 {
|
||||
|
2
go.mod
2
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
|
||||
|
4
go.sum
4
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=
|
||||
|
@ -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(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user