Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.
Merged
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
143 changes: 143 additions & 0 deletions cmd/common/prompt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package common

import (
"github.com/erikgeiser/promptkit/selection"
"github.com/erikgeiser/promptkit/textinput"
"github.com/rigdev/rig/pkg/utils"
"golang.org/x/exp/slices"
)

type GetInputOption = func(*textinput.TextInput) *textinput.TextInput

var ValidateAllOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateAll
return inp
}

var BoolValidateOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = BoolValidate
return inp
}

var ValidateIntOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateInt
return inp
}

var ValidateNonEmptyOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateNonEmpty
return inp
}

var ValidateEmailOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateEmail
return inp
}

var ValidateSystemNameOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateSystemName
return inp
}

var ValidateURLOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateURL
return inp
}

var ValidateImageOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateImage
return inp
}

var ValidatePhoneOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = utils.ValidatePhone
return inp
}

var ValidatePasswordOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = utils.ValidatePassword
return inp
}

var ValidateBoolOpt = func(inp *textinput.TextInput) *textinput.TextInput {
inp.Validate = ValidateBool
return inp
}

var InputDefaultOpt = func(def string) GetInputOption {
return func(inp *textinput.TextInput) *textinput.TextInput {
inp.InitialValue = def
return inp
}
}

func PromptGetInput(label string, opts ...GetInputOption) (string, error) {
input := textinput.New(label)
for _, opt := range opts {
input = opt(input)
}

s, err := input.RunPrompt()
if err != nil {
return "", err
}
return s, nil
}

func GetPasswordPrompt(label string) (string, error) {
input := textinput.New(label)
input.Hidden = true
input.Validate = utils.ValidatePassword
input.ResultTemplate = ""

pw, err := input.RunPrompt()
if err != nil {
return "", err
}
return pw, nil
}

func PromptSelect(label string, choices []string) (int, string, error) {
sp := selection.New(label, choices)
sp.PageSize = 4
choice, err := sp.RunPrompt()
if err != nil {
return 0, "", err
}

return slices.Index(choices, choice), choice, nil
}

func PromptConfirm(label string, def bool) (bool, error) {
input := textinput.New(label + "?")
input.Validate = ValidateBool
input.Template = confirmTemplateY
if !def {
input.Template = confirmTemplateN
}
result, err := input.RunPrompt()
if err != nil {
return false, err
}
if result == "" {
return def, nil
}

return parseBool(result)
}

