termcinema-cli 0.1.0

🎬 Animated terminal-to-SVG renderer CLI for the termcinema project
Documentation
//! Layout configuration for the CLI renderer.
//!
//! This module builds a [`LayoutSpec`] from CLI arguments,
//! providing dimension, spacing, and alignment settings
//! to control how text is rendered within the SVG canvas.
//!
//! It includes:
//! - Pixel dimensions (`width`, `height`) and optional padding;
//! - Horizontal (`align`) and vertical (`v_align`) text alignment;
//! - Graceful fallback for invalid or missing values.

use crate::args::CliArgs;
use termcinema_engine::{LayoutSpec, TextAlign, VerticalAlign};

/// Build a [`LayoutSpec`] from CLI arguments.
///
/// Applies defaults for missing or invalid values:
/// - `padding` defaults to `10` if unspecified
/// - `align` falls back to `"left"`
/// - `v_align` falls back to `"middle"`
pub(crate) fn build_layout(args: &CliArgs) -> LayoutSpec {
    LayoutSpec {
        width: args.width,
        height: args.height,
        padding: args.padding.or(Some(10)),
        line_spacing: args.line_spacing,
        align: Some(parse_align(args.align.as_deref())),
        v_align: Some(parse_v_align(args.v_align.as_deref())),
    }
}

/// Parse horizontal text alignment from string input (`left`, `center`, `right`).
/// Falls back to `TextAlign::Left` if input is invalid or missing.
fn parse_align(input: Option<&str>) -> TextAlign {
    match input.unwrap_or("left").to_lowercase().as_str() {
        "left" => TextAlign::Left,
        "center" => TextAlign::Center,
        "right" => TextAlign::Right,
        invalid => {
            eprintln!(
                "⚠️ Invalid align value '{}'. Falling back to 'left'.",
                invalid
            );
            TextAlign::Left
        }
    }
}

/// Parse vertical text alignment from string input (`top`, `middle`, `bottom`).
/// Falls back to `VerticalAlign::Middle` if input is invalid or missing.
fn parse_v_align(input: Option<&str>) -> VerticalAlign {
    match input.unwrap_or("middle").to_lowercase().as_str() {
        "top" => VerticalAlign::Top,
        "middle" => VerticalAlign::Middle,
        "bottom" => VerticalAlign::Bottom,
        invalid => {
            eprintln!(
                "⚠️ Invalid v_align value '{}'. Falling back to 'middle'.",
                invalid
            );
            VerticalAlign::Middle
        }
    }
}