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:
		
						commit
						85217be1b5
					
				@ -30,13 +30,6 @@ type Module struct {
 | 
			
		||||
	Type string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Position struct {
 | 
			
		||||
	Height int
 | 
			
		||||
	Left   int
 | 
			
		||||
	Top    int
 | 
			
		||||
	Width  int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Sigils struct {
 | 
			
		||||
	Checkbox struct {
 | 
			
		||||
		Checked   string
 | 
			
		||||
@ -64,7 +57,6 @@ type Common struct {
 | 
			
		||||
 | 
			
		||||
func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config.Config, globalSettings *config.Config) *Common {
 | 
			
		||||
	colorsConfig, _ := globalSettings.Get("wtf.colors")
 | 
			
		||||
	positionPath := "position"
 | 
			
		||||
	sigilsPath := "wtf.sigils"
 | 
			
		||||
 | 
			
		||||
	common := Common{
 | 
			
		||||
@ -86,12 +78,7 @@ func NewCommonSettingsFromModule(name, defaultTitle string, moduleConfig *config
 | 
			
		||||
			Type: moduleConfig.UString("type", name),
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		Position: Position{
 | 
			
		||||
			Height: moduleConfig.UInt(positionPath + ".height"),
 | 
			
		||||
			Left:   moduleConfig.UInt(positionPath + ".left"),
 | 
			
		||||
			Top:    moduleConfig.UInt(positionPath + ".top"),
 | 
			
		||||
			Width:  moduleConfig.UInt(positionPath + ".width"),
 | 
			
		||||
		},
 | 
			
		||||
		Position: NewPositionFromYAML(name, moduleConfig),
 | 
			
		||||
 | 
			
		||||
		Enabled:         moduleConfig.UBool("enabled", false),
 | 
			
		||||
		RefreshInterval: moduleConfig.UInt("refreshInterval", 300),
 | 
			
		||||
 | 
			
		||||
@ -126,12 +126,15 @@ func LoadConfigFile(filePath string) *config.Config {
 | 
			
		||||
 | 
			
		||||
	cfg, err := config.ParseYamlFile(absPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("\n\033[1mERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.\n")
 | 
			
		||||
		fmt.Println("This could mean one of two things:\n")
 | 
			
		||||
		fmt.Println("\n\033[1mERROR:\033[0m Could not load '\033[0;33mconfig.yml\033[0m'.")
 | 
			
		||||
		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("    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.Printf("Error: \033[0;31m%s\033[0m\n\n", err.Error())
 | 
			
		||||
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								cfg/position.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								cfg/position.go
									
									
									
									
									
										Normal 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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -125,6 +125,8 @@ func (widget *Widget) deleteSelectedTorrent() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	widget.client.TorrentRemove(removePayload)
 | 
			
		||||
 | 
			
		||||
	widget.display()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pauseUnpauseTorrent either pauses or unpauses the downloading and seeding of the selected torrent
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user