You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.2 KiB
137 lines
3.2 KiB
package console
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
|
|
"gitoa.ru/go-4devs/console/input"
|
|
"gitoa.ru/go-4devs/console/input/option"
|
|
"gitoa.ru/go-4devs/console/input/value"
|
|
"gitoa.ru/go-4devs/console/output"
|
|
"gitoa.ru/go-4devs/console/output/verbosity"
|
|
)
|
|
|
|
const (
|
|
verboseTrace = 3
|
|
verboseDebug = 2
|
|
verboseInfo = 3
|
|
)
|
|
|
|
// Execute the current command with option.
|
|
func Execute(ctx context.Context, cmd *Command, opts ...func(*App)) {
|
|
opts = append([]func(*App){WithSkipArgs(1)}, opts...)
|
|
New(opts...).exec(ctx, cmd)
|
|
}
|
|
|
|
// Run current command by input and output.
|
|
func Run(ctx context.Context, cmd *Command, in input.Input, out output.Output) error {
|
|
def := input.NewDefinition()
|
|
|
|
if err := cmd.Init(ctx, def); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := in.Bind(ctx, Default(def)); err != nil {
|
|
ansi(ctx, in, out).Print(ctx, "<error>\n\n ", err, "\n</error>\n")
|
|
|
|
return showHelp(ctx, cmd, in, output.Ansi(out))
|
|
}
|
|
|
|
out = ansi(ctx, in, out)
|
|
|
|
out = verbose(ctx, in, out)
|
|
|
|
if in.Option(ctx, "version").Bool() {
|
|
version := cmd.Version
|
|
if version == "" {
|
|
version = "unknown"
|
|
}
|
|
|
|
out.Println(ctx, "command <comment>", cmd.Name, "</comment> version: <info>", version, "</info>")
|
|
|
|
return nil
|
|
}
|
|
|
|
if in.Option(ctx, "help").Bool() {
|
|
return showHelp(ctx, cmd, in, out)
|
|
}
|
|
|
|
return cmd.Run(ctx, in, out)
|
|
}
|
|
|
|
func ansi(ctx context.Context, in input.Input, out output.Output) output.Output {
|
|
switch {
|
|
case in.Option(ctx, "ansi").Bool():
|
|
out = output.Ansi(out)
|
|
case in.Option(ctx, "no-ansi").Bool():
|
|
out = output.None(out)
|
|
case lookupEnv("NO_COLOR"):
|
|
out = output.None(out)
|
|
default:
|
|
out = output.Ansi(out)
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
func lookupEnv(name string) bool {
|
|
v, has := os.LookupEnv(name)
|
|
|
|
return has && v == "true"
|
|
}
|
|
|
|
func verbose(ctx context.Context, in input.Input, out output.Output) output.Output {
|
|
switch {
|
|
case in.Option(ctx, "quiet").Bool():
|
|
out = output.Quiet()
|
|
default:
|
|
v := in.Option(ctx, "verbose").Bools()
|
|
|
|
switch {
|
|
case len(v) == verboseInfo:
|
|
out = output.Verbosity(out, verbosity.Info)
|
|
case len(v) == verboseDebug:
|
|
out = output.Verbosity(out, verbosity.Debug)
|
|
case len(v) >= verboseTrace:
|
|
out = output.Verbosity(out, verbosity.Trace)
|
|
default:
|
|
out = output.Verbosity(out, verbosity.Norm)
|
|
}
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
func showHelp(ctx context.Context, cmd *Command, in input.Input, out output.Output) error {
|
|
a := &input.Array{}
|
|
a.SetArgument(HelpArgumentCommandName, value.New(cmd.Name))
|
|
a.SetOption("help", value.New(false))
|
|
|
|
if _, err := Find(cmd.Name); errors.Is(err, ErrNotFound) {
|
|
register(cmd)
|
|
}
|
|
|
|
help, err := Find(CommandHelp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
w := input.Chain(a, in)
|
|
|
|
return Run(ctx, help, w, out)
|
|
}
|
|
|
|
// Default options and argument command.
|
|
func Default(d *input.Definition) *input.Definition {
|
|
return d.SetOptions(
|
|
option.Bool("no-ansi", "Disable ANSI output"),
|
|
option.Bool("ansi", "Do not ask any interactive question"),
|
|
option.Bool("version", "Display this application version", option.Short("V")),
|
|
option.Bool("help", "Display this help message", option.Short("h")),
|
|
option.Bool("verbose",
|
|
"Increase the verbosity of messages: -v for info output, -vv for debug and -vvv for trace",
|
|
option.Short("v"), option.Array),
|
|
option.Bool("quiet", "Do not output any message", option.Short("q")),
|
|
)
|
|
}
|
|
|