diff --git a/cmd/d2/main.go b/cmd/d2/main.go index d5976671a..e111d72f0 100644 --- a/cmd/d2/main.go +++ b/cmd/d2/main.go @@ -31,12 +31,27 @@ func run(ctx context.Context, ms *xmain.State) (err error) { // :( ctx = xmain.DiscardSlog(ctx) - watchFlag := ms.Opts.Bool("D2_WATCH", "watch", "w", false, "watch for changes to input and live reload. Use $HOST and $PORT to specify the listening address.\n$D2_HOST and $D2_PORT are also accepted and take priority (default localhost:0, which is will open on a randomly available local port).") - bundleFlag := ms.Opts.Bool("D2_BUNDLE", "bundle", "b", true, "bundle all assets and layers into the output svg.") - debugFlag := ms.Opts.Bool("DEBUG", "debug", "d", false, "print debug logs.") + watchFlag, err := ms.Opts.Bool("D2_WATCH", "watch", "w", false, "watch for changes to input and live reload. Use $HOST and $PORT to specify the listening address.\n$D2_HOST and $D2_PORT are also accepted and take priority (default localhost:0, which is will open on a randomly available local port).") + if err != nil { + return xmain.UsageErrorf(err.Error()) + } + bundleFlag, err := ms.Opts.Bool("D2_BUNDLE", "bundle", "b", true, "bundle all assets and layers into the output svg.") + if err != nil { + return xmain.UsageErrorf(err.Error()) + } + debugFlag, err := ms.Opts.Bool("DEBUG", "debug", "d", false, "print debug logs.") + if err != nil { + return xmain.UsageErrorf(err.Error()) + } layoutFlag := ms.Opts.String("D2_LAYOUT", "layout", "l", "dagre", `the layout engine used.`) - themeFlag := ms.Opts.Int64("D2_THEME", "theme", "t", 0, "the diagram theme ID. For a list of available options, see https://oss.terrastruct.com/d2") - versionFlag := ms.Opts.Bool("", "version", "v", false, "get the version") + themeFlag, err := ms.Opts.Int64("D2_THEME", "theme", "t", 0, "the diagram theme ID. For a list of available options, see https://oss.terrastruct.com/d2") + if err != nil { + return xmain.UsageErrorf(err.Error()) + } + versionFlag, err := ms.Opts.Bool("", "version", "v", false, "get the version") + if err != nil { + return xmain.UsageErrorf(err.Error()) + } err = ms.Opts.Parse() if !errors.Is(err, pflag.ErrHelp) && err != nil { diff --git a/lib/xmain/opts.go b/lib/xmain/opts.go index c095d58cb..15a0c71a1 100644 --- a/lib/xmain/opts.go +++ b/lib/xmain/opts.go @@ -20,7 +20,7 @@ type Opts struct { registeredEnvs []string } -func NewOpts(env *xos.Env, args []string, log *cmdlog.Logger) *Opts { +func NewOpts(env *xos.Env, log *cmdlog.Logger, args []string) *Opts { flags := pflag.NewFlagSet("", pflag.ContinueOnError) flags.SortFlags = false flags.Usage = func() {} @@ -52,29 +52,26 @@ func (o *Opts) Help() string { return b.String() } -func (o *Opts) Int64(envKey, flag, shortFlag string, defaultVal int64, usage string) *int64 { +func (o *Opts) Int64(envKey, flag, shortFlag string, defaultVal int64, usage string) (*int64, error) { if envKey != "" { if o.env.Getenv(envKey) != "" { envVal, err := strconv.ParseInt(o.env.Getenv(envKey), 10, 64) if err != nil { - o.log.Error.Printf(`ignoring invalid environment variable %s. Expected int64. Found "%v".`, envKey, envVal) - } else if envVal != defaultVal { - defaultVal = envVal + return nil, fmt.Errorf(`invalid environment variable %s. Expected int64. Found "%v".`, envKey, envVal) } + defaultVal = envVal } o.registeredEnvs = append(o.registeredEnvs, envKey) } - return o.flags.Int64P(flag, shortFlag, defaultVal, usage) + return o.flags.Int64P(flag, shortFlag, defaultVal, usage), nil } func (o *Opts) String(envKey, flag, shortFlag string, defaultVal, usage string) *string { if envKey != "" { if o.env.Getenv(envKey) != "" { envVal := o.env.Getenv(envKey) - if envVal != defaultVal { - defaultVal = envVal - } + defaultVal = envVal } o.registeredEnvs = append(o.registeredEnvs, envKey) } @@ -82,21 +79,23 @@ func (o *Opts) String(envKey, flag, shortFlag string, defaultVal, usage string) return o.flags.StringP(flag, shortFlag, defaultVal, usage) } -func (o *Opts) Bool(envKey, flag, shortFlag string, defaultVal bool, usage string) *bool { +func (o *Opts) Bool(envKey, flag, shortFlag string, defaultVal bool, usage string) (*bool, error) { if envKey != "" { if o.env.Getenv(envKey) != "" { envVal := o.env.Getenv(envKey) if !boolyEnv(envVal) { - o.log.Error.Printf(`ignoring invalid environment variable %s. Expected bool. Found "%s".`, envKey, envVal) - } else if (defaultVal && falseyEnv(envVal)) || - (!defaultVal && truthyEnv(envVal)) { - defaultVal = !defaultVal + return nil, fmt.Errorf(`invalid environment variable %s. Expected bool. Found "%s".`, envKey, envVal) + } + if truthyEnv(envVal) { + defaultVal = true + } else { + defaultVal = false } } o.registeredEnvs = append(o.registeredEnvs, envKey) } - return o.flags.BoolP(flag, shortFlag, defaultVal, usage) + return o.flags.BoolP(flag, shortFlag, defaultVal, usage), nil } func boolyEnv(s string) bool { @@ -104,19 +103,15 @@ func boolyEnv(s string) bool { } func falseyEnv(s string) bool { - return s == "0" || s == "false" || s == "f" + return s == "0" || s == "false" } func truthyEnv(s string) bool { - return s == "1" || s == "true" || s == "t" + return s == "1" || s == "true" } func (o *Opts) Parse() error { - err := o.flags.Parse(o.args) - if err != nil { - return err - } - return nil + return o.flags.Parse(o.args) } func (o *Opts) SetArgs(args []string) { diff --git a/lib/xmain/xmain.go b/lib/xmain/xmain.go index 3ef9b89aa..18eba1367 100644 --- a/lib/xmain/xmain.go +++ b/lib/xmain/xmain.go @@ -42,7 +42,7 @@ func Main(run RunFunc) { Env: xos.NewEnv(os.Environ()), } ms.Log = cmdlog.Log(ms.Env, os.Stderr) - ms.Opts = NewOpts(ms.Env, args, ms.Log) + ms.Opts = NewOpts(ms.Env, ms.Log, args) sigs := make(chan os.Signal, 1) signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)