1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

Reimpliments the module configuration validation

Now supports displaying errors from multiple widgets.
This commit is contained in:
Chris Cummer
2019-07-05 23:01:25 -07:00
parent c308d1b6c2
commit b07f3c5e67
65 changed files with 371 additions and 363 deletions

View File

@@ -44,7 +44,7 @@ type Sigils struct {
type Common struct {
Colors
Module
Position `help:"Defines where in the grid this modules widget will be displayed."`
PositionSettings `help:"Defines where in the grid this modules widget will be displayed."`
Sigils
Enabled bool `help:"Determines whether or not this module is executed and if its data displayed onscreen." values:"true, false"`
@@ -78,7 +78,7 @@ func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config
Type: moduleConfig.UString("type", name),
},
Position: NewPositionFromYAML(name, moduleConfig),
PositionSettings: NewPositionSettingsFromYAML(name, moduleConfig),
Enabled: moduleConfig.UBool("enabled", false),
RefreshInterval: moduleConfig.UInt("refreshInterval", 300),
@@ -100,6 +100,8 @@ func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config
return &common
}
/* -------------------- Exported Functions -------------------- */
func (common *Common) DefaultFocusedRowColor() string {
return fmt.Sprintf("%s:%s", common.Colors.HighlightFore, common.Colors.HighlightBack)
}
@@ -109,12 +111,11 @@ func (common *Common) DefaultRowColor() string {
}
func (common *Common) FocusChar() string {
focusChar := string('0' + common.focusChar)
if common.focusChar == -1 {
focusChar = ""
if common.focusChar <= -1 {
return ""
}
return focusChar
return string('0' + common.focusChar)
}
func (common *Common) RowColor(idx int) string {
@@ -143,3 +144,15 @@ func (common *Common) SigilStr(len, pos int, width int) string {
return sigils
}
// Validations aggregates all the validations from all the sub-sections in Common into a
// single array of validations
func (common *Common) Validations() []Validatable {
validatables := []Validatable{}
for _, validation := range common.PositionSettings.Validations.validations {
validatables = append(validatables, validation)
}
return validatables
}

View File

@@ -1,123 +0,0 @@
package cfg
import (
"fmt"
"os"
"strings"
"github.com/olebedev/config"
)
const (
positionPath = "position"
)
/* -------------------- Position Validation -------------------- */
type positionValidation struct {
err error
name string
val int
}
func (posVal *positionValidation) hasError() bool {
return posVal.err != nil
}
// String returns the Stringer representation of the positionValidation
func (posVal *positionValidation) String() string {
return fmt.Sprintf("Invalid value for %s:\t%d", posVal.name, posVal.val)
}
func newPositionValidation(name string, val int, err error) *positionValidation {
posVal := &positionValidation{
err: err,
name: name,
val: val,
}
return posVal
}
/* -------------------- Position -------------------- */
// Position represents the onscreen location of a widget
type Position struct {
Height int
Left int
Top int
Width int
}
// NewPositionFromYAML creates and returns a new instance of Position
func NewPositionFromYAML(moduleName string, moduleConfig *config.Config) Position {
var val int
var err error
validations := make(map[string]*positionValidation)
// Parse the positional data from the config data
val, err = moduleConfig.Int(positionPath + ".top")
validations["top"] = newPositionValidation("top", val, err)
val, err = moduleConfig.Int(positionPath + ".left")
validations["left"] = newPositionValidation("left", val, err)
val, err = moduleConfig.Int(positionPath + ".width")
validations["width"] = newPositionValidation("width", val, err)
val, err = moduleConfig.Int(positionPath + ".height")
validations["height"] = newPositionValidation("height", val, err)
validatePositions(moduleName, validations)
pos := Position{
Top: validations["top"].val,
Left: validations["left"].val,
Width: validations["width"].val,
Height: validations["height"].val,
}
return pos
}
/* -------------------- Unexported Functions -------------------- */
// If any of the position values have an error then we inform the user and exit the app
// Common examples of invalid position configuration are:
//
// position:
// top: 3
// width: 2
// height: 1
//
// position:
// top: 3
// # left: 2
// width: 2
// height: 1
//
// position:
// top: 3
// left: 2
// width: 2
// height: 1
//
func validatePositions(moduleName string, validations map[string]*positionValidation) {
var errStr string
for _, posVal := range validations {
if posVal.hasError() {
errStr += fmt.Sprintf(" - %s.\t\033[0;31mError\033[0m %v\n", posVal, posVal.err)
}
}
if errStr != "" {
fmt.Println()
fmt.Printf("\033[0;1mErrors in %s position configuration\033[0m\n", strings.Title(moduleName))
fmt.Println(errStr)
fmt.Println("Please check your config.yml file.")
fmt.Println()
os.Exit(1)
}
}

51
cfg/position_settings.go Normal file
View File

@@ -0,0 +1,51 @@
package cfg
import (
"github.com/olebedev/config"
)
const (
positionPath = "position"
)
// PositionSettings represents the onscreen location of a widget
type PositionSettings struct {
Validations *Validations
Height int
Left int
Top int
Width int
}
// NewPositionSettingsFromYAML creates and returns a new instance of cfg.Position
func NewPositionSettingsFromYAML(moduleName string, moduleConfig *config.Config) PositionSettings {
var currVal int
var err error
validations := NewValidations()
// Parse the positional data from the config data
currVal, err = moduleConfig.Int(positionPath + ".top")
validations.append("top", newPositionValidation("top", currVal, err))
currVal, err = moduleConfig.Int(positionPath + ".left")
validations.append("left", newPositionValidation("left", currVal, err))
currVal, err = moduleConfig.Int(positionPath + ".width")
validations.append("width", newPositionValidation("width", currVal, err))
currVal, err = moduleConfig.Int(positionPath + ".height")
validations.append("height", newPositionValidation("height", currVal, err))
pos := PositionSettings{
Validations: validations,
Top: validations.valueFor("top"),
Left: validations.valueFor("left"),
Width: validations.valueFor("width"),
Height: validations.valueFor("height"),
}
return pos
}

View File

@@ -0,0 +1,65 @@
package cfg
import (
"fmt"
"github.com/logrusorgru/aurora"
)
// Common examples of invalid position configuration are:
//
// position:
// top: -3
// left: 2
// width: 0
// height: 1
//
// position:
// top: 3
// width: 2
// height: 1
//
// position:
// top: 3
// # left: 2
// width: 2
// height: 1
//
// position:
// top: 3
// left: 2
// width: 2
// height: 1
//
type positionValidation struct {
err error
name string
intVal int
}
func (posVal *positionValidation) Error() error {
return posVal.err
}
func (posVal *positionValidation) HasError() bool {
return posVal.err != nil
}
func (posVal *positionValidation) IntValue() int {
return posVal.intVal
}
// String returns the Stringer representation of the positionValidation
func (posVal *positionValidation) String() string {
return fmt.Sprintf("Invalid value for %s:\t%d", aurora.Yellow(posVal.name), posVal.intVal)
}
func newPositionValidation(name string, intVal int, err error) *positionValidation {
posVal := &positionValidation{
err: err,
name: name,
intVal: intVal,
}
return posVal
}

9
cfg/validatable.go Normal file
View File

@@ -0,0 +1,9 @@
package cfg
// Validatable is implemented by any value that validates a configuration setting
type Validatable interface {
Error() error
HasError() bool
String() string
IntValue() int
}

28
cfg/validations.go Normal file
View File

@@ -0,0 +1,28 @@
package cfg
// Validations represent a collection of config setting validations
type Validations struct {
validations map[string]Validatable
}
// NewValidations creates and returns an instance of Validations
func NewValidations() *Validations {
vals := &Validations{
validations: make(map[string]Validatable),
}
return vals
}
func (vals *Validations) append(key string, posVal Validatable) {
vals.validations[key] = posVal
}
func (vals *Validations) valueFor(key string) int {
val := vals.validations[key]
if val != nil {
return val.IntValue()
}
return 0
}