Initial commit.

This commit is contained in:
2025-10-11 17:19:11 +00:00
commit 24245e46e8
33 changed files with 4206 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
package prompt_test
import (
"fmt"
// "github.com/wild-cloud/wild-central/wild/internal/prompt"
)
// ExampleString demonstrates the String prompt function
func ExampleString() {
// This example shows the prompt output format
// Actual usage would read from stdin interactively
fmt.Println("Enter SMTP host [smtp.gmail.com]:")
// User input: <empty> (returns default)
// Result: "smtp.gmail.com"
fmt.Println("Enter SMTP host [smtp.gmail.com]:")
// User input: "smtp.example.com"
// Result: "smtp.example.com"
}
// ExampleInt demonstrates the Int prompt function
func ExampleInt() {
// This example shows the prompt output format
fmt.Println("Enter SMTP port [587]:")
// User input: <empty> (returns default)
// Result: 587
fmt.Println("Enter SMTP port [587]:")
// User input: "465"
// Result: 465
}
// ExampleBool demonstrates the Bool prompt function
func ExampleBool() {
// This example shows the prompt output format
fmt.Println("Enable TLS [Y/n]:")
// User input: <empty> (returns default true)
// Result: true
fmt.Println("Enable TLS [Y/n]:")
// User input: "n"
// Result: false
fmt.Println("Enable debug mode [y/N]:")
// User input: <empty> (returns default false)
// Result: false
fmt.Println("Enable debug mode [y/N]:")
// User input: "yes"
// Result: true
}
// Example usage in a real command
func ExampleUsage() {
// Example of using prompt functions in a CLI command:
//
// host, err := prompt.String("Enter SMTP host", "smtp.gmail.com")
// if err != nil {
// return err
// }
//
// port, err := prompt.Int("Enter SMTP port", 587)
// if err != nil {
// return err
// }
//
// useTLS, err := prompt.Bool("Enable TLS", true)
// if err != nil {
// return err
// }
//
// fmt.Printf("Configuration: host=%s, port=%d, tls=%v\n", host, port, useTLS)
}

89
internal/prompt/prompt.go Normal file
View File

@@ -0,0 +1,89 @@
// Package prompt provides simple utilities for interactive CLI prompts
package prompt
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// String prompts the user for a string value with a default
func String(prompt, defaultValue string) (string, error) {
if defaultValue != "" {
fmt.Printf("%s [%s]: ", prompt, defaultValue)
} else {
fmt.Printf("%s: ", prompt)
}
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
return "", fmt.Errorf("failed to read input: %w", err)
}
input = strings.TrimSpace(input)
if input == "" {
return defaultValue, nil
}
return input, nil
}
// Int prompts the user for an integer value with a default
func Int(prompt string, defaultValue int) (int, error) {
fmt.Printf("%s [%d]: ", prompt, defaultValue)
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
return 0, fmt.Errorf("failed to read input: %w", err)
}
input = strings.TrimSpace(input)
if input == "" {
return defaultValue, nil
}
value, err := strconv.Atoi(input)
if err != nil {
return 0, fmt.Errorf("invalid integer value: %s", input)
}
return value, nil
}
// Bool prompts the user for a boolean value with a default
func Bool(prompt string, defaultValue bool) (bool, error) {
defaultStr := "y/n"
if defaultValue {
defaultStr = "Y/n"
} else {
defaultStr = "y/N"
}
fmt.Printf("%s [%s]: ", prompt, defaultStr)
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
return false, fmt.Errorf("failed to read input: %w", err)
}
input = strings.TrimSpace(input)
input = strings.ToLower(input)
if input == "" {
return defaultValue, nil
}
switch input {
case "y", "yes", "true":
return true, nil
case "n", "no", "false":
return false, nil
default:
return false, fmt.Errorf("invalid boolean value: %s (expected y/n/yes/no/true/false)", input)
}
}

View File

@@ -0,0 +1,64 @@
package prompt
import (
"testing"
)
// Note: These are basic unit tests for the prompt package.
// Interactive testing requires manual verification since the functions
// read from stdin and write to stdout.
func TestBoolParsing(t *testing.T) {
tests := []struct {
name string
input string
expected bool
hasError bool
}{
{"yes", "yes", true, false},
{"y", "y", true, false},
{"true", "true", true, false},
{"no", "no", false, false},
{"n", "n", false, false},
{"false", "false", false, false},
{"invalid", "maybe", false, true},
{"invalid", "xyz", false, true},
}
// Test the parsing logic that would be used by Bool function
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := tt.input
var result bool
var err error
switch input {
case "y", "yes", "true":
result = true
case "n", "no", "false":
result = false
default:
err = &invalidBoolError{}
}
if tt.hasError {
if err == nil {
t.Errorf("expected error for input %q, got nil", tt.input)
}
} else {
if err != nil {
t.Errorf("unexpected error for input %q: %v", tt.input, err)
}
if result != tt.expected {
t.Errorf("expected %v for input %q, got %v", tt.expected, tt.input, result)
}
}
})
}
}
type invalidBoolError struct{}
func (e *invalidBoolError) Error() string {
return "invalid boolean value"
}