// TODO matias@rig.dev Find a better way instead of duplicate template strings
var (
confirmTemplateY = `
{{- Bold .Prompt }} {{- Faint " [Y/n]" }} {{ .Input -}}
{{- if .ValidationError }} {{ Foreground "1" (Bold "✘") }}
{{- else }} {{ Foreground "2" (Bold "✔") }}
{{- end -}}
`
confirmTemplateN = `
{{- Bold .Prompt }} {{- Faint " [y/N]" }} {{ .Input -}}
{{- if .ValidationError }} {{ Foreground "1" (Bold "✘") }}
{{- else }} {{ Foreground "2" (Bold "✔") }}
{{- end -}}
`
)
4 changes: 2 additions & 2 deletions cmd/common/useridentifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func PromptUserIndentifierUpdate() (*user.Update, error) {
var err error
identifier, err := PromptGetInput("Username, email or phone number:", ValidateAll)
identifier, err := PromptGetInput("Username, email or phone number:", ValidateAllOpt)
if err != nil {
return nil, err
}
Expand All @@ -24,7 +24,7 @@ func PromptUserIndentifierUpdate() (*user.Update, error) {

func PromptUserIndentifier() (*model.UserIdentifier, error) {
var err error
identifierStr, err := PromptGetInput("Username, email or phone number:", ValidateAll)
identifierStr, err := PromptGetInput("Username, email or phone number:", ValidateAllOpt)
if err != nil {
return nil, err
}
Expand Down
154 changes: 10 additions & 144 deletions cmd/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package common

import (
"context"
goerrors "errors"
"net/mail"
"net/url"
"regexp"
Expand All @@ -11,26 +10,17 @@ import (

"github.com/bufbuild/connect-go"
"github.com/docker/distribution/reference"
"github.com/manifoldco/promptui"
"github.com/rigdev/rig-go-api/api/v1/database"
"github.com/rigdev/rig-go-api/api/v1/group"
"github.com/rigdev/rig-go-api/api/v1/storage"
"github.com/rigdev/rig-go-api/api/v1/user"
"github.com/rigdev/rig-go-sdk"
"github.com/rigdev/rig/pkg/errors"
"github.com/rigdev/rig/pkg/utils"
"github.com/rigdev/rig/pkg/uuid"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/reflect/protoreflect"
)

var GetInputTemplates = &promptui.PromptTemplates{
Prompt: "{{ . }} ",
Valid: "{{ . | green }} ",
Invalid: "{{ . | red }} ",
Success: "{{ . | bold }} ",
}

var ValidateAll = func(input string) error {
return nil
}
Expand Down Expand Up @@ -91,19 +81,16 @@ var ValidateImage = func(input string) error {
return nil
}

func PromptGetInput(label string, validate func(input string) error) (string, error) {
prompt := promptui.Prompt{
Label: label,
Templates: GetInputTemplates,
Validate: validate,
var ValidateBool = func(s string) error {
if s == "" {
return nil
}

result, err := prompt.Run()
if err != nil {
return "", err
if _, err := parseBool(s); err != nil {
return err
}

return result, nil
return nil
}

func parseBool(s string) (bool, error) {
Expand All @@ -116,113 +103,10 @@ func parseBool(s string) (bool, error) {
return false, errors.InvalidArgumentErrorf("invalid bool format")
}

func PromptConfirm(label string, def bool) (bool, error) {
prompt := promptui.Prompt{
Label: label,
// Templates: GetInputTemplates,
IsConfirm: true,
Validate: func(s string) error {
if s == "" {
return nil
}

if _, err := parseBool(s); err != nil {
return err
}

return nil
},
Default: "N",
}

if def {
prompt.Default = "Y"
}

result, err := prompt.Run()
confirmed := !goerrors.Is(err, promptui.ErrAbort)
if err != nil && confirmed {
return false, err
}

if result == "" {
return def, nil
}

return parseBool(result)
}

func PromptGetInputWithDefault(label string, validate func(input string) error, def string) (string, error) {
prompt := promptui.Prompt{
Label: label,
Templates: GetInputTemplates,
Validate: validate,
Default: def,
AllowEdit: true,
}

result, err := prompt.Run()
if err != nil {
return "", err
}

return result, nil
}

func PromptSelect(label string, items []string, hideSelected bool) (int, string, error) {
templates := &promptui.SelectTemplates{
Label: "{{ . }}",
Active: "->{{ . | cyan }}",
Inactive: " {{ . | cyan }}",
Selected: "{{ . | green }}",
}

prompt := promptui.Select{
Templates: templates,
Label: label,
Items: items,
HideSelected: hideSelected,
}

i, res, err := prompt.Run()
if err != nil {
return 0, "", err
}

return i, res, nil
}

func GetPasswordPrompt(label string) (string, error) {
prompt := promptui.Prompt{
Label: label,
Templates: GetInputTemplates,
HideEntered: true,
Mask: '*',
Validate: func(input string) error {
if err := utils.ValidatePassword(input); err != nil {
return err
}
return nil
},
}

result, err := prompt.Run()
if err != nil {
return "", err
}
return result, nil
}

func GetUser(ctx context.Context, identifier string, nc rig.Client) (*user.User, string, error) {
var err error
if identifier == "" {
validateIdentifier := func(identifier string) error {
if identifier == "" {
return errors.InvalidArgumentErrorf("Please provide an identifier")
}
return nil
}
identifier, err = PromptGetInput("User Identifier:", validateIdentifier)
identifier, err = PromptGetInput("User Identifier:", ValidateSystemNameOpt)
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -261,13 +145,7 @@ func GetUser(ctx context.Context, identifier string, nc rig.Client) (*user.User,
func GetGroup(ctx context.Context, identifier string, nc rig.Client) (*group.Group, string, error) {
var err error
if identifier == "" {
validateIdentifier := func(identifier string) error {
if identifier == "" {
return errors.InvalidArgumentErrorf("Please provide an identifier")
}
return nil
}
identifier, err = PromptGetInput("Group Identifier:", validateIdentifier)
identifier, err = PromptGetInput("Group Identifier:", ValidateSystemNameOpt)
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -300,13 +178,7 @@ func GetGroup(ctx context.Context, identifier string, nc rig.Client) (*group.Gro
func GetDatabase(ctx context.Context, identifier string, nc rig.Client) (*database.Database, string, error) {
var err error
if identifier == "" {
validateIdentifier := func(identifier string) error {
if identifier == "" {
return errors.InvalidArgumentErrorf("Please provide an identifier")
}
return nil
}
identifier, err = PromptGetInput("DB Identifier:", validateIdentifier)
identifier, err = PromptGetInput("DB Identifier:", ValidateSystemNameOpt)
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -340,13 +212,7 @@ func GetDatabase(ctx context.Context, identifier string, nc rig.Client) (*databa
func GetStorageProvider(ctx context.Context, identifier string, nc rig.Client) (*storage.Provider, string, error) {
var err error
if identifier == "" {
validateIdentifier := func(identifier string) error {
if identifier == "" {
return errors.InvalidArgumentErrorf("Please provide an identifier")
}
return nil
}
identifier, err = PromptGetInput("Provider Identifier:", validateIdentifier)
identifier, err = PromptGetInput("Provider Identifier:", ValidateSystemNameOpt)
if err != nil {
return nil, "", err
}
Expand Down
Loading