package descriptor import ( "bytes" "context" "fmt" "strings" "text/template" "gitoa.ru/go-4devs/config" "gitoa.ru/go-4devs/config/definition/option" "gitoa.ru/go-4devs/config/param" "gitoa.ru/go-4devs/config/provider/arg" "gitoa.ru/go-4devs/console/output" ) const ( defaultSpace = 2 dashDelimiter = "-" ) //nolint:gochecknoglobals var ( txtFunc = template.FuncMap{ "synopsis": txtSynopsis, "definition": txtDefinition, "help": txtHelp, "commands": txtCommands, } txtHelpTemplate = template.Must(template.New("txt_template"). Funcs(txtFunc). Parse(` {{- if .Description -}} Description: {{ .Description }} {{ end -}} Usage: {{ .Name }} {{ synopsis .Options }} {{ definition .Options }} {{- help . }} `)) txtListTemplate = template.Must(template.New("txt_list"). Funcs(txtFunc). Parse(`Usage: command [options] [arguments] {{ definition .Options }} {{- commands .Commands -}} `)) ) func TxtStyle() param.Option { return arg.WithStyle( arg.Style{ Start: "", End: "", }, arg.Style{ Start: "", End: "", }, ) } type txt struct{} func (t *txt) Command(ctx context.Context, out output.Output, cmd Command) error { var tpl bytes.Buffer err := txtHelpTemplate.Execute(&tpl, cmd) if err != nil { return fmt.Errorf("execute txt help tpl:%w", err) } out.Println(ctx, tpl.String()) return nil } func (t *txt) Commands(ctx context.Context, out output.Output, cmds Commands) error { var buf bytes.Buffer err := txtListTemplate.Execute(&buf, cmds) if err != nil { return fmt.Errorf("execute txt list tpl:%w", err) } out.Println(ctx, buf.String()) return nil } func txtCommands(cmds []NSCommand) string { width := commandsTotalWidth(cmds) showNS := len(cmds) > 1 var buf bytes.Buffer buf.WriteString("\nAvailable commands") if len(cmds) == 1 && cmds[0].Name != "" { buf.WriteString("for the \"") buf.WriteString(cmds[0].Name) buf.WriteString(`" namespace`) } buf.WriteString(":\n") for _, ns := range cmds { if ns.Name != "" && showNS { buf.WriteString("") buf.WriteString(ns.Name) buf.WriteString("\n") } for _, cmd := range ns.Commands { buf.WriteString(" ") buf.WriteString(cmd.Name) buf.WriteString("") buf.WriteString(strings.Repeat(" ", width-len(cmd.Name)+defaultSpace)) buf.WriteString(cmd.Description) buf.WriteString("\n") } } return buf.String() } func txtHelp(cmd Command) string { if cmd.Help == "" { return "" } tpl := template.Must(template.New("help").Parse(cmd.Help)) var buf bytes.Buffer buf.WriteString("\nHelp:") _ = tpl.Execute(&buf, cmd) return buf.String() } func txtDefinition(options config.Options) string { var buf bytes.Buffer err := arg.NewDump().Reference(&buf, options) if err != nil { return err.Error() } return buf.String() } func txtSynopsis(options config.Options) string { def := arg.NewViews(options, nil) var buf bytes.Buffer if len(def.Options()) > 0 { buf.WriteString("[options] ") } args := def.Arguments() if buf.Len() > 0 && len(args) > 0 { buf.WriteString("[--]") } var opt int for _, arg := range args { buf.WriteString(" ") if !option.IsRequired(arg) { buf.WriteString("[") opt++ } buf.WriteString("<") buf.WriteString(arg.Name(dashDelimiter)) buf.WriteString(">") if option.IsSlice(arg) { buf.WriteString("...") } } buf.WriteString(strings.Repeat("]", opt)) return buf.String() } func commandsTotalWidth(cmds []NSCommand) int { var width int for _, ns := range cmds { for _, cmd := range ns.Commands { if len(cmd.Name) > width { width = len(cmd.Name) } } } return width }