Skip to content

Commit 4171855

Browse files
committed
feat(console): add context-aware help with topic and payload guidance
1 parent 78a8a1d commit 4171855

6 files changed

Lines changed: 852 additions & 94 deletions

File tree

runner/console/completer.go

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,61 +54,103 @@ var opt = []prompt.Suggest{
5454
}
5555

5656
func Complete(d prompt.Document) []prompt.Suggest {
57-
args := strings.Split(d.TextBeforeCursor(), " ")
57+
args := completionArgs(d)
58+
word := d.GetWordBeforeCursor()
5859
if len(args) <= 1 {
59-
return prompt.FilterHasPrefix(core, d.GetWordBeforeCursor(), true)
60+
return prompt.FilterHasPrefix(core, word, true)
6061
}
6162
switch args[0] {
63+
case "help":
64+
return helpSuggestions(args, word)
6265
case "use":
6366
if len(args) == 2 {
64-
return prompt.FilterContains(modules, d.GetWordBeforeCursor(), true)
67+
return prompt.FilterContains(modules, word, true)
6568
}
6669
}
6770
return []prompt.Suggest{}
6871
}
6972

7073
func actionCompleter(d prompt.Document) []prompt.Suggest {
71-
args := strings.Split(d.TextBeforeCursor(), " ")
74+
args := completionArgs(d)
75+
word := d.GetWordBeforeCursor()
7276
if len(args) <= 1 {
73-
return prompt.FilterHasPrefix(append(core, action...), d.GetWordBeforeCursor(), true)
77+
return prompt.FilterHasPrefix(append(core, action...), word, true)
7478
}
7579
switch args[0] {
80+
case "help":
81+
return helpSuggestions(args, word)
7682
case "use":
7783
if len(args) == 2 {
78-
return prompt.FilterContains(modules, d.GetWordBeforeCursor(), true)
84+
return prompt.FilterContains(modules, word, true)
7985
}
8086
case "show":
8187
if len(args) == 2 {
82-
return prompt.FilterContains(opt, d.GetWordBeforeCursor(), true)
88+
return prompt.FilterContains(opt, word, true)
8389
}
8490
case "set":
8591
if len(args) == 2 {
86-
getOpt := func() (p []prompt.Suggest) {
87-
for k := range config {
88-
if v, ok := optionsDesc[k]; ok { // && k != utils.Provider
89-
p = append(p, prompt.Suggest{Text: k, Description: v})
90-
}
91-
}
92-
return
93-
}()
94-
return prompt.FilterContains(getOpt, d.GetWordBeforeCursor(), true)
92+
return prompt.FilterContains(optionSuggestions(), word, true)
9593
}
9694
if len(args) == 3 && args[1] == utils.Payload {
97-
getPayloads := func() (p []prompt.Suggest) {
98-
for _, entry := range payloads.Visible() {
99-
p = append(p, prompt.Suggest{Text: entry.Name, Description: entry.Payload.Desc()})
100-
}
101-
return
102-
}()
103-
return prompt.FilterContains(getPayloads, d.GetWordBeforeCursor(), true)
95+
return prompt.FilterContains(payloadSuggestions(), word, true)
10496
}
10597
if len(args) == 3 && args[1] == utils.Version {
10698
var versions = []prompt.Suggest{
10799
{Text: "Intl", Description: "International Edition"},
108100
{Text: "China", Description: "Chinese Edition"},
109101
}
110-
return prompt.FilterContains(versions, d.GetWordBeforeCursor(), true)
102+
return prompt.FilterContains(versions, word, true)
111103
}
112104
}
113105
return []prompt.Suggest{}
114106
}
107+
108+
func completionArgs(d prompt.Document) []string {
109+
text := d.TextBeforeCursor()
110+
args := strings.Fields(text)
111+
if strings.HasSuffix(text, " ") || strings.HasSuffix(text, "\t") {
112+
args = append(args, "")
113+
}
114+
return args
115+
}
116+
117+
func helpSuggestions(args []string, word string) []prompt.Suggest {
118+
if len(args) == 2 {
119+
return prompt.FilterContains(helpTopicSuggestions(), word, true)
120+
}
121+
if len(args) == 3 && (args[1] == "payload" || args[1] == "metadata") {
122+
return prompt.FilterContains(payloadSuggestions(), word, true)
123+
}
124+
return []prompt.Suggest{}
125+
}
126+
127+
func helpTopicSuggestions() []prompt.Suggest {
128+
suggestions := make([]prompt.Suggest, 0, len(helpTopicOrder))
129+
for _, key := range helpTopicOrder {
130+
if topic, ok := helpTopics[key]; ok {
131+
suggestions = append(suggestions, prompt.Suggest{
132+
Text: key,
133+
Description: topic.Summary,
134+
})
135+
}
136+
}
137+
return suggestions
138+
}
139+
140+
func optionSuggestions() []prompt.Suggest {
141+
suggestions := make([]prompt.Suggest, 0, len(config))
142+
for k := range config {
143+
if v, ok := optionsDesc[k]; ok {
144+
suggestions = append(suggestions, prompt.Suggest{Text: k, Description: v})
145+
}
146+
}
147+
return suggestions
148+
}
149+
150+
func payloadSuggestions() []prompt.Suggest {
151+
suggestions := make([]prompt.Suggest, 0, len(payloads.Visible()))
152+
for _, entry := range payloads.Visible() {
153+
suggestions = append(suggestions, prompt.Suggest{Text: entry.Name, Description: entry.Payload.Desc()})
154+
}
155+
return suggestions
156+
}

