Owns its configuration, moved to picom's window rules; started once from the session's xinitrc slot; Go tools restart, rules, window-opacity and toggle, which find the operator's X session from the window manager's environment.
98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
// Reading a tool's arguments: JSON numbers arrive as float64, and a missing argument is its default.
|
|
// The same in every desktop module that carries it.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// text is a string argument, trimmed; required says an empty one is refused.
|
|
func text(args map[string]any, key string, required bool) (string, error) {
|
|
v, present := args[key]
|
|
if !present || v == nil {
|
|
if required {
|
|
return "", fmt.Errorf("%s is required", key)
|
|
}
|
|
return "", nil
|
|
}
|
|
s, ok := v.(string)
|
|
if !ok {
|
|
return "", fmt.Errorf("%s is a string, not %T", key, v)
|
|
}
|
|
s = strings.TrimSpace(s)
|
|
if s == "" && required {
|
|
return "", fmt.Errorf("%s is required", key)
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// whole is a whole-number argument within [least, most], or def when absent.
|
|
func whole(args map[string]any, key string, def, least, most int) (int, error) {
|
|
v, present := args[key]
|
|
if !present || v == nil {
|
|
return def, nil
|
|
}
|
|
f, ok := v.(float64)
|
|
if !ok {
|
|
if i, isInt := v.(int); isInt {
|
|
f = float64(i)
|
|
} else {
|
|
return 0, fmt.Errorf("%s is a number, not %T", key, v)
|
|
}
|
|
}
|
|
if f != math.Trunc(f) {
|
|
return 0, fmt.Errorf("%s is a whole number, not %v", key, f)
|
|
}
|
|
n := int(f)
|
|
if n < least || n > most {
|
|
return 0, fmt.Errorf("%s is %d; it is between %d and %d", key, n, least, most)
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// flag is a boolean argument, or def when absent.
|
|
func flag(args map[string]any, key string, def bool) (bool, error) {
|
|
v, present := args[key]
|
|
if !present || v == nil {
|
|
return def, nil
|
|
}
|
|
b, ok := v.(bool)
|
|
if !ok {
|
|
return false, fmt.Errorf("%s is true or false, not %T", key, v)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
// texts is a list-of-strings argument.
|
|
func texts(args map[string]any, key string) ([]string, error) {
|
|
v, present := args[key]
|
|
if !present || v == nil {
|
|
return nil, nil
|
|
}
|
|
list, ok := v.([]any)
|
|
if !ok {
|
|
if ss, isStrings := v.([]string); isStrings {
|
|
return ss, nil
|
|
}
|
|
return nil, fmt.Errorf("%s is a list of strings, not %T", key, v)
|
|
}
|
|
out := make([]string, 0, len(list))
|
|
for i, item := range list {
|
|
s, ok := item.(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s[%d] is a string, not %T", key, i, item)
|
|
}
|
|
out = append(out, s)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// seconds is a timeout argument in seconds, defaulted and bounded below the runtime's call limit.
|
|
func seconds(args map[string]any, key string, def, most int) (time.Duration, error) {
|
|
n, err := whole(args, key, def, 1, most)
|
|
return time.Duration(n) * time.Second, err
|
|
}
|