package niri import ( "encoding/json" "fmt" "regexp" "strconv" ) type SizeChange struct { SetFixed *int `json:"SetFixed,omitempty"` SetProportion *float64 `json:"SetProportion,omitempty"` AdjustFixed *int `json:"AdjustFixed,omitempty"` AdjustProportion *float64 `json:"AdjustProportion,omitempty"` } func (m SizeChange) String() string { data, _ := json.MarshalIndent(m, "", "\t") return string(data) } func SizeSetFixed(size int) SizeChange { return SizeChange{SetFixed: &size} } func SizeSetProportion(size float64) SizeChange { return SizeChange{SetProportion: &size} } func SizeAdjustFixed(size int) SizeChange { return SizeChange{AdjustFixed: &size} } func SizeAdjustProportion(size float64) SizeChange { return SizeChange{AdjustProportion: &size} } const sizePatternString = `^(\+|-)?((\d+?)(?:\.\d+)?)(%)?$` const sizePatternGroupAdjust = 1 const sizePatternGroupFloatValue = 2 const sizePatternGroupIntValue = 3 const sizePatternGroupPercentage = 4 var sizePattern = regexp.MustCompile(sizePatternString) func ParseSize(str string) (SizeChange, error) { matches := sizePattern.FindStringSubmatch(str) if matches == nil { return SizeChange{}, fmt.Errorf("invalid size spec '%s'. Expected pattern: %s", str, sizePatternString) } adjust := matches[sizePatternGroupAdjust] != "" proportion := matches[sizePatternGroupPercentage] == "%" negative := matches[sizePatternGroupAdjust] == "-" factor := 1 if negative { factor = -1 } floatValue, err := strconv.ParseFloat(matches[sizePatternGroupFloatValue], 64) if err != nil { return SizeChange{}, fmt.Errorf("invalid size spec '%s'. Expected pattern: %s", str, sizePatternString) } intValue, err := strconv.ParseInt(matches[sizePatternGroupIntValue], 10, 64) if err != nil { return SizeChange{}, fmt.Errorf("invalid size spec '%s'. Expected pattern: %s", str, sizePatternString) } switch true { case adjust && proportion: return SizeAdjustProportion(floatValue * float64(factor)), nil case adjust && !proportion: return SizeAdjustFixed(int(intValue) * factor), nil case !adjust && proportion: return SizeSetProportion(floatValue * float64(factor)), nil case !adjust && !proportion: return SizeSetFixed(int(intValue) * factor), nil default: return SizeChange{}, fmt.Errorf("invalid size spec '%s'. Expected pattern: %s", str, sizePatternString) } }