runner/console/executor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func Executor(s string) {
3939
case "note":
4040
note(args)
4141
case "help":
42-
help()
42+
help(args)
4343
case "clear":
4444
os.Stdout.Write([]byte("\033[2J\033[H"))
4545
case "exit", "quit":

runner/console/help.go

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,51 @@
11
package console
22

3-
import "fmt"
4-
5-
func help() {
6-
document := `
7-
Core Commands
8-
=============
9-
10-
Command Description
11-
------- -----------
12-
help Help menu
13-
use Interact with a provider by name
14-
sessions List cache credential and display information about credentials
15-
clear Clear screen
16-
exit Exit the console
17-
18-
19-
Module Commands
20-
===============
21-
22-
Command Description
23-
------- -----------
24-
show Displays provider options or validation payloads
25-
set Sets a provider option or payload parameter
26-
run Runs the selected validation workflow
27-
shell Opens an authorized instance-cmd-check session
28-
29-
30-
### Examples
31-
32-
Select a cloud provider:
33-
34-
use aws
35-
36-
Displays the options required by the provider:
37-
38-
show options
39-
40-
Display the available validation payloads:
41-
42-
show payloads
43-
44-
Select a validation payload:
45-
46-
set payload iam-user-check
47-
48-
Select a cache credential:
49-
50-
sessions -i 1
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
func help(args []string) {
9+
args = normalizeHelpArgs(args)
10+
ctx := currentHelpContext()
11+
if len(args) == 0 {
12+
renderContextHelp(ctx)
13+
return
14+
}
15+
16+
switch args[0] {
17+
case "payload":
18+
if len(args) == 1 {
19+
renderPayloadCatalogHelp(ctx)
20+
return
21+
}
22+
renderPayloadHelp(ctx, args[1], false)
23+
return
24+
case "metadata":
25+
if len(args) == 1 {
26+
renderMetadataOverviewHelp(ctx)
27+
return
28+
}
29+
renderPayloadHelp(ctx, args[1], true)
30+
return
31+
}
32+
33+
if topic, ok := helpTopics[args[0]]; ok {
34+
renderTopicHelp(ctx, topic)
35+
return
36+
}
37+
38+
fmt.Printf("No help available for %q.\n", strings.Join(args, " "))
39+
fmt.Println("Try `help`, `help payload`, or `help metadata`.")
40+
}
5141

52-
Use CloudToolKit only in owned, lab, or explicitly authorized environments.`
53-
fmt.Println(document)
42+
func normalizeHelpArgs(args []string) []string {
43+
normalized := make([]string, 0, len(args))
44+
for _, arg := range args {
45+
arg = strings.TrimSpace(arg)
46+
if arg != "" {
47+
normalized = append(normalized, arg)
48+
}
49+
}
50+
return normalized
5451
}

0 commit comments

Comments
 (0)