Interactive Prompts
Relevant source files
The following files were used as context for generating this wiki page:
- src/flext_cli/services/_prompts_parts/flextcliprompts_part_01.py
- src/flext_cli/services/_prompts_parts/flextcliprompts_part_03.py
- src/flext_cli/_utilities/prompts.py
- examples/ex_11_complete_integration.py
- tests/unit/_cases/test_prompts/testsflextcliprompts_part_01.py
- tests/unit/_cases/test_prompts/testsflextcliprompts_part_02.py
Interactive Prompts within flext-cli provide a standardized, type-safe suite of tools for handling user input and feedback in command-line applications. The system abstracts raw terminal interactions into high-level methods for text input, confirmations, multiple-choice selections, and secure password entry. It integrates the "Railway Oriented Programming" pattern, returning Result objects to handle successes and failures (such as user cancellations or stream errors) consistently across the CLI.
The module is designed to be environment-aware, automatically transitioning to non-interactive behavior when the CLI is running in a "quiet" mode or in non-interactive environments (e.g., CI/CD pipelines). In these scenarios, the system avoids blocking the execution by returning default values or pre-configured results, ensuring the application remains stable and automated.
Architecture and Components
The prompt system is built using a multi-part implementation strategy, separating core logic, helper utilities, and support structures. The primary interface for developers is the FlextCliPrompts class, which leverages specialized utilities for formatting and validation.
Component Breakdown
| Component | Responsibility |
|---|---|
FlextCliPrompts | The main service class providing methods like prompt(), confirm(), and prompt_choice(). |
FlextCliUtilitiesPrompts | Static helper methods for building confirmation text, display messages, and parsing raw input. |
PromptRuntimeState | Manages the current interactive and quiet status of the prompt service. |
Result / r | The railway container used to wrap all prompt outputs, providing a unified error handling contract. |
Sources: src/flext_cli/services/_prompts_parts/flextcliprompts_part_01.py, src/flext_cli/_utilities/prompts.py, examples/ex_11_complete_integration.py:46
Prompt Execution Flow
The following diagram illustrates how the system handles a standard prompt request, accounting for interactivity checks and input normalization.
The system ensures that even if interactive mode is enabled, raw input is always normalized (trimmed) before being evaluated against default values.
Sources: src/flext_cli/services/_prompts_parts/flextcliprompts_part_01.py:61-82, src/flext_cli/_utilities/prompts.py:31-34
Core Interaction Methods
The prompt service provides several specialized methods to handle different input requirements. All methods are designed to catch KeyboardInterrupt and EOFError to prevent the CLI from crashing ungracefully.
Basic Text Prompts and Confirmations
The prompt() method captures general text input, while confirm() specifically handles boolean (Yes/No) questions.
- Confirmation Logic: The system accepts variations like "y", "yes", "n", and "no". If invalid input is provided, the service warns the user and retries until a valid response is received or the stream ends.
- Safety: If a user cancels with
Ctrl+C, the system returns aResult.failwith the message "User cancelled confirmation".
Sources: src/flext_cli/services/_prompts_parts/flextcliprompts_part_01.py:23-42, tests/unit/_cases/test_prompts/testsflextcliprompts_part_01.py:75-84
Choice and Password Selection
Advanced interactions include selecting from a predefined list or entering sensitive data.
| Method | Key Features | Validation Rules |
|---|---|---|
prompt_choice | Displays a list of options. | Requires a selection; fails if choices list is empty or interactive mode is disabled without a valid default. |
prompt_password | Masks input for security. | Can enforce a min_length; fails if input is too short. |
Sources: src/flext_cli/_utilities/prompts.py:53-83, tests/unit/_cases/test_prompts/testsflextcliprompts_part_02.py:16-56
Implementation Details
Result Handling with Railway Pattern
The use of the railway pattern ensures that prompt failures do not require complex try/except blocks in the business logic.
# From ex_11_complete_integration.py
key_result = cli.prompt("Enter key:", default="sample_key")
if key_result.failure:
return r[t.JsonMapping].fail(f"Prompt failed: {key_result.error}")
key = key_result.value
Sources: examples/ex_11_complete_integration.py:47-51
Utility Helpers
Formatting of prompts is handled by FlextCliUtilitiesPrompts, which provides standardized visual cues for defaults.
# From _utilities/prompts.py
@staticmethod
def prompts_display_message(message: str, default: str) -> str:
"""Build prompt display message with optional default marker."""
if default:
return f"{message}{c.Cli.PROMPT_DEFAULT_FMT.format(default=default)}"
return message
Sources: src/flext_cli/_utilities/prompts.py:24-29
Testing and Behavioral Constraints
The system includes extensive behavioral tests to ensure reliability across different environments:
- Non-Interactive Environments: Tests verify that
prompt()andconfirm()return the provided default values without attempting to read fromstdinwhen interactivity is disabled. - Error Resilience: The system is tested against
KeyboardInterruptandEOFErrorto ensure it returns failure results instead of exiting the process. - Edge Cases: Empty choices or invalid default values in
prompt_choiceare explicitly caught and reported as failures.
Sources: tests/unit/_cases/test_prompts/testsflextcliprompts_part_01.py:38-48, tests/unit/_cases/test_prompts/testsflextcliprompts_part_02.py:17-25
Conclusion
Interactive Prompts in flext-cli serve as a robust bridge between the user and the application's logic. By combining environment awareness, strict validation, and the railway result pattern, the system provides a professional user experience while maintaining the automation capabilities required for modern development workflows.