bobarista

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2025 License: MIT Imports: 9 Imported by: 0

README

🧋 Bobarista

A delightfully smooth form flow framework for Go terminal applications

Go Version License Go Report Card

Bobarista is a powerful, flexible form flow framework built on top of Charm's Bubble Tea and Huh. Create beautiful, interactive multi-step terminal forms with conditional logic, custom navigation, and delightful theming - all with a fluent, easy-to-use API.

✨ Features

  • 🎯 Sequential Forms - Chain multiple forms together seamlessly
  • 🔀 Conditional Logic - Skip forms based on user input
  • 🧭 Custom Navigation - Control form flow with custom logic
  • 💾 Value Persistence - Automatic data management across forms
  • 🎨 Beautiful Themes - 7 built-in color schemes + custom themes
  • 🐛 Debug Mode - Visual debugging with state inspection
  • 📝 Comprehensive Logging - Built-in logging for troubleshooting
  • Error Handling - Robust error management with specific error types
  • 🎉 Completion Callbacks - Handle form completion with custom logic
  • 📱 Responsive - Adapts to terminal size with scrolling support

🚀 Quick Start

go get github.com/choice404/bobarista
Your First Bobarista Form
package main

import (
    "fmt"
    "log"
    
    "github.com/charmbracelet/huh"
    "github.com/choice404/bobarista/pkg/bobarista"
)

func main() {
    var name, email string
    
    // Create your form flow
    app := bobarista.New("🧋 Welcome to Bobarista").
        WithColorScheme("ocean").
        AddForm(bobarista.NewForm("welcome", "User Information").
            WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
                return huh.NewForm(
                    huh.NewGroup(
                        huh.NewInput().
                            Title("What's your name?").
                            Placeholder("Enter your name").
                            Value(&name),
                        huh.NewInput().
                            Title("What's your email?").
                            Placeholder("you@example.com").
                            Value(&email),
                    ),
                )
            }).
            WithOnComplete(func(current *bobarista.FormData, global *bobarista.FormData) error {
                global.Values.Set("name", name)
                global.Values.Set("email", email)
                return nil
            })).
        OnComplete(func(app *bobarista.Bobarista) error {
            fmt.Printf("🎉 Welcome %s! We'll contact you at %s\n", name, email)
            return nil
        }).
        Build()
    
    if err := app.Run(); err != nil {
        log.Fatal(err)
    }
}

🎨 Beautiful Themes

Bobarista comes with 7 stunning built-in themes:

app := bobarista.New("Themed App").
    WithColorScheme("ocean").    // 🌊 Ocean blue
    // WithColorScheme("forest").   // 🌲 Forest green  
    // WithColorScheme("sunset").   // 🌅 Sunset orange
    // WithColorScheme("ubuntu").   // 🟠 Ubuntu orange
    // WithColorScheme("dark").     // 🌙 Dark mode
    // WithColorScheme("monochrome"). // ⚫ Black & white
    // WithColorScheme("default").  // 🎯 Default cyan
    Build()

Or create your own custom theme:

customTheme := bobarista.CreateCustomColorScheme("neon", "#FF00FF", "#00FFFF", "#FFFF00")
bobarista.RegisterColorScheme("neon", customTheme)

app := bobarista.New("Neon App").WithColorScheme("neon")

🔀 Conditional Forms & Smart Navigation

Create dynamic form flows that adapt based on user input:

var userType, companyName, personalDetails string

app := bobarista.New("🎯 Smart Registration").
    AddForm(bobarista.NewForm("type", "User Type").
        WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
            return huh.NewForm(
                huh.NewGroup(
                    huh.NewSelect[string]().
                        Title("Are you registering as...").
                        Options(
                            huh.NewOption("🏢 Company", "company"),
                            huh.NewOption("👤 Individual", "individual"),
                        ).
                        Value(&userType),
                ),
            )
        }).
        WithOnComplete(func(current *bobarista.FormData, global *bobarista.FormData) error {
            global.Values.Set("user_type", userType)
            return nil
        })).
    AddForm(bobarista.NewForm("company", "Company Details").
        WithSkipCondition(func(current *bobarista.FormData, global *bobarista.FormData) bool {
            // Skip this form if user is not a company
            if val, exists := global.Values.Get("user_type"); exists {
                return val != "company"
            }
            return true
        }).
        WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
            return huh.NewForm(
                huh.NewGroup(
                    huh.NewInput().Title("Company Name").Value(&companyName),
                ),
            )
        })).
    Build()

🐛 Debug Mode

Enable debug mode to see what's happening under the hood:

app := bobarista.New("🔍 Debug Example").
    WithDebug(true).  // Shows a debug panel with form state, values, and navigation
    AddForm(...).
    Build()

The debug panel shows:

  • Current form state and values
  • Global data inspection
  • Navigation history and progress
  • Form completion status
  • Real-time error information

🎯 Advanced Examples

Multi-Step Project Setup Wizard
var projectType, language, framework, features string

wizard := bobarista.New("🚀 Project Setup Wizard").
    WithColorScheme("forest").
    WithMaxWidth(100).
    AddForm(bobarista.NewForm("project", "Project Type").
        WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
            return huh.NewForm(
                huh.NewGroup(
                    huh.NewSelect[string]().
                        Title("What type of project?").
                        Options(
                            huh.NewOption("🌐 Web Application", "web"),
                            huh.NewOption("⚡ CLI Tool", "cli"),
                            huh.NewOption("📱 Mobile App", "mobile"),
                        ).
                        Value(&projectType),
                ),
            )
        })).
    AddForm(bobarista.NewForm("language", "Programming Language").
        WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
            var options []huh.Option[string]
            
            // Dynamic options based on project type
            if projectType == "web" {
                options = []huh.Option[string]{
                    huh.NewOption("🐹 Go", "go"),
                    huh.NewOption("🐍 Python", "python"),
                    huh.NewOption("⚡ Node.js", "nodejs"),
                }
            } else {
                options = []huh.Option[string]{
                    huh.NewOption("🐹 Go", "go"),
                    huh.NewOption("🦀 Rust", "rust"),
                    huh.NewOption("⚡ C++", "cpp"),
                }
            }
            
            return huh.NewForm(
                huh.NewGroup(
                    huh.NewSelect[string]().
                        Title("Choose your language").
                        Options(options...).
                        Value(&language),
                ),
            )
        })).
    OnComplete(func(wizard *bobarista.Bobarista) error {
        fmt.Printf("🎉 Project created: %s %s application!\n", language, projectType)
        return nil
    }).
    Build()
Custom Navigation Logic
app := bobarista.New("🧭 Custom Navigation").
    AddForm(bobarista.NewForm("start", "Getting Started").
        WithNavigation(func(current *bobarista.FormData) int {
            // Custom navigation logic
            if someCondition {
                return 3 // Jump to form index 3
            }
            if anotherCondition {
                return -2 // Complete the flow early
            }
            return -1 // Use default navigation (next form)
        })).
    Build()

📊 Form Value Management

Bobarista automatically manages form values with a powerful and flexible system:

// Setting values in completion handlers
.WithOnComplete(func(current *bobarista.FormData, global *bobarista.FormData) error {
    // Set individual values
    global.Values.Set("username", username)
    global.Values.Set("email", email)
    
    // Or merge all current form values
    global.Values.Merge(current.Values)
    
    return nil
})

// Reading values in generators
.WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
    // Check if a value exists and use it as default
    var defaultName string
    if name, exists := global.Get("name"); exists {
        defaultName = name
    }
    
    return huh.NewForm(
        huh.NewGroup(
            huh.NewInput().
                Title("Name").
                Value(&defaultName),
        ),
    )
})

🎉 Completion & Display Control

Customize what happens when your form flow completes:

app := bobarista.New("📋 Survey Complete").
    WithDisplayKeys([]string{"name", "email", "rating"}). // Only show these in summary
    AddForm(...).
    OnComplete(func(app *bobarista.Bobarista) error {
        // Save to database, send email, etc.
        return saveResults(app.GetGlobalData())
    }).
    WithDisplayCallback(func() string {
        return `
🎉 Thank you for your feedback!

Your responses have been saved and our team will review them shortly.
You should receive a confirmation email within the next few minutes.

Have a great day! ✨
        `
    }).
    Build()

🛠️ Error Handling

Bobarista provides comprehensive error handling with specific error types:

if err := app.Run(); err != nil {
    switch e := err.(type) {
    case bobarista.CupSleeveError:
        fmt.Printf("❌ Form error in '%s': %v\n", e.FormID, e.Err)
    case bobarista.ValidationError:
        fmt.Printf("⚠️  Validation error in form '%s', field '%s': %v\n", 
            e.FormID, e.Field, e.Err)
    case bobarista.NavigationError:
        fmt.Printf("🧭 Navigation error from '%s' to '%s': %v\n", 
            e.FromFormID, e.ToFormID, e.Err)
    default:
        fmt.Printf("💥 Unexpected error: %v\n", err)
    }
}

