package app import ( "context" "errors" "os" "slices" "strconv" "strings" ) func assert(cond bool, msg string) { if !cond { panic(msg) } } func check(e error) { if e != nil { panic(e) } } func exitOnError(err error) { if err != nil { os.Stderr.WriteString(err.Error()) os.Exit(1) } } func async(cb func(ctx context.Context)) { wg.Add(1) go func() { defer wg.Done() select { case <-ctx.Done(): return default: cb(ctx) } }() } func getArg[T any](args []string, name string, f func(string, bool) T) T { i := slices.Index(args, name) if i == -1 { return f("", false) } if i == len(args)-1 { panic(errors.New("invalid " + name + " option")) } s := args[i+1] if strings.HasPrefix(s, "--") { return f("", true) } return f(s, true) } func strArg(args []string, name string, def ...string) string { return getArg(args, name, func(s string, b bool) string { if b { return s } for _, v := range def { return v } return "" }) } func intArg(args []string, name string, def ...int) int { return getArg(args, name, func(s string, b bool) int { if b { size, err := strconv.Atoi(s) check(err) assert(size > 0, "invalid "+name+" option") return size } for _, v := range def { return v } return 0 }) } func boolArg(args []string, name string, def ...bool) bool { return getArg(args, name, func(s string, b bool) bool { if b { if s == "" { return true } v, err := strconv.ParseBool(s) check(err) return v } for _, v := range def { return v } return false }) }