Merge pull request #10745 from cli/kw/preview-prompter-command
Add `preview prompter` command
This commit is contained in:
commit
a04dc73e5d
3 changed files with 263 additions and 0 deletions
25
pkg/cmd/preview/preview.go
Normal file
25
pkg/cmd/preview/preview.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package preview
|
||||
|
||||
import (
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
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",
|
||||
Long: heredoc.Doc(`
|
||||
Preview commands are for testing, demonstrative, and development purposes only.
|
||||
They should be considered unstable and can change at any time.
|
||||
`),
|
||||
}
|
||||
|
||||
cmdutil.DisableAuthCheck(cmd)
|
||||
|
||||
cmd.AddCommand(cmdPrompter.NewCmdPrompter(f, nil))
|
||||
|
||||
return cmd
|
||||
}
|
||||
236
pkg/cmd/preview/prompter/prompter.go
Normal file
236
pkg/cmd/preview/prompter/prompter.go
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
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, *iostreams.IOStreams) 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, *iostreams.IOStreams) error{
|
||||
selectPrompt: runSelect,
|
||||
multiSelectPrompt: runMultiSelect,
|
||||
inputPrompt: runInput,
|
||||
passwordPrompt: runPassword,
|
||||
confirmPrompt: runConfirm,
|
||||
authTokenPrompt: runAuthToken,
|
||||
confirmDeletionPrompt: runConfirmDeletion,
|
||||
inputHostnamePrompt: runInputHostname,
|
||||
markdownEditorPrompt: runMarkdownEditor,
|
||||
}
|
||||
|
||||
allPromptsOrder := []string{
|
||||
selectPrompt,
|
||||
multiSelectPrompt,
|
||||
inputPrompt,
|
||||
passwordPrompt,
|
||||
confirmPrompt,
|
||||
authTokenPrompt,
|
||||
confirmDeletionPrompt,
|
||||
inputHostnamePrompt,
|
||||
markdownEditorPrompt,
|
||||
}
|
||||
|
||||
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, in a fixed order
|
||||
for _, promptType := range allPromptsOrder {
|
||||
f := prompterTypeFuncMap[promptType]
|
||||
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)
|
||||
|
||||
for _, f := range opts.PromptsToRun {
|
||||
if err := f(p, opts.IO); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSelect(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Single Select")
|
||||
cuisines := []string{"Italian", "Greek", "Indian", "Japanese", "American"}
|
||||
favorite, err := p.Select("Favorite cuisine?", "Italian", cuisines)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Favorite cuisine: %s\n", cuisines[favorite])
|
||||
return nil
|
||||
}
|
||||
|
||||
func runMultiSelect(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "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.Fprintf(io.Out, "Favorite cuisine: %s\n", cuisines[f])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runInput(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Text Input")
|
||||
text, err := p.Input("Favorite meal?", "Breakfast")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "You typed: %s\n", text)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runPassword(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Password Input")
|
||||
safeword, err := p.Password("Safe word?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Safe word: %s\n", safeword)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runConfirm(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Confirmation")
|
||||
confirmation, err := p.Confirm("Are you sure?", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Confirmation: %t\n", confirmation)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAuthToken(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Auth Token (can't be blank)")
|
||||
token, err := p.AuthToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Auth token: %s\n", token)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runConfirmDeletion(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Deletion Confirmation")
|
||||
err := p.ConfirmDeletion("delete-me")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(io.Out, "Item deleted")
|
||||
return nil
|
||||
}
|
||||
|
||||
func runInputHostname(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
fmt.Fprintln(io.Out, "Demonstrating Hostname")
|
||||
hostname, err := p.InputHostname()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Hostname: %s\n", hostname)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runMarkdownEditor(p prompter.Prompter, io *iostreams.IOStreams) error {
|
||||
defaultText := "default text value"
|
||||
|
||||
fmt.Fprintln(io.Out, "Demonstrating Markdown Editor with blanks allowed and default text")
|
||||
editorText, err := p.MarkdownEditor("Edit your text:", defaultText, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Returned text: %s\n\n", editorText)
|
||||
|
||||
fmt.Fprintln(io.Out, "Demonstrating Markdown Editor with blanks disallowed and default text")
|
||||
editorText2, err := p.MarkdownEditor("Edit your text:", defaultText, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Returned text: %s\n\n", editorText2)
|
||||
|
||||
fmt.Fprintln(io.Out, "Demonstrating Markdown Editor with blanks disallowed and no default text")
|
||||
editorText3, err := p.MarkdownEditor("Edit your text:", "", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(io.Out, "Returned text: %s\n", editorText3)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -26,6 +26,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"
|
||||
|
|
@ -141,6 +142,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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue