mirror of
https://github.com/bcicen/ctop.git
synced 2024-08-30 18:23:19 +00:00
refactor column config
This commit is contained in:
parent
ee25f80a9c
commit
118b89240d
138
config/columns.go
Normal file
138
config/columns.go
Normal file
@ -0,0 +1,138 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// defaults
|
||||
var defaultColumns = []Column{
|
||||
Column{
|
||||
Name: "status",
|
||||
Label: "Status Indicator",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "name",
|
||||
Label: "Container Name",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "id",
|
||||
Label: "Container ID",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "cpu",
|
||||
Label: "CPU Usage",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "mem",
|
||||
Label: "Memory Usage",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "net",
|
||||
Label: "Network RX/TX",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "io",
|
||||
Label: "Disk IO Read/Write",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "pids",
|
||||
Label: "Container PID Count",
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
type Column struct {
|
||||
Name string
|
||||
Label string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// ColumnsString returns an ordered and comma-delimited string of currently enabled Columns
|
||||
func ColumnsString() string { return strings.Join(EnabledColumns(), ",") }
|
||||
|
||||
// EnabledColumns returns an ordered array of enabled column names
|
||||
func EnabledColumns() (a []string) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
for _, col := range GlobalColumns {
|
||||
if col.Enabled {
|
||||
a = append(a, col.Name)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// ColumnLeft moves the column with given name up one position, if possible
|
||||
func ColumnLeft(name string) {
|
||||
idx := colIndex(name)
|
||||
if idx > 0 {
|
||||
swapCols(idx, idx-1)
|
||||
}
|
||||
}
|
||||
|
||||
// ColumnRight moves the column with given name up one position, if possible
|
||||
func ColumnRight(name string) {
|
||||
idx := colIndex(name)
|
||||
if idx < len(GlobalColumns)-1 {
|
||||
swapCols(idx, idx+1)
|
||||
}
|
||||
}
|
||||
|
||||
// Set Column order and enabled status from one or more provided Column names
|
||||
func SetColumns(names []string) {
|
||||
var (
|
||||
n int
|
||||
curColStr = ColumnsString()
|
||||
newColumns = make([]*Column, len(GlobalColumns))
|
||||
)
|
||||
|
||||
lock.Lock()
|
||||
|
||||
// add enabled columns by name
|
||||
for _, name := range names {
|
||||
newColumns[n] = popColumn(name)
|
||||
newColumns[n].Enabled = true
|
||||
n++
|
||||
}
|
||||
|
||||
// extend with omitted columns as disabled
|
||||
for _, col := range GlobalColumns {
|
||||
newColumns[n] = col
|
||||
newColumns[n].Enabled = false
|
||||
n++
|
||||
}
|
||||
|
||||
GlobalColumns = newColumns
|
||||
lock.Unlock()
|
||||
|
||||
log.Noticef("config change [columns]: %s -> %s", curColStr, ColumnsString())
|
||||
}
|
||||
|
||||
func swapCols(i, j int) { GlobalColumns[i], GlobalColumns[j] = GlobalColumns[j], GlobalColumns[i] }
|
||||
|
||||
func popColumn(name string) *Column {
|
||||
idx := colIndex(name)
|
||||
if idx < 0 {
|
||||
panic("no such column name: " + name)
|
||||
}
|
||||
col := GlobalColumns[idx]
|
||||
GlobalColumns = append(GlobalColumns[:idx], GlobalColumns[idx+1:]...)
|
||||
return col
|
||||
}
|
||||
|
||||
// return index of column with given name, if any
|
||||
func colIndex(name string) int {
|
||||
for n, c := range GlobalColumns {
|
||||
if c.Name == name {
|
||||
return n
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
@ -16,17 +16,18 @@ var (
|
||||
type File struct {
|
||||
Options map[string]string `toml:"options"`
|
||||
Toggles map[string]bool `toml:"toggles"`
|
||||
Widgets []Widget `toml:"widget"`
|
||||
}
|
||||
|
||||
func exportConfig() File {
|
||||
// update columns param from working config
|
||||
Update("columns", ColumnsString())
|
||||
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
|
||||
c := File{
|
||||
Options: make(map[string]string),
|
||||
Toggles: make(map[string]bool),
|
||||
Widgets: make([]Widget, len(GlobalWidgets)),
|
||||
}
|
||||
|
||||
for _, p := range GlobalParams {
|
||||
@ -35,9 +36,6 @@ func exportConfig() File {
|
||||
for _, sw := range GlobalSwitches {
|
||||
c.Toggles[sw.Key] = sw.Val
|
||||
}
|
||||
for n, w := range GlobalWidgets {
|
||||
c.Widgets[n] = *w
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
@ -54,15 +52,21 @@ func Read() error {
|
||||
if _, err := toml.DecodeFile(path, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range config.Options {
|
||||
Update(k, v)
|
||||
}
|
||||
for k, v := range config.Toggles {
|
||||
UpdateSwitch(k, v)
|
||||
}
|
||||
for _, w := range config.Widgets {
|
||||
UpdateWidget(strings.ToLower(w.Name), w.Enabled)
|
||||
|
||||
// set working column config, if provided
|
||||
colStr := GetVal("columns")
|
||||
if len(colStr) > 0 {
|
||||
var colNames []string
|
||||
for _, s := range strings.Split(colStr, ",") {
|
||||
colNames = append(colNames, strings.TrimSpace(s))
|
||||
}
|
||||
SetColumns(colNames)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
var (
|
||||
GlobalParams []*Param
|
||||
GlobalSwitches []*Switch
|
||||
GlobalWidgets []*Widget
|
||||
GlobalColumns []*Column
|
||||
lock sync.RWMutex
|
||||
log = logging.Init()
|
||||
)
|
||||
@ -19,15 +19,16 @@ var (
|
||||
func Init() {
|
||||
for _, p := range defaultParams {
|
||||
GlobalParams = append(GlobalParams, p)
|
||||
log.Infof("loaded default config param: %s: %s", quote(p.Key), quote(p.Val))
|
||||
log.Infof("loaded default config param [%s]: %s", quote(p.Key), quote(p.Val))
|
||||
}
|
||||
for _, s := range defaultSwitches {
|
||||
GlobalSwitches = append(GlobalSwitches, s)
|
||||
log.Infof("loaded default config switch: %s: %t", quote(s.Key), s.Val)
|
||||
log.Infof("loaded default config switch [%s]: %t", quote(s.Key), s.Val)
|
||||
}
|
||||
for _, w := range defaultWidgets {
|
||||
GlobalWidgets = append(GlobalWidgets, w)
|
||||
log.Infof("loaded default widget: %s: %t", quote(w.Name), w.Enabled)
|
||||
for _, c := range defaultColumns {
|
||||
x := c
|
||||
GlobalColumns = append(GlobalColumns, &x)
|
||||
log.Infof("loaded default widget config [%s]: %t", quote(x.Name), x.Enabled)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,11 @@ var defaultParams = []*Param{
|
||||
Val: "sh",
|
||||
Label: "Shell",
|
||||
},
|
||||
&Param{
|
||||
Key: "columns",
|
||||
Val: "status,name,id,cpu,mem,net,io,pids",
|
||||
Label: "Enabled Columns",
|
||||
},
|
||||
}
|
||||
|
||||
type Param struct {
|
||||
|
122
config/widget.go
122
config/widget.go
@ -1,122 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// defaults
|
||||
var defaultWidgets = []*Widget{
|
||||
&Widget{
|
||||
Name: "status",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "name",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "id",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "cpu",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "mem",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "net",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "io",
|
||||
Enabled: true,
|
||||
},
|
||||
&Widget{
|
||||
Name: "pids",
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
type Widget struct {
|
||||
Name string
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// GetWidget returns a Widget by name
|
||||
func GetWidget(name string) *Widget {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
|
||||
for _, w := range GlobalWidgets {
|
||||
if w.Name == name {
|
||||
return w
|
||||
}
|
||||
}
|
||||
log.Errorf("widget name not found: %s", name)
|
||||
return &Widget{} // default
|
||||
}
|
||||
|
||||
// Widgets returns a copy of all configurable Widgets, in order
|
||||
func Widgets() []Widget {
|
||||
a := make([]Widget, len(GlobalWidgets))
|
||||
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
|
||||
for n, w := range GlobalWidgets {
|
||||
a[n] = *w
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// EnabledWidgets returns an ordered array of enabled widget names
|
||||
func EnabledWidgets() (a []string) {
|
||||
for _, w := range Widgets() {
|
||||
if w.Enabled {
|
||||
a = append(a, w.Name)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func UpdateWidget(name string, enabled bool) {
|
||||
w := GetWidget(name)
|
||||
oldVal := w.Enabled
|
||||
log.Noticef("config change [%s-enabled]: %t -> %t", name, oldVal, enabled)
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
w.Enabled = enabled
|
||||
}
|
||||
|
||||
func ToggleWidgetEnabled(name string) {
|
||||
w := GetWidget(name)
|
||||
newVal := !w.Enabled
|
||||
log.Noticef("config change [%s-enabled]: %t -> %t", name, w.Enabled, newVal)
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
w.Enabled = newVal
|
||||
}
|
||||
|
||||
// UpdateWidgets replaces existing ordered widgets with those provided
|
||||
func UpdateWidgets(newWidgets []Widget) {
|
||||
oldOrder := widgetNames()
|
||||
lock.Lock()
|
||||
for n, w := range newWidgets {
|
||||
GlobalWidgets[n] = &w
|
||||
}
|
||||
lock.Unlock()
|
||||
log.Noticef("config change [widget-order]: %s -> %s", oldOrder, widgetNames())
|
||||
}
|
||||
|
||||
func widgetNames() string {
|
||||
a := make([]string, len(GlobalWidgets))
|
||||
for n, w := range Widgets() {
|
||||
a[n] = w.Name
|
||||
}
|
||||
return strings.Join(a, ", ")
|
||||
}
|
Loading…
Reference in New Issue
Block a user