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

Merge pull request #489 from wtfutil/482-missing-position-data-crash

WTF-482 Gracefully handle missing position configuration
This commit is contained in:
Chris Cummer 2019-07-05 22:26:23 -07:00 committed by GitHub
commit 85217be1b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 131 additions and 16 deletions

View File

@ -30,13 +30,6 @@ type Module struct {
Type string Type string
} }
type Position struct {
Height int
Left int
Top int
Width int
}
type Sigils struct { type Sigils struct {
Checkbox struct { Checkbox struct {
Checked string Checked string
@ -64,7 +57,6 @@ type Common struct {
func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config.Config, globalSettings *config.Config) *Common { func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config.Config, globalSettings *config.Config) *Common {
colorsConfig, _ := globalSettings.Get("wtf.colors") colorsConfig, _ := globalSettings.Get("wtf.colors")
positionPath := "position"
sigilsPath := "wtf.sigils" sigilsPath := "wtf.sigils"
common := Common{ common := Common{
@ -86,12 +78,7 @@ func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config
Type: moduleConfig.UString("type", name), Type: moduleConfig.UString("type", name),
}, },
Position: Position{ Position: NewPositionFromYAML(name, moduleConfig),
Height: moduleConfig.UInt(positionPath + ".height"),
Left: moduleConfig.UInt(positionPath + ".left"),
Top: moduleConfig.UInt(positionPath + ".top"),
Width: moduleConfig.UInt(positionPath + ".width"),
},
Enabled: moduleConfig.UBool("enabled", false), Enabled: moduleConfig.UBool("enabled", false),
RefreshInterval: moduleConfig.UInt("refreshInterval", 300), RefreshInterval: moduleConfig.UInt("refreshInterval", 300),

View File

@ -126,12 +126,15 @@ func LoadConfigFile(filePath string) *config.Config {
cfg, err := config.ParseYamlFile(absPath) cfg, err := config.ParseYamlFile(absPath)
if err != nil { if err != nil {
fmt.Println("\n\033[1mERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.\n") fmt.Println("\n\033[1mERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.")
fmt.Println("This could mean one of two things:\n") fmt.Println()
fmt.Println("This could mean one of two things:")
fmt.Println()
fmt.Println(" 1. Your \033[0;33mconfig.yml\033[0m file is missing. Check in \033[0;33m~/.config/wtf\033[0m to see if \033[0;33mconfig.yml\033[0m is there.") fmt.Println(" 1. Your \033[0;33mconfig.yml\033[0m file is missing. Check in \033[0;33m~/.config/wtf\033[0m to see if \033[0;33mconfig.yml\033[0m is there.")
fmt.Println(" 2. Your \033[0;33mconfig.yml\033[0m file has a syntax error. Try running it through http://www.yamllint.com to check for errors.") fmt.Println(" 2. Your \033[0;33mconfig.yml\033[0m file has a syntax error. Try running it through http://www.yamllint.com to check for errors.")
fmt.Println() fmt.Println()
fmt.Printf("Error: \033[0;31m%s\033[0m\n\n", err.Error()) fmt.Printf("Error: \033[0;31m%s\033[0m\n\n", err.Error())
os.Exit(1) os.Exit(1)
} }

123
cfg/position.go Normal file
View File

@ -0,0 +1,123 @@
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)
}
}

View File

@ -125,6 +125,8 @@ func (widget *Widget) deleteSelectedTorrent() {
} }
widget.client.TorrentRemove(removePayload) widget.client.TorrentRemove(removePayload)
widget.display()
} }
// pauseUnpauseTorrent either pauses or unpauses the downloading and seeding of the selected torrent // pauseUnpauseTorrent either pauses or unpauses the downloading and seeding of the selected torrent