MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / validateExample

Function validateExample

internal/cmdhelp/example_validation.go:44–112  ·  view source on GitHub ↗
(path string, idx int, ex Example, doc *Document, root *cobra.Command)

Source from the content-addressed store, hash-verified

42}
43
44func validateExample(path string, idx int, ex Example, doc *Document, root *cobra.Command) []string {
45 tokens, err := shellSplit(ex.Cmd)
46 if err != nil {
47 return []string{fmt.Sprintf("%s example[%d]: cannot tokenize %q: %v", path, idx, ex.Cmd, err)}
48 }
49 if len(tokens) == 0 {
50 return []string{fmt.Sprintf("%s example[%d]: empty cmd string", path, idx)}
51 }
52
53 // Token 0 should be the binary's name. Examples that begin with
54 // something else (e.g. `cat ~/foo.json | jq`) are documentation
55 // snippets showing related output, not pad invocations the
56 // validator can check. Skip them rather than fail — the drift
57 // contract is for pad-invocation drift specifically.
58 binary := root.Name()
59 if tokens[0] != binary {
60 return nil
61 }
62
63 // Pass the full post-binary token stream to cobra's Find. Cobra
64 // knows each command's flag set and skips flag/value pairs while
65 // matching subcommand names — so examples that interleave flags
66 // with subcommands (e.g. `pad --workspace foo item create task`)
67 // resolve to `item create`, not the root.
68 target, _, ferr := root.Find(tokens[1:])
69 if ferr != nil || target == nil {
70 return []string{fmt.Sprintf("%s example[%d]: command path doesn't resolve: %s", path, idx, ex.Cmd)}
71 }
72
73 // Validate every --flag/-f against target's flag tree.
74 // Note: flags can appear before the subcommand path on cobra
75 // (e.g. `pad --workspace foo item create ...`), so scan all tokens.
76 var findings []string
77 skipNext := false
78 for _, t := range tokens[1:] {
79 if skipNext {
80 skipNext = false
81 continue
82 }
83 if !strings.HasPrefix(t, "-") {
84 continue
85 }
86 // Strip leading dashes and any =value suffix.
87 name := strings.TrimLeft(t, "-")
88 if eq := strings.IndexByte(name, '='); eq >= 0 {
89 name = name[:eq]
90 }
91 if name == "" {
92 continue // bare "--" terminator
93 }
94 // Walk target up to root, accept the flag if any level has it.
95 // Boolean flags don't consume the next token; non-bool flags
96 // do — but we only need the name check for drift detection,
97 // so don't bother with the value-consumption walk except to
98 // note that the "next token" might be a value rather than
99 // another flag (no special handling needed here).
100 if !flagExists(target, name) {
101 // Try negate-flag form: --no-<rest>.

Callers 1

ValidateExamplesFunction · 0.85

Calls 2

shellSplitFunction · 0.85
flagExistsFunction · 0.85

Tested by

no test coverage detected