Skip to main content

Module views

Module views 

Source
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 .status works 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 UserOutput testing

Structs§

CompositeSink
DebugDetailMessage
A debug detail message shown at Debug verbosity level and above
DetailMessage
A detail message shown at VeryVerbose verbosity level and above
ErrorMessage
Error message for critical failures
FileSink
Example: File sink that writes all output to a file
InfoBlockMessage
Info block messages display a title followed by multiple lines of text. Useful for displaying grouped information, configuration details, or multi-line informational content.
InfoBlockMessageBuilder
Builder for constructing InfoBlockMessage with a fluent API
JsonFormatter
JSON formatter for machine-readable output
ProgressMessage
Progress message for ongoing operations
ResultMessage
Result message for final output data
StandardSink
Standard sink writing to stdout/stderr
StepsMessage
Steps message for sequential instructions
StepsMessageBuilder
Builder for constructing StepsMessage with a fluent API
SuccessMessage
Success message for completed operations
TelemetrySink
Theme
Output theme controlling symbols and formatting
UserOutput
User-facing output handler with sink-based architecture
WarningMessage
Warning message for non-critical issues

Enums§

Channel
Output channel for routing messages
VerbosityLevel
Verbosity levels for user output

Traits§

FormatterOverride
Optional trait for post-processing message output
OutputMessage
Trait for output messages that can be written to user-facing channels
OutputSink
Trait for output destinations