package wand import ( "fmt" "os" "path" ) type Config struct { file func(Cmd) *file merge []Config fromOption bool optional bool } type Cmd struct { name string impl any subcommands []Cmd isDefault bool minPositional int maxPositional int shortForms []string description string isHelp bool helpRequested bool } func Command(name string, impl any, subcmds ...Cmd) Cmd { return command(name, impl, subcmds...) } func Default(cmd Cmd) Cmd { cmd.isDefault = true return cmd } func Args(cmd Cmd, min, max int) Cmd { cmd.minPositional = min cmd.maxPositional = max return cmd } func ShortFormOptions(cmd Cmd, f ...string) Cmd { cmd.shortForms = append(cmd.shortForms, f...) for i := range cmd.subcommands { cmd.subcommands[i] = ShortFormOptions( cmd.subcommands[i], f..., ) } return cmd } func MergeConfig(conf ...Config) Config { return Config{ merge: conf, } } func OptionalConfig(conf Config) Config { conf.optional = true for i := range conf.merge { conf.merge[i] = OptionalConfig(conf.merge[i]) } return conf } func Etc() Config { return OptionalConfig(Config{ file: func(cmd Cmd) *file { return fileReader(path.Join("/etc", cmd.name, "config")) }, }) } func UserConfig() Config { return OptionalConfig(MergeConfig( Config{ file: func(cmd Cmd) *file { return fileReader( path.Join(os.Getenv("HOME"), fmt.Sprintf(".%s", cmd.name), "config"), ) }, }, Config{ file: func(cmd Cmd) *file { return fileReader( path.Join(os.Getenv("HOME"), ".config", cmd.name, "config"), ) }, }, )) } func ConfigFromOption() Config { return Config{fromOption: true} } func SystemConfig() Config { return MergeConfig(Etc(), UserConfig(), ConfigFromOption()) } func Exec(impl any, conf ...Config) { exec(os.Stdin, os.Stdout, os.Stderr, os.Exit, wrap(impl), MergeConfig(conf...), os.Environ(), os.Args) }