package niri import ( "encoding/json" "fmt" "regexp" "strconv" ) type PositionChange struct { SetFixed Option[int] `json:"SetFixed,omitempty"` AdjustFixed Option[int] `json:"AdjustFixed,omitempty"` } func (m PositionChange) String() string { data, _ := json.MarshalIndent(m, "", "\t") return string(data) } func PositionSetFixed(position int) PositionChange { return PositionChange{SetFixed: &position} } func PositionAdjustFixed(position int) PositionChange { return PositionChange{AdjustFixed: &position} } const positionPatternString = `^(\+|-)?(\d+?)$` const positionPatternGroupAdjust = 1 const positionPatternGroupIntValue = 2 var positionPattern = regexp.MustCompile(positionPatternString) func ParsePosition(str string) (PositionChange, error) { matches := positionPattern.FindStringSubmatch(str) if matches == nil { return PositionChange{}, fmt.Errorf("invalid position spec '%s'. Expected pattern: %s", str, positionPatternString) } adjust := matches[positionPatternGroupAdjust] != "" negative := matches[positionPatternGroupAdjust] == "-" factor := 1 if negative { factor = -1 } intValue, err := strconv.ParseInt(matches[positionPatternGroupIntValue], 10, 64) if err != nil { return PositionChange{}, fmt.Errorf("invalid position spec '%s'. Expected pattern: %s", str, positionPatternString) } switch true { case adjust: return PositionAdjustFixed(int(intValue) * factor), nil case !adjust: return PositionSetFixed(int(intValue) * factor), nil default: return PositionChange{}, fmt.Errorf("invalid position spec '%s'. Expected pattern: %s", str, positionPatternString) } }