Expand description
Views Layer - User Interface Output
This module implements the Views layer of the MVC presentation architecture, handling user-facing output formatting and presentation. It provides clean separation between internal logging and user interface output, implementing a dual-channel strategy following Unix conventions and modern CLI best practices (similar to cargo, docker, npm):
- stdout (Results Channel): Final results, structured data, output for piping/redirection
- stderr (Progress/Operational Channel): Progress updates, status messages, warnings, errors
This separation enables:
- Clean piping:
torrust-tracker-deployer destroy env | jq .statusworks correctly - Automation friendly: Scripts can redirect progress to /dev/null while capturing results
- Unix convention compliance: Follows established patterns from modern CLI tools
- Better UX: Progress feedback doesn’t interfere with result data
§Type-Safe Channel Routing
The module uses newtype wrappers (StdoutWriter and StderrWriter) to provide compile-time
guarantees that messages are routed to the correct output channel. This prevents accidental
channel confusion and makes the code more maintainable by catching routing errors at compile
time rather than runtime.
The newtype pattern is a zero-cost abstraction - it has the same memory layout and performance characteristics as the wrapped type, but provides type safety benefits.
§Buffering Behavior
Output is line-buffered by default. Messages are typically flushed automatically
after each newline. For cases where immediate output is critical (e.g., before
long-running operations), call flush() explicitly:
output.progress("Starting long operation...");
output.flush()?; // Ensure message appears before operation starts
perform_long_operation();§Example Usage
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};
let mut output = UserOutput::new(VerbosityLevel::Normal);
// Progress messages go to stderr
output.progress("Destroying environment...");
// Success status goes to stderr
output.success("Environment destroyed successfully");
// Results go to stdout for piping
output.result(r#"{"status": "destroyed"}"#);§Channel Strategy
Based on research from docs/research/UX/console-app-output-patterns.md:
- stdout: Deployment results, configuration summaries, structured data (JSON)
- stderr: Step progress, status updates, warnings, error messages with actionable guidance
§Progress Indicators
The progress module provides components for displaying real-time progress during long operations.
See also: docs/research/UX/user-output-vs-logging-separation.md
Re-exports§
pub use render::Render;pub use render::ViewRenderError;
Modules§
- commands
- Command-specific views
- progress
- Progress Reporting for Long-Running Operations
- render
- Render trait and error type for command view rendering.
- testing
- Testing utilities for
UserOutputtesting
Structs§
- Composite
Sink - Debug
Detail Message - A debug detail message shown at Debug verbosity level and above
- Detail
Message - A detail message shown at
VeryVerboseverbosity level and above - Error
Message - Error message for critical failures
- File
Sink - Example: File sink that writes all output to a file
- Info
Block Message - Info block messages display a title followed by multiple lines of text. Useful for displaying grouped information, configuration details, or multi-line informational content.
- Info
Block Message Builder - Builder for constructing
InfoBlockMessagewith a fluent API - Json
Formatter - JSON formatter for machine-readable output
- Progress
Message - Progress message for ongoing operations
- Result
Message - Result message for final output data
- Standard
Sink - Standard sink writing to stdout/stderr
- Steps
Message - Steps message for sequential instructions
- Steps
Message Builder - Builder for constructing
StepsMessagewith a fluent API - Success
Message - Success message for completed operations
- Telemetry
Sink - Theme
- Output theme controlling symbols and formatting
- User
Output - User-facing output handler with sink-based architecture
- Warning
Message - Warning message for non-critical issues
Enums§
- Channel
- Output channel for routing messages
- Verbosity
Level - Verbosity levels for user output
Traits§
- Formatter
Override - Optional trait for post-processing message output
- Output
Message - Trait for output messages that can be written to user-facing channels
- Output
Sink - Trait for output destinations