feat(preview): add preview prompter command

This commit is contained in:
Kynan Ware 2025-04-07 14:40:03 -06:00
parent d230b08c43
commit abd573ac66
3 changed files with 247 additions and 0 deletions

View file

@ -0,0 +1,20 @@
package preview
import (
cmdPrompter "github.com/cli/cli/v2/pkg/cmd/preview/prompter"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/spf13/cobra"
)
func NewCmdPreview(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "preview <command>",
Short: "Execute previews for gh features",
}
cmdutil.DisableAuthCheck(cmd)
cmd.AddCommand(cmdPrompter.NewCmdPrompter(f, nil))
return cmd
}

View file

@ -0,0 +1,225 @@
package prompter
import (
"fmt"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/internal/gh"
"github.com/cli/cli/v2/internal/prompter"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/spf13/cobra"
)
type prompterOptions struct {
IO *iostreams.IOStreams
Config func() (gh.Config, error)
PromptsToRun []func(prompter.Prompter) error
}
func NewCmdPrompter(f *cmdutil.Factory, runF func(*prompterOptions) error) *cobra.Command {
opts := &prompterOptions{
IO: f.IOStreams,
Config: f.Config,
}
const (
selectPrompt = "select"
multiSelectPrompt = "multi-select"
inputPrompt = "input"
passwordPrompt = "password"
confirmPrompt = "confirm"
authTokenPrompt = "auth-token"
confirmDeletionPrompt = "confirm-deletion"
inputHostnamePrompt = "input-hostname"
markdownEditorPrompt = "markdown-editor"
)
prompterTypeFuncMap := map[string]func(prompter.Prompter) error{
selectPrompt: runSelect,
multiSelectPrompt: runMultiSelect,
inputPrompt: runInput,
passwordPrompt: runPassword,
confirmPrompt: runConfirm,
authTokenPrompt: runAuthToken,
confirmDeletionPrompt: runConfirmDeletion,
inputHostnamePrompt: runInputHostname,
markdownEditorPrompt: runMarkdownEditor,
}
cmd := &cobra.Command{
Use: "prompter [prompt type]",
Short: "Execute a test program to preview the prompter",
Long: heredoc.Doc(`
Execute a test program to preview the prompter.
Without an argument, all prompts will be run.
Available prompt types:
- select
- multi-select
- input
- password
- confirm
- auth-token
- confirm-deletion
- input-hostname
- markdown-editor
`),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if runF != nil {
return runF(opts)
}
if len(args) == 0 {
// All prompts
for _, f := range prompterTypeFuncMap {
opts.PromptsToRun = append(opts.PromptsToRun, f)
}
} else {
// Only the one specified
for _, arg := range args {
f, ok := prompterTypeFuncMap[arg]
if !ok {
return fmt.Errorf("unknown prompter type: %q", arg)
}
opts.PromptsToRun = append(opts.PromptsToRun, f)
}
}
return prompterRun(opts)
},
}
return cmd
}
func prompterRun(opts *prompterOptions) error {
editor, err := cmdutil.DetermineEditor(opts.Config)
if err != nil {
return err
}
p := prompter.New(editor, opts.IO.In, opts.IO.Out, opts.IO.ErrOut)
for _, f := range opts.PromptsToRun {
if err := f(p); err != nil {
return err
}
// Newline for readability
fmt.Println()
}
return nil
}
func runSelect(p prompter.Prompter) error {
fmt.Println("Demonstrating Single Select")
cuisines := []string{"Italian", "Greek", "Indian", "Japanese", "American"}
favorite, err := p.Select("Favorite cuisine?", "Italian", cuisines)
if err != nil {
return err
}
fmt.Printf("Favorite cuisine: %s\n", cuisines[favorite])
return nil
}
func runMultiSelect(p prompter.Prompter) error {
fmt.Println("Demonstrating Multi Select")
cuisines := []string{"Italian", "Greek", "Indian", "Japanese", "American"}
favorites, err := p.MultiSelect("Favorite cuisines?", []string{}, cuisines)
if err != nil {
return err
}
for _, f := range favorites {
fmt.Printf("Favorite cuisine: %s\n", cuisines[f])
}
return nil
}
func runInput(p prompter.Prompter) error {
fmt.Println("Demonstrating Text Input")
text, err := p.Input("Favorite meal?", "Breakfast")
if err != nil {
return err
}
fmt.Printf("You typed: %s\n", text)
return nil
}
func runPassword(p prompter.Prompter) error {
fmt.Println("Demonstrating Password Input")
safeword, err := p.Password("Safe word?")
if err != nil {
return err
}
fmt.Printf("Safe word: %s\n", safeword)
return nil
}
func runConfirm(p prompter.Prompter) error {
fmt.Println("Demonstrating Confirmation")
confirmation, err := p.Confirm("Are you sure?", true)
if err != nil {
return err
}
fmt.Printf("Confirmation: %t\n", confirmation)
return nil
}
func runAuthToken(p prompter.Prompter) error {
fmt.Println("Demonstrating Auth Token (can't be blank)")
token, err := p.AuthToken()
if err != nil {
return err
}
fmt.Printf("Auth token: %s\n", token)
return nil
}
func runConfirmDeletion(p prompter.Prompter) error {
fmt.Println("Demonstrating Deletion Confirmation")
err := p.ConfirmDeletion("delete-me")
if err != nil {
return err
}
fmt.Println("Item deleted")
return nil
}
func runInputHostname(p prompter.Prompter) error {
fmt.Println("Demonstrating Hostname")
hostname, err := p.InputHostname()
if err != nil {
return err
}
fmt.Printf("Hostname: %s\n", hostname)
return nil
}
func runMarkdownEditor(p prompter.Prompter) error {
defaultText := "default text value"
fmt.Println("Demonstrating Markdown Editor with blanks allowed and default text")
editorText, err := p.MarkdownEditor("Edit your text:", defaultText, true)
if err != nil {
return err
}
fmt.Printf("Returned text: %s\n", editorText)
fmt.Println("Demonstrating Markdown Editor with blanks disallowed and default text")
editorText2, err := p.MarkdownEditor("Edit your text:", defaultText, false)
if err != nil {
return err
}
fmt.Printf("Returned text: %s\n", editorText2)
fmt.Println("Demonstrating Markdown Editor with blanks disallowed and no default text")
editorText3, err := p.MarkdownEditor("Edit your text:", "", false)
if err != nil {
return err
}
fmt.Printf("Returned text: %s\n", editorText3)
return nil
}

View file

@ -25,6 +25,7 @@ import (
labelCmd "github.com/cli/cli/v2/pkg/cmd/label"
orgCmd "github.com/cli/cli/v2/pkg/cmd/org"
prCmd "github.com/cli/cli/v2/pkg/cmd/pr"
previewCmd "github.com/cli/cli/v2/pkg/cmd/preview"
projectCmd "github.com/cli/cli/v2/pkg/cmd/project"
releaseCmd "github.com/cli/cli/v2/pkg/cmd/release"
repoCmd "github.com/cli/cli/v2/pkg/cmd/repo"
@ -139,6 +140,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) (*cobra.Command,
cmd.AddCommand(statusCmd.NewCmdStatus(f, nil))
cmd.AddCommand(codespaceCmd.NewCmdCodespace(f))
cmd.AddCommand(projectCmd.NewCmdProject(f))
cmd.AddCommand(previewCmd.NewCmdPreview(f))
// below here at the commands that require the "intelligent" BaseRepo resolver
repoResolvingCmdFactory := *f