📝 Built-in Logging

Bobarista includes comprehensive logging for debugging and monitoring:

// Logs are automatically written to ~/.config/bobarista/bobarista.log
// Or customize the location:
bobarista.LogFilename = "my-app.log"

// Use logging functions directly
bobarista.LogInfo("Application started")
bobarista.LogError(fmt.Errorf("something went wrong"))
bobarista.LogDebug("Debug information")
bobarista.LogWarning("Warning message")

🏗️ Builder API Reference

The fluent builder API makes it easy to construct complex form flows:

app := bobarista.New("My App").                    // Create new builder
    WithMaxWidth(120).                             // Set max display width
    WithColorScheme("ocean").                      // Choose color theme
    WithDisplayKeys([]string{"name", "email"}).    // Control completion display
    WithDebug(true).                               // Enable debug mode
    OnInit(func(app *bobarista.Bobarista, forms []bobarista.FormData) {
        // Initialize global data
    }).
    OnComplete(func(app *bobarista.Bobarista) error {
        // Handle completion
        return nil
    }).
    WithDisplayCallback(func() string {
        return "Custom completion message"
    }).
    AddForm(bobarista.NewForm("form1", "First Form").
        WithGenerator(func(current *bobarista.FormValues, global *bobarista.FormValues) *huh.Form {
            // Create huh.Form
        }).
        WithOnComplete(func(current *bobarista.FormData, global *bobarista.FormData) error {
            // Handle form completion
            return nil
        }).
        WithSkipCondition(func(current *bobarista.FormData, global *bobarista.FormData) bool {
            // Return true to skip this form
            return false
        }).
        WithNavigation(func(current *bobarista.FormData) int {
            // Custom navigation logic
            return -1 // Use default navigation
        }).
        WithoutStatus()). // Don't show progress for this form
    Build()

🎯 Common Use Cases

  • 🔐 User Registration & Onboarding - Multi-step user signup flows
  • ⚙️ Configuration Wizards - Application setup and configuration
  • 📋 Surveys & Forms - Data collection with conditional questions
  • 🚀 Project Generators - CLI tools for scaffolding projects
  • 🔧 Installation Wizards - Software installation and setup
  • 📊 Data Entry Applications - Complex data input workflows
  • 🎮 Interactive CLI Tools - User-friendly command-line interfaces

📚 Documentation

🤝 Contributing

We love contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Charm for the amazing Bubble Tea and Huh libraries
  • The Go community for inspiration and feedback
  • All contributors who help make Bobarista better

⭐ Star History

If you find Bobarista useful, please consider giving it a star! ⭐

Documentation

Overview

Package bobarista provides a flexible form flow framework built on top of Bubble Tea. It allows you to create multi-step forms with navigation, validation, and custom styling.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidFormIndex is returned when an invalid form index is provided.
	ErrInvalidFormIndex = errors.New("invalid form index")

	// ErrFormNotFound is returned when a requested form cannot be found.
	ErrFormNotFound = errors.New("form not found")

	// ErrNoFormsProvided is returned when no forms are provided to the navigator.
	ErrNoFormsProvided = errors.New("no forms provided")

	// ErrNoValidForms is returned when no valid forms are found for navigation.
	ErrNoValidForms = errors.New("no valid forms found")

	// ErrNoGenerator is returned when a form lacks a required generator function.
	ErrNoGenerator = errors.New("form generator is required")

	// ErrNilForm is returned when a form generator returns nil.
	ErrNilForm = errors.New("form generator returned nil")

	// ErrEmptyFormID is returned when a form has an empty ID.
	ErrEmptyFormID = errors.New("form ID cannot be empty")
)

Predefined errors for common Bobarista operations.

View Source
var LogFilename string

LogFilename specifies the name of the log file to use. If empty, a default filename with the process ID will be generated.

Functions

func GetAvailableColorSchemes

func GetAvailableColorSchemes() []string

GetAvailableColorSchemes returns a list of all available color scheme names. This is useful for providing users with theme selection options.

func LogDebug

func LogDebug(message string)

LogDebug logs a debug message to the log file. If the log file cannot be opened or written to, the error is printed to stderr.

func LogError

func LogError(err error)

LogError logs an error message to the log file. If the log file cannot be opened or written to, the error is printed to stderr.

func LogInfo

func LogInfo(message string)

LogInfo logs an informational message to the log file. If the log file cannot be opened or written to, the error is printed to stderr.

