Files
entity-maker/internal/prompt/prompt.go
2025-10-31 14:36:41 +01:00

187 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package prompt
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"github.com/fatih/color"
)
var (
cyan = color.New(color.FgCyan).SprintFunc()
green = color.New(color.FgGreen).SprintFunc()
yellow = color.New(color.FgYellow).SprintFunc()
red = color.New(color.FgRed).SprintFunc()
)
// Reader interface for testing
type Reader interface {
ReadString(delim byte) (string, error)
}
// PromptString prompts for a string value
func PromptString(label string, defaultValue string, required bool) (string, error) {
reader := bufio.NewReader(os.Stdin)
return promptStringWithReader(reader, label, defaultValue, required)
}
func promptStringWithReader(reader Reader, label string, defaultValue string, required bool) (string, error) {
for {
prompt := fmt.Sprintf("%s", cyan(label))
if defaultValue != "" {
prompt += fmt.Sprintf(" [%s]", green(defaultValue))
}
prompt += ": "
fmt.Print(prompt)
input, err := reader.ReadString('\n')
if err != nil {
return "", err
}
input = strings.TrimSpace(input)
// If input is empty, use default value
if input == "" {
if defaultValue != "" {
// Echo the selected default value
fullPrompt := fmt.Sprintf("%s [%s]: %s", cyan(label), green(defaultValue), defaultValue)
fmt.Printf("\033[1A\r%s\n", fullPrompt)
return defaultValue, nil
}
if required {
fmt.Println(red("✗ This field is required"))
continue
}
return "", nil
}
return input, nil
}
}
// PromptInt prompts for an integer value
func PromptInt(label string, defaultValue int, required bool) (int, error) {
reader := bufio.NewReader(os.Stdin)
return promptIntWithReader(reader, label, defaultValue, required)
}
func promptIntWithReader(reader Reader, label string, defaultValue int, required bool) (int, error) {
for {
defaultStr := ""
if defaultValue != 0 {
defaultStr = strconv.Itoa(defaultValue)
}
prompt := fmt.Sprintf("%s", cyan(label))
if defaultStr != "" {
prompt += fmt.Sprintf(" [%s]", green(defaultStr))
}
prompt += ": "
fmt.Print(prompt)
input, err := reader.ReadString('\n')
if err != nil {
return 0, err
}
input = strings.TrimSpace(input)
// If input is empty, use default value
if input == "" {
if defaultValue != 0 {
// Echo the selected default value
fullPrompt := fmt.Sprintf("%s [%s]: %s", cyan(label), green(defaultStr), defaultStr)
fmt.Printf("\033[1A\r%s\n", fullPrompt)
return defaultValue, nil
}
if required {
fmt.Println(red("✗ This field is required"))
continue
}
return 0, nil
}
// Parse integer
value, err := strconv.Atoi(input)
if err != nil {
fmt.Println(red("✗ Please enter a valid number"))
continue
}
return value, nil
}
}
// ValidateDirectory checks if a directory exists or can be created
func ValidateDirectory(path string) error {
// Check if path exists
info, err := os.Stat(path)
if err == nil {
// Path exists, check if it's a directory
if !info.IsDir() {
return fmt.Errorf("path exists but is not a directory")
}
return nil
}
// Path doesn't exist, try to create it
if os.IsNotExist(err) {
if err := os.MkdirAll(path, 0755); err != nil {
return fmt.Errorf("cannot create directory: %w", err)
}
return nil
}
return err
}
// PromptDirectory prompts for a directory path and validates it
func PromptDirectory(label string, defaultValue string, required bool) (string, error) {
for {
path, err := PromptString(label, defaultValue, required)
if err != nil {
return "", err
}
if path == "" && !required {
return "", nil
}
// Validate directory
if err := ValidateDirectory(path); err != nil {
fmt.Printf("%s %s\n", red("✗"), err.Error())
continue
}
return path, nil
}
}
// PrintHeader prints a colored header
func PrintHeader(text string) {
header := color.New(color.FgCyan, color.Bold)
header.Println("\n" + text)
header.Println(strings.Repeat("=", len(text)))
}
// PrintSuccess prints a success message
func PrintSuccess(text string) {
fmt.Printf("%s %s\n", green("✓"), text)
}
// PrintError prints an error message
func PrintError(text string) {
fmt.Printf("%s %s\n", red("✗"), text)
}
// PrintInfo prints an info message
func PrintInfo(text string) {
fmt.Printf("%s %s\n", yellow(""), text)
}