Skip to content
Draft
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
30 changes: 30 additions & 0 deletions internal/cli/examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,36 @@ func exampleBlocks(examples ...string) string {
return strings.Join(blocks, "\n\n")
}

func exampleCommands(blocks string) []string {
var examples []string
var lines []string
inExample := false
flush := func() {
example := strings.TrimSpace(strings.Join(lines, "\n"))
if example != "" {
examples = append(examples, example)
}
lines = nil
}

for _, line := range strings.Split(blocks, "\n") {
if strings.HasPrefix(strings.TrimSpace(line), "Example - ") {
if inExample {
flush()
}
inExample = true
continue
}
if inExample {
lines = append(lines, strings.TrimPrefix(line, " "))
}
}
if inExample {
flush()
}
return examples
}

func builtinExampleTitle(index int) string {
switch index {
case 0:
Expand Down
12 changes: 10 additions & 2 deletions internal/cli/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ func getAllSchemas() []CommandSchema {
}

func buildSchemaCatalog(root *cobra.Command) schemaCatalog {
root.InitDefaultHelpCmd()
schemas := getAllSchemas()
seededByName := map[string]CommandSchema{}
for _, schema := range schemas {
Expand All @@ -285,7 +286,7 @@ func buildSchemaCatalog(root *cobra.Command) schemaCatalog {

catalog := schemaCatalog{byName: map[string]CommandSchema{}}
seen := map[string]bool{}
walkPublicCommands(root, func(cmd *cobra.Command) {
addCommand := func(cmd *cobra.Command) {
commandID := canonicalCommandID(cmd)
if commandID == "" || seen[commandID] {
return
Expand All @@ -301,6 +302,9 @@ func buildSchemaCatalog(root *cobra.Command) schemaCatalog {
schema.Summary = cmd.Short
}
schema.Aliases = append([]string(nil), cmd.Aliases...)
if examples := exampleCommands(cmd.Example); len(examples) > 0 {
schema.Examples = examples
}
schema.Subcommands = publicSubcommandIDs(cmd)
if len(schema.Subcommands) > 0 {
schema.Kind = "group"
Expand All @@ -311,7 +315,11 @@ func buildSchemaCatalog(root *cobra.Command) schemaCatalog {
schema = finalizeSchema(schema)
catalog.Ordered = append(catalog.Ordered, schema)
catalog.byName[schema.Name] = schema
})
}
walkPublicCommands(root, addCommand)
if helpCmd, _, err := root.Find([]string{"help"}); err == nil && helpCmd != root {
addCommand(helpCmd)
}

for _, schema := range schemas {
if seen[schema.Name] {
Expand Down
67 changes: 67 additions & 0 deletions internal/cli/schema_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,78 @@
package cli

import (
"reflect"
"strings"
"testing"

"github.com/TencentCloudAgentRuntime/ags-cli/internal/command"
"github.com/spf13/cobra"
)

func TestBuildSchemaCatalogUsesRenderedCommandExamples(t *testing.T) {
root := &cobra.Command{Use: "agr"}
root.AddCommand(&cobra.Command{
Use: "show",
Short: "Show a resource",
Run: func(*cobra.Command, []string) {},
Example: exampleBlocks(
"agr show resource-1",
"agr show resource-1 -o json\nagr show resource-2 -o json",
),
})

schema, ok := buildSchemaCatalog(root).Lookup(root, "show")
if !ok {
t.Fatal("show schema not found")
}
want := []string{
"agr show resource-1",
"agr show resource-1 -o json\nagr show resource-2 -o json",
}
if !reflect.DeepEqual(schema.Examples, want) {
t.Fatalf("Examples = %#v, want %#v", schema.Examples, want)
}
}

func TestSchemaCatalogLeafExamplesMatchHelp(t *testing.T) {
root := RootCmd()
catalog := buildSchemaCatalog(root)
helpSchema, ok := catalog.Lookup(root, "help")
if !ok {
t.Fatal("help schema not found")
}
wantHelpExamples := []string{"agr help instance create", "agr help schema"}
if !reflect.DeepEqual(helpSchema.Examples, wantHelpExamples) {
t.Fatalf("help Examples = %#v, want %#v", helpSchema.Examples, wantHelpExamples)
}

walkPublicCommands(root, func(cmd *cobra.Command) {
if cmd.HasAvailableSubCommands() {
return
}
commandID := canonicalCommandID(cmd)
schema, ok := catalog.Lookup(root, commandID)
if !ok {
t.Errorf("schema for %s not found", commandID)
return
}

wantCount := strings.Count(cmd.Example, "Example - ")
if len(schema.Examples) != wantCount {
t.Errorf("%s schema has %d examples, help has %d", commandID, len(schema.Examples), wantCount)
return
}
for _, example := range schema.Examples {
for _, line := range strings.Split(example, "\n") {
line = strings.TrimSpace(line)
if line != "" && !strings.Contains(cmd.Example, line) {
t.Errorf("%s schema example line %q is missing from help", commandID, line)
}
}
}
})
}

func TestSchemaFromDescriptorInfersEffects(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading