Extending Input Types
Relevant source files
The following files were used as context for generating this wiki page:
The "wizard-tutorial" project implements a modular architecture for handling user input in a terminal-based wizard application. Built using the Bubble Tea framework, the system relies on an interface-driven design that allows for the seamless addition of different input types, such as short text fields and multi-line text areas.
The core of this system is the Input interface, which abstracts the underlying implementation details of specific Charm Bubbles components. This abstraction ensures that the main application logic remains agnostic of the specific input component being used, facilitating easy extension and maintenance.
Sources: input.go:9-17, main.go:34-45, README.md:1-12
Input Architecture
The project utilizes a wrapper-based architecture to integrate third-party components into a unified interface. Since standard components like textinput and textarea do not inherently satisfy a single shared custom interface required by the wizard's logic, they are wrapped in local structures.
The Input Interface
The Input interface defines the contract that any new input type must fulfill to be compatible with the wizard's question-and-answer flow.
| Method | Return Type | Description |
|---|---|---|
Blink() | tea.Msg | Handles cursor blinking messages. |
Blur() | tea.Msg | Returns a message indicating the input has lost focus. |
Focus() | tea.Cmd | Returns a command to give focus to the input. |
SetValue(string) | None | Sets the current text value of the input. |
Value() | string | Retrieves the current text value from the input. |
Update(tea.Msg) | (Input, tea.Cmd) | Processes messages and returns the updated model. |
View() | string | Returns the string representation for rendering. |
Sources: input.go:9-17
Component Relationship
The following class diagram illustrates how specific implementations like shortAnswerField and longAnswerField implement the Input interface while wrapping their respective Bubble Tea models.
The diagram shows the relationship between the central Input interface and the concrete implementations used in the project.
Sources: input.go:9-106
Implementing New Input Types
To extend the system with a new input type, a developer must create a new struct that wraps a component and implements the Input interface.
Data Flow for Input Processing
When the wizard cycles through questions, it interacts with the Input interface methods during the Update and View cycles of the Bubble Tea program.
This flowchart depicts how user input is processed through the generic Input interface within the main application loop.
Sources: main.go:71-92
Short vs. Long Answers
The project distinguishes between shortAnswerField (using textinput) and longAnswerField (using textarea).
- Short Answer Field: Initialized via
NewShortAnswerField(), it focuses on single-line input. - Long Answer Field: Initialized via
NewLongAnswerField(), it allows for multi-line textual data.
Sources: input.go:23-35, input.go:73-85
Question Integration
Questions are associated with specific input types through factory functions. This allows the Main model to iterate through a slice of Question structs without knowing the specific implementation of the input field.
Factory functions encapsulate the creation of specific question types and their associated input models.
Sources: main.go:47-62
Question Structure Configuration
The Question struct binds the prompt text with the answer storage and the UI component.
| Field | Type | Description |
|---|---|---|
question | string | The text prompt displayed to the user. |
answer | string | The value captured from the input upon completion. |
input | Input | The interface-compliant input component. |
Sources: main.go:34-38
Summary of Extension Steps
To add a new input type (e.g., a Selection List or a Toggle):
- Define a Struct: Create a struct to hold the new component's state.
- Implement Methods: Implement all methods defined in the
Inputinterface (Blink,Blur,Focus,SetValue,Value,Update,View). - Create Constructor: Provide a
New...Field()function to initialize the component. - Add Helper: Optionally add a
new...Question()function inmain.goto simplify question creation.
Sources: input.go:9-17, main.go:47-62