Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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