func LogWarning

func LogWarning(message string)

LogWarning logs a warning message to the log file. If the log file cannot be opened or written to, the error is printed to stderr.

func RegisterColorScheme

func RegisterColorScheme(name string, scheme ColorScheme)

RegisterColorScheme adds a new color scheme to the available schemes. This allows users to define and register custom themes.

Types

type BobaBuilder

type BobaBuilder struct {
	// contains filtered or unexported fields
}

BobaBuilder provides a fluent interface for constructing Bobarista form flows. It allows you to configure forms, styling, and behavior before building the final Bobarista instance.

func New

func New(title string) *BobaBuilder

New creates a new BobaBuilder with the specified title. This is the entry point for creating a new form flow.

func (*BobaBuilder) AddForm

func (b *BobaBuilder) AddForm(form Form) *BobaBuilder

AddForm adds a form to the form flow. Forms will be processed in the order they are added.

func (*BobaBuilder) Build

func (b *BobaBuilder) Build() *Bobarista

Build creates and returns a new Bobarista instance with the configured settings. This finalizes the builder and creates the form flow ready for execution.

func (*BobaBuilder) OnComplete

func (b *BobaBuilder) OnComplete(handler func(*Bobarista) error) *BobaBuilder

OnComplete sets a callback function that is called when the entire form flow completes. The callback receives the Bobarista instance with all collected data.

func (*BobaBuilder) OnInit

func (b *BobaBuilder) OnInit(handler func(*Bobarista, []FormData)) *BobaBuilder

OnInit sets a callback function that is called when the form flow initializes. The callback receives the Bobarista instance and initial form data for all forms.

func (*BobaBuilder) WithColorScheme

func (b *BobaBuilder) WithColorScheme(scheme string) *BobaBuilder

WithColorScheme sets the color scheme for the form display. Available schemes include "default", "dark", "ubuntu", "ocean", "forest", "sunset", and "monochrome".

func (*BobaBuilder) WithDebug

func (b *BobaBuilder) WithDebug(enabled bool) *BobaBuilder

WithDebug enables or disables debug mode. When enabled, a debug panel shows current form state, values, and navigation info.

func (*BobaBuilder) WithDisplayCallback

func (b *BobaBuilder) WithDisplayCallback(callback func() string) *BobaBuilder

WithDisplayCallback sets a custom function to generate the completion display content. If not set, a default summary will be shown based on DisplayKeys or all values.

func (*BobaBuilder) WithDisplayKeys

func (b *BobaBuilder) WithDisplayKeys(keys []string) *BobaBuilder

WithDisplayKeys sets which keys should be displayed in the completion summary. If not set, all non-empty values will be displayed.

func (*BobaBuilder) WithMaxWidth

func (b *BobaBuilder) WithMaxWidth(width int) *BobaBuilder

WithMaxWidth sets the maximum width for the form display. This controls how wide the form can be rendered on screen.

type BobaState

type BobaState int

BobaState represents the current state of the form flow.

const (
	// StateActive indicates the form flow is currently active and accepting input.
	StateActive BobaState = iota
	// StateCompleted indicates the form flow has completed successfully.
	StateCompleted
	// StateError indicates the form flow has encountered an error.
	StateError
)

type Bobarista

type Bobarista struct {
	// contains filtered or unexported fields
}

Bobarista represents the main form flow application. It manages the state, navigation, and rendering of multi-step forms.

func (*Bobarista) GetCurrentFormData

func (f *Bobarista) GetCurrentFormData() FormData

GetCurrentFormData returns the form data for the currently active form. If no form is active, returns empty form data.

func (*Bobarista) GetErrors

func (f *Bobarista) GetErrors() []error

GetErrors returns all errors that have occurred during the form flow. This is useful for debugging and error handling.

func (*Bobarista) GetGlobalData

func (f *Bobarista) GetGlobalData() FormData

GetGlobalData returns a copy of the global form data. This contains values that are shared across all forms in the flow.

func (*Bobarista) Init

func (f *Bobarista) Init() tea.Cmd

Init implements the tea.Model interface and initializes the form flow. It sets up global data, form values, and navigates to the first valid form.

func (*Bobarista) Run

func (f *Bobarista) Run() error

Run starts the form flow and blocks until completion or error. It initializes the Bubble Tea program and handles the main event loop.

func (*Bobarista) Update

func (f *Bobarista) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements the tea.Model interface and handles incoming messages. It processes keyboard input, window resize events, and form state changes.

func (*Bobarista) View

func (f *Bobarista) View() string

View implements the tea.Model interface and renders the current state. It delegates to the renderer based on the current form flow state.

type ColorScheme

type ColorScheme struct {
	// Name is the human-readable name of the color scheme.
	Name string

	// Primary is the main accent color used for headers and primary elements.
	Primary lipgloss.AdaptiveColor

	// Secondary is used for highlighted text and secondary emphasis.
	Secondary lipgloss.AdaptiveColor

	// Tertiary is used for labels, keys, and tertiary elements.
	Tertiary lipgloss.AdaptiveColor

	// Success is used for positive feedback and success messages.
	Success lipgloss.AdaptiveColor

	// Error is used for error messages and negative feedback.
	Error lipgloss.AdaptiveColor

	// Warning is used for warning messages and cautionary feedback.
	Warning lipgloss.AdaptiveColor

	// Info is used for informational messages and neutral feedback.
	Info lipgloss.AdaptiveColor
}

ColorScheme defines a complete color theme for the Bobarista form flow. It provides colors for different UI elements and semantic meanings.

func CreateCustomColorScheme

func CreateCustomColorScheme(name string, primary, secondary, tertiary string) ColorScheme

CreateCustomColorScheme creates a new ColorScheme with the specified colors. It uses the provided colors for primary, secondary, and tertiary elements, while using standard colors for semantic elements (success, error, warning, info).

func GetColorScheme

func GetColorScheme(name string) (ColorScheme, bool)

GetColorScheme retrieves a color scheme by name. Returns the color scheme and true if found, or an empty scheme and false if not found.

type CompletionHandler

type CompletionHandler func(current *FormData, global *FormData) error

CompletionHandler is called when a form is completed successfully. It receives the current form's data and global data, and can return an error to halt the flow.

type CupSleeveError

type CupSleeveError struct {
	// FormID identifies the form where the error occurred.
	FormID string
	// Err is the underlying error.
	Err error
}

CupSleeveError represents an error that occurred within a specific form. It wraps the underlying error with context about which form caused the issue.

func NewCupSleeveError

func NewCupSleeveError(formID string, err error) CupSleeveError

NewCupSleeveError creates a new CupSleeveError with the specified form ID and underlying error.

func (CupSleeveError) Error

func (fe CupSleeveError) Error() string

Error implements the error interface, providing a formatted error message. It includes the form ID if available.

func (CupSleeveError) Unwrap

func (fe CupSleeveError) Unwrap() error

Unwrap returns the underlying error, supporting Go's error unwrapping.

type DuplicateFormIDError

type DuplicateFormIDError struct {
	// ID is the duplicate form ID that was found.
	ID string
	// FirstIndex is the index of the first occurrence of the duplicate ID.
	FirstIndex int
	// SecondIndex is the index of the second occurrence of the duplicate ID.
	SecondIndex int
}

DuplicateFormIDError represents an error when duplicate form IDs are detected. This helps identify configuration issues during form flow setup.

func NewDuplicateFormIDError

func NewDuplicateFormIDError(id string, firstIndex, secondIndex int) DuplicateFormIDError

NewDuplicateFormIDError creates a new DuplicateFormIDError with the specified details.

func (DuplicateFormIDError) Error

func (e DuplicateFormIDError) Error() string

Error implements the error interface for DuplicateFormIDError.

type ErrorCollector

type ErrorCollector struct {
	// contains filtered or unexported fields
}

ErrorCollector provides a convenient way to collect multiple errors during form processing. It's useful for validation and setup phases where multiple errors might occur.

func NewErrorCollector

func NewErrorCollector() *ErrorCollector

NewErrorCollector creates a new ErrorCollector instance.

func (*ErrorCollector) Add

func (ec *ErrorCollector) Add(err error)

Add adds an error to the collector if it's not nil.

func (*ErrorCollector) AddCupSleeveError

func (ec *ErrorCollector) AddCupSleeveError(formID string, err error)

AddCupSleeveError adds a CupSleeveError to the collector with the specified form ID.

func (*ErrorCollector) Clear

func (ec *ErrorCollector) Clear()

Clear removes all errors from the collector, resetting it to an empty state.

func (*ErrorCollector) Error

func (ec *ErrorCollector) Error() string

Error implements the error interface, providing a formatted summary of all collected errors.

func (*ErrorCollector) Errors

func (ec *ErrorCollector) Errors() []error

Errors returns all collected errors.

func (*ErrorCollector) HasErrors

func (ec *ErrorCollector) HasErrors() bool

HasErrors returns true if the collector contains any errors.

type Form

type Form struct {
	// ID is a unique identifier for the form within the flow.
	ID string

	// Name is a human-readable name displayed in the UI.
	Name string

	// Group is an optional grouping identifier for organizing related forms.
	Group string

	// Generator creates the actual huh.Form instance when the form is displayed.
	Generator FormGenerator

	// OnComplete is called when the form is successfully completed.
	OnComplete CompletionHandler

	// ShouldSkip determines whether this form should be skipped based on current data.
	ShouldSkip SkipCondition

	// NextForm provides custom navigation logic to determine the next form.
	NextForm NavigationHandler

	// ShowStatus controls whether this form shows progress status in the UI.
	ShowStatus bool
}

Form represents a single form in the Bobarista form flow. It contains the form's metadata, generator function, and behavior callbacks.

func NewForm

func NewForm(id, name string) Form

NewForm creates a new Form with the specified ID and name. The form is created with default settings (ShowStatus = true).

func (Form) WithGenerator

func (f Form) WithGenerator(gen FormGenerator) Form

WithGenerator sets the form generator function. The generator is responsible for creating the actual huh.Form instance.

func (Form) WithNavigation

func (f Form) WithNavigation(handler NavigationHandler) Form

WithNavigation sets a custom navigation handler for the form. This allows for non-linear form flows based on form data.

func (Form) WithOnComplete

func (f Form) WithOnComplete(handler CompletionHandler) Form

WithOnComplete sets the completion handler for the form. This handler is called when the form is successfully completed.

func (Form) WithSkipCondition

func (f Form) WithSkipCondition(condition SkipCondition) Form

WithSkipCondition sets the skip condition for the form. The form will be skipped if the condition returns true.

func (Form) WithoutStatus

func (f Form) WithoutStatus() Form

WithoutStatus disables the progress status display for this form. The form will not show progress information in the UI.

type FormData

type FormData struct {
	// ID is the unique identifier of the form this data belongs to.
	ID string

	// Values contains all the field values for this form.
	Values *FormValues
}

FormData represents the complete data for a form, including its ID and values. It's used to pass form information between different parts of the Bobarista flow.

func NewFormData

func NewFormData(id string) FormData

NewFormData creates a new FormData instance with the specified ID. The values are initialized as empty but ready to use.

type FormGenerator

type FormGenerator func(current *FormValues, global *FormValues) *huh.Form

FormGenerator is a function that creates a huh.Form instance. It receives the current form's values and global values to customize the form.

type FormValues

type FormValues map[string]*string

FormValues represents a collection of form field values. It maps field names to their string values, with nil indicating unset fields.

func NewFormValues

func NewFormValues() *FormValues

NewFormValues creates a new, empty FormValues instance. All form values start uninitialized (nil pointers).

func (FormValues) Copy

func (fv FormValues) Copy() FormValues

Copy creates a deep copy of the FormValues. All string values are copied, ensuring the new FormValues is independent.

func (FormValues) Delete

func (fv FormValues) Delete(key string)

Delete removes a key and its value from the FormValues.

func (FormValues) Get

func (fv FormValues) Get(key string) (string, bool)

Get retrieves the value for the specified key. Returns the value and true if the key exists and has a non-nil value, or empty string and false if the key doesn't exist or is nil.

func (FormValues) Has

func (fv FormValues) Has(key string) bool

Has checks whether a key exists in the FormValues. Returns true if the key exists (even if the value is nil).

func (FormValues) Merge

func (fv FormValues) Merge(other *FormValues)

Merge combines values from another FormValues into this one. Values from the other FormValues will overwrite existing values with the same key. If other is nil, no changes are made.

func (FormValues) Set

func (fv FormValues) Set(key, value string)

Set stores a value for the specified key. The value is copied to ensure the FormValues owns the data.

type Logger

type Logger interface {
	// LogError logs an error message.
	LogError(err error)

	// LogInfo logs an informational message.
	LogInfo(message string)

	// LogDebug logs a debug message.
	LogDebug(message string)

	// LogWarning logs a warning message.
	LogWarning(message string)
}

Logger defines the interface for logging operations in Bobarista. Implementations can provide custom logging behavior for different environments.

type NavigationError struct {
	// FromFormID identifies the form being navigated from.
	FromFormID string
	// ToFormID identifies the form being navigated to.
	ToFormID string
	// Err is the underlying navigation error.
	Err error
}

NavigationError represents an error that occurred during form navigation. It provides context about the source and destination forms.

func NewNavigationError

func NewNavigationError(fromFormID, toFormID string, err error) NavigationError

NewNavigationError creates a new NavigationError with the specified form IDs and underlying error.

func (ne NavigationError) Error() string

Error implements the error interface for NavigationError.

func (ne NavigationError) Unwrap() error

Unwrap returns the underlying error, supporting Go's error unwrapping.

type NavigationHandler func(current *FormData) int

NavigationHandler provides custom navigation logic for a form. It receives the current form's data and returns the index of the next form to display. Return -1 to use default navigation, -2 to complete the flow.

type Navigator struct {
	// contains filtered or unexported fields
}

Navigator manages form navigation and flow control within a Bobarista form flow. It handles moving between forms, tracking history, and determining valid navigation paths.

func NewNavigator

func NewNavigator(forms []Form) *Navigator

NewNavigator creates a new Navigator with the provided forms. The navigator starts with no current form (currentIdx = -1).

func (n *Navigator) Back() bool

Back navigates to the previous form in the history. Returns true if navigation was successful, false if no history exists.

func (n *Navigator) Current() *Form

Current returns the currently active form, or nil if no form is active.

func (n *Navigator) GetCurrentIndex() int

GetCurrentIndex returns the index of the currently active form. Returns -1 if no form is active.

func (n *Navigator) GetFormByID(id string) (*Form, int, error)

GetFormByID finds a form by its ID and returns the form, its index, and any error. Returns ErrFormNotFound if the form doesn't exist.

func (n *Navigator) GetFormCount() int

GetFormCount returns the total number of forms in the navigator.

func (n *Navigator) GetFormsByGroup(group string) []Form

GetFormsByGroup returns all forms that belong to the specified group. Returns an empty slice if no forms match the group.

func (n *Navigator) GetProgress() float64

GetProgress calculates the current progress as a percentage. Returns 0.0 if no forms exist or no form is active.

func (n *Navigator) HasNext() bool

HasNext returns true if there are more forms after the current one.

func (n *Navigator) HasPrevious() bool

HasPrevious returns true if there are forms in the navigation history.

func (n *Navigator) MoveTo(index int) error

MoveTo navigates to the form at the specified index. It adds the current form to the navigation history before moving.

func (n *Navigator) MoveToFirstValid(globalData FormData) error

MoveToFirstValid finds and navigates to the first valid (non-skipped) form. This is typically called during initialization.

func (n *Navigator) Next(data FormData) (int, error)

Next determines the index of the next form to navigate to. It considers custom navigation handlers and skip conditions. Returns -1 if no more forms are available, -2 if the flow should complete.

func (n *Navigator) Reset()

Reset resets the navigator to its initial state. This clears the current form and navigation history.

func (n *Navigator) ValidateNavigation() []error

ValidateNavigation validates the form configuration and returns any errors found. It checks for missing forms, empty IDs, duplicate IDs, and missing generators.

type Recipe

type Recipe struct {
	// Title is the main title displayed at the top of the form flow.
	Title string

	// MaxWidth sets the maximum width in characters for the form display.
	MaxWidth int

	// DisplayKeys specifies which form values to show in the completion summary.
	// If empty, all non-empty values will be displayed.
	DisplayKeys []string

	// ColorScheme determines the visual theme for the form flow.
	// Available options: "default", "dark", "ubuntu", "ocean", "forest", "sunset", "monochrome".
	ColorScheme string

	// Debug enables debug mode, showing additional information during form flow execution.
	Debug bool

	// OnInit is called when the form flow initializes.
	// It receives the Bobarista instance and initial form data for all forms.
	OnInit func(*Bobarista, []FormData)

	// OnComplete is called when the entire form flow completes successfully.
	// It receives the Bobarista instance with all collected data.
	OnComplete func(*Bobarista) error

	// DisplayCallback provides custom content for the completion screen.
	// If nil, a default summary will be generated based on DisplayKeys.
	DisplayCallback func() string
}

Recipe holds the configuration settings for a Bobarista form flow. It defines the appearance, behavior, and callback functions for the entire flow.

func DefaultConfig

func DefaultConfig() Recipe

DefaultConfig returns a Recipe with sensible default values. This provides a starting point for customization.

type Renderer

type Renderer struct {
	// contains filtered or unexported fields
}

Renderer handles the visual presentation of the Bobarista form flow. It manages layout, styling, and different display states (active, completed, error).

func NewRenderer

func NewRenderer(config Recipe) *Renderer

NewRenderer creates a new Renderer with the specified configuration. It initializes the viewport, applies the color scheme, and sets default dimensions.

func (*Renderer) CanScrollDown

func (r *Renderer) CanScrollDown() bool

CanScrollDown returns true if the viewport can scroll down.

func (*Renderer) CanScrollUp

func (r *Renderer) CanScrollUp() bool

CanScrollUp returns true if the viewport can scroll up.

func (*Renderer) HandleScroll

func (r *Renderer) HandleScroll(direction int)

HandleScroll processes scroll events for the viewport. Positive direction scrolls down, negative scrolls up.

func (*Renderer) Render

func (r *Renderer) Render(cupSleeve *Bobarista) string

Render renders the Bobarista form flow based on its current state. It delegates to specific render methods based on the application state.

func (*Renderer) SetColorScheme

func (r *Renderer) SetColorScheme(schemeName string)

SetColorScheme updates the renderer's color scheme. If the scheme doesn't exist, the change is ignored.

func (*Renderer) UpdateSize

func (r *Renderer) UpdateSize(width, height int)

UpdateSize updates the renderer's dimensions based on terminal size. It respects the maximum width configuration and updates the viewport accordingly.

type SkipCondition

type SkipCondition func(current *FormData, global *FormData) bool

SkipCondition determines whether a form should be skipped. It receives the current form's data and global data, returning true to skip the form.

type Styles

type Styles struct {
	// Base is the default style applied to the main content area.
	Base lipgloss.Style

	// HeaderText styles the main header text at the top of the interface.
	HeaderText lipgloss.Style

	// Status styles the status display area, typically used for completion screens.
	Status lipgloss.Style

	// StatusHeader styles headers within status displays.
	StatusHeader lipgloss.Style

	// Error styles error messages and error display areas.
	Error lipgloss.Style

	// ErrorHeader styles headers in error displays.
	ErrorHeader lipgloss.Style

	// Help styles help text and instructions.
	Help lipgloss.Style

	// Highlight styles emphasized or highlighted text.
	Highlight lipgloss.Style

	// KeyText styles form field names and keys in debug displays.
	KeyText lipgloss.Style

	// ValueText styles form field values and data in debug displays.
	ValueText lipgloss.Style

	// FooterText styles footer text and status information.
	FooterText lipgloss.Style

	// Progress styles progress indicators and progress text.
	Progress lipgloss.Style

	// ProgressFilled styles the filled portion of progress indicators.
	ProgressFilled lipgloss.Style

	// Border styles borders around panels and containers.
	Border lipgloss.Style

	// Success styles success messages and positive feedback.
	Success lipgloss.Style

	// Warning styles warning messages and cautionary text.
	Warning lipgloss.Style

	// Info styles informational messages and neutral feedback.
	Info lipgloss.Style
}

Styles contains all the styling definitions used throughout the Bobarista form flow. It provides consistent visual appearance across different components and states.

func DefaultStyles

func DefaultStyles() *Styles

DefaultStyles creates a new Styles instance using the default color scheme. This provides a convenient way to get standard styling without specifying a scheme.

func NewStyles

func NewStyles(colorScheme ColorScheme) *Styles

NewStyles creates a new Styles instance with the specified color scheme. It initializes all style components with appropriate colors and formatting.

func (*Styles) ApplyColorScheme

func (s *Styles) ApplyColorScheme(colorScheme ColorScheme)

ApplyColorScheme updates all styles to use the specified color scheme. This allows for dynamic theme switching without recreating the entire Styles instance.

type ValidationError

type ValidationError struct {
	// FormID identifies the form where validation failed.
	FormID string
	// Field identifies the specific field that failed validation.
	Field string
	// Err is the underlying validation error.
	Err error
}

ValidationError represents a validation error that occurred in a specific form field. It provides context about both the form and the specific field that failed validation.

func NewValidationError

func NewValidationError(formID, field string, err error) ValidationError

NewValidationError creates a new ValidationError with the specified form ID, field, and underlying error.

func (ValidationError) Error

func (ve ValidationError) Error() string

Error implements the error interface for ValidationError.

func (ValidationError) Unwrap

func (ve ValidationError) Unwrap() error

Unwrap returns the underlying error, supporting Go's error unwrapping.

Directories

Path Synopsis
examples
advanced command
basic command
registration command
survey command
themes command
wizard command
Package internal provides utility functions and types used internally by CupSleeve.
Package internal provides utility functions and types used internally by CupSleeve.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL