Skip to content
Open
18 changes: 14 additions & 4 deletions internal/commandsgen/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,22 @@ func (c *Command) writeCode(w *codeWriter) error {
} else {
w.writeLinef("s.Command.Args = %v.NoArgs", w.importCobra())
}
if c.IgnoreMissingEnv {
if c.IgnoreMissingEnv || c.Deprecated {
w.writeLinef("s.Command.Annotations = make(map[string]string)")
w.writeLinef("s.Command.Annotations[\"ignoresMissingEnv\"] = \"true\"")
if c.IgnoreMissingEnv {
w.writeLinef("s.Command.Annotations[\"ignoresMissingEnv\"] = \"true\"")
}
}
if c.Deprecated != "" {
w.writeLinef("s.Command.Deprecated = %q", c.Deprecated)
// Note: We intentionally don't set s.Command.Deprecated here because Cobra
Comment thread
chaptersix marked this conversation as resolved.
// prints deprecation warnings to stdout, which breaks JSON output. Instead,
// the deprecation warning is prepended to the description/help text and
// printed to stderr via the annotation below.
if c.Deprecated {
msg := c.DeprecationMessage
if msg == "" {
msg = defaultDeprecationMessage
}
w.writeLinef("s.Command.Annotations[\"deprecationWarning\"] = %q", msg)
}
// Add subcommands
for _, subCommand := range subCommands {
Expand Down
28 changes: 26 additions & 2 deletions internal/commandsgen/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ type (
Description string `yaml:"description"`
DescriptionPlain string
DescriptionHighlighted string
Deprecated string `yaml:"deprecated"`
HasInit bool `yaml:"has-init"`
Deprecated bool `yaml:"deprecated"`
DeprecationMessage string `yaml:"deprecation-message"`
HasInit bool `yaml:"has-init"`
ExactArgs int `yaml:"exact-args"`
MaximumArgs int `yaml:"maximum-args"`
IgnoreMissingEnv bool `yaml:"ignores-missing-env"`
Expand Down Expand Up @@ -137,6 +138,22 @@ var markdownInlineCodeRegex = regexp.MustCompile("`([^`]+)`")
const ansiReset = "\033[0m"
const ansiBold = "\033[1m"

const defaultDeprecationMessage = "This command is deprecated and will be removed in a later release."

// generateDeprecationBox creates a formatted CAUTION box for deprecated commands.
// If message is empty, uses the default deprecation message.
func generateDeprecationBox(message string) string {
if message == "" {
message = defaultDeprecationMessage
}
content := "CAUTION: " + message
// Calculate box width (content + 2 spaces padding + 2 border chars)
boxWidth := len(content) + 4
border := "+" + strings.Repeat("-", boxWidth-2) + "+"
middle := "| " + content + " |"
return "```\n" + border + "\n" + middle + "\n" + border + "\n```\n\n"
}

func (o OptionSets) processSection() error {
if o.Name == "" {
return fmt.Errorf("missing option set name")
Expand Down Expand Up @@ -172,6 +189,13 @@ func (c *Command) processSection() error {
return fmt.Errorf("missing description for command: %s", c.FullName)
}

// Auto-handle deprecation: prepend warning box to description and append
// "(Deprecated)" to summary.
if c.Deprecated {
c.Description = generateDeprecationBox(c.DeprecationMessage) + c.Description
c.Summary += " (Deprecated)"
}

if len(c.NamePath) == 2 {
if c.Docs.Keywords == nil {
return fmt.Errorf("missing keywords for root command: %s", c.FullName)
Expand Down
48 changes: 48 additions & 0 deletions internal/commandsgen/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package commandsgen

import "testing"

func TestGenerateDeprecationBox(t *testing.T) {
tests := []struct {
name string
message string
expected string
}{
{
name: "default message when empty",
message: "",
expected: "```\n" +
"+-----------------------------------------------------------------------------+\n" +
"| CAUTION: This command is deprecated and will be removed in a later release. |\n" +
"+-----------------------------------------------------------------------------+\n" +
"```\n\n",
},
{
name: "custom message",
message: "Use the new API instead.",
expected: "```\n" +
"+-----------------------------------+\n" +
"| CAUTION: Use the new API instead. |\n" +
"+-----------------------------------+\n" +
"```\n\n",
},
{
name: "short custom message",
message: "Removed.",
expected: "```\n" +
"+-------------------+\n" +
"| CAUTION: Removed. |\n" +
"+-------------------+\n" +
"```\n\n",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := generateDeprecationBox(tt.message)
if got != tt.expected {
t.Errorf("generateDeprecationBox(%q) =\n%q\nwant:\n%q", tt.message, got, tt.expected)
}
})
}
}
Loading
Loading