Skip to main content

Crate standout

Crate standout 

Source
Expand description

§Standout - Non-Interactive CLI Framework

Standout is a CLI output framework that decouples your application logic from terminal presentation. It provides:

  • Template rendering with MiniJinja + styled output
  • Adaptive themes for named style definitions with light/dark mode support
  • Automatic terminal capability detection (TTY, CLICOLOR, etc.)
  • Output mode control (Auto/Term/Text/TermDebug)
  • Help topics system for extended documentation
  • Pager support for long content

This crate is CLI-agnostic at its core - it doesn’t care how you parse arguments. For clap integration, see the cli module.

§Core Concepts

  • Theme: Named collection of adaptive styles that respond to light/dark mode
  • ColorMode: Light or dark color mode enum
  • OutputMode: Control output formatting (Auto/Term/Text/TermDebug)
  • topics: Help topics system for extended documentation
  • Style syntax: Tag-based styling [name]content[/name]
  • Renderer: Pre-compile templates for repeated rendering
  • validate_template: Check templates for unknown style tags

§Quick Start

use standout::{render, Theme};
use console::Style;
use serde::Serialize;

#[derive(Serialize)]
struct Summary {
    title: String,
    total: usize,
}

let theme = Theme::new()
    .add("title", Style::new().bold())
    .add("count", Style::new().cyan());

let template = r#"
[title]{{ title }}[/title]
---------------------------
Total items: [count]{{ total }}[/count]
"#;

let output = render(
    template,
    &Summary { title: "Report".into(), total: 3 },
    &theme,
).unwrap();
println!("{}", output);

§Tag-Based Styling

Use tag syntax [name]content[/name] for styling both static and dynamic content:

use standout::{render_with_output, Theme, OutputMode};
use console::Style;
use serde::Serialize;

#[derive(Serialize)]
struct Data { name: String, count: usize }

let theme = Theme::new()
    .add("title", Style::new().bold())
    .add("count", Style::new().cyan());

let template = r#"[title]Report[/title]: [count]{{ count }}[/count] items by {{ name }}"#;

let output = render_with_output(
    template,
    &Data { name: "Alice".into(), count: 42 },
    &theme,
    OutputMode::Text,
).unwrap();

assert_eq!(output, "Report: 42 items by Alice");

Unknown tags show a ? marker in terminal output: [unknown?]text[/unknown?]. Use validate_template to catch typos during development.

§Adaptive Themes (Light & Dark)

Themes are inherently adaptive. Individual styles can define mode-specific variations that are automatically selected based on the user’s OS color mode.

use standout::Theme;
use console::Style;

let theme = Theme::new()
    // Non-adaptive style (same in all modes)
    .add("header", Style::new().bold().cyan())
    // Adaptive style with light/dark variants
    .add_adaptive(
        "panel",
        Style::new(),                                  // Base
        Some(Style::new().fg(console::Color::Black)), // Light mode
        Some(Style::new().fg(console::Color::White)), // Dark mode
    );

// Rendering automatically detects OS color mode
let output = standout::render(
    r#"[panel]active[/panel]"#,
    &serde_json::json!({}),
    &theme,
).unwrap();

§YAML-Based Themes

Themes can also be loaded from YAML files, which is convenient for UI designers who may not be Rust programmers.

use standout::Theme;

let theme = Theme::from_yaml(r#"
header:
  fg: cyan
  bold: true
panel:
  fg: gray
  light:
    fg: black
  dark:
    fg: white
title: header
"#).unwrap();

§Rendering Strategy

  1. Build a Theme using the fluent builder API or YAML.
  2. Load/define templates using regular MiniJinja syntax ({{ value }}, {% for %}, etc.) with tag-based styling ([name]content[/name]).
  3. Call render for ad-hoc rendering or create a Renderer if you have many templates.
  4. Standout processes style tags, auto-detects colors, and returns the final string.

Everything from the theme inward is pure Rust data: no code outside Standout needs to touch stdout/stderr or ANSI escape sequences directly.

§More Examples

use standout::{Renderer, Theme};
use console::Style;
use serde::Serialize;

#[derive(Serialize)]
struct Entry { label: String, value: i32 }

let theme = Theme::new()
    .add("label", Style::new().bold())
    .add("value", Style::new().green());

let mut renderer = Renderer::new(theme).unwrap();
renderer.add_template("row", "[label]{{ label }}[/label]: [value]{{ value }}[/value]").unwrap();
let rendered = renderer.render("row", &Entry { label: "Count".into(), value: 42 }).unwrap();
assert_eq!(rendered, "Count: 42");

§Help Topics System

The topics module provides a help topics system for extended documentation:

use standout::topics::{Topic, TopicRegistry, TopicType, render_topic};

// Create and populate a registry
let mut registry = TopicRegistry::new();
registry.add_topic(Topic::new(
    "Storage",
    "Notes are stored in ~/.notes/\n\nEach note is a separate file.",
    TopicType::Text,
    Some("storage".to_string()),
));

// Render a topic
if let Some(topic) = registry.get_topic("storage") {
    let output = render_topic(topic, None).unwrap();
    println!("{}", output);
}

// Load topics from a directory
registry.add_from_directory_if_exists("docs/topics").ok();

§Integration with Clap

The cli module provides full clap integration with:

  • Command dispatch with automatic template rendering
  • Help command interception (help, help <topic>, help topics)
  • Output flag injection (--output=auto|term|text|json)
  • Styled help rendering
use clap::Command;
use standout::cli::{App, HandlerResult, Output};

// Simple parsing with styled help
let matches = App::parse(Command::new("my-app"));

// Full application with command dispatch
App::builder()
    .command("list", |_m, _ctx| {
        Ok(Output::Render(json!({"items": ["a", "b"]})))
    }, "{% for item in items %}{{ item }}\n{% endfor %}")
    .build()?
    .run(cmd, std::env::args());

Re-exports§

pub use standout_seeker as seeker;

Modules§

assets
Framework-supplied assets (templates and styles).
cli
CLI dispatch and integration for clap-based applications.
context
Context injection for template rendering.
file_loader
File-based resource loading for templates and stylesheets.
style
Style system for named styles, aliases, and YAML-based stylesheets.
tabular
Unicode-aware column formatting for terminal tables.
topics
Help topics system for extended CLI documentation.
views
View abstractions for standardized CLI output patterns.

Macros§

dispatch
Declarative macro for defining command dispatch tables.
embed_styles
Embeds all stylesheet files from a directory at compile time.
embed_templates
Embeds all template files from a directory at compile time.

Structs§

EmbeddedSource
Embedded resource source with optional debug hot-reload.
Error
Represents template errors.
FileRegistry
Generic registry for file-based resources.
FileRegistryConfig
Configuration for a file registry.
LoadedFile
A file discovered during directory walking.
Renderer
A renderer with pre-registered templates.
StyleAttributes
Parsed style attributes from YAML.
Styles
A collection of named styles.
StylesheetRegistry
Registry for stylesheet/theme resolution from multiple sources.
StylesheetResource
Marker type for stylesheet resources.
TemplateFile
A template file discovered during directory walking.
TemplateRegistry
Registry for template resolution from multiple sources.
TemplateResource
Marker type for template resources.
Theme
A named collection of styles used when rendering templates.
ThemeVariants
Theme variants containing styles for base, light, and dark modes.
UnknownTagError
An error representing an unknown tag in the input.
UnknownTagErrors
A collection of unknown tag errors found during parsing.

Enums§

ColorDef
Parsed color definition from stylesheet.
ColorMode
The user’s preferred color mode.
LoadError
Error type for file loading operations.
LoadedEntry
How a resource is stored—file path (dev) or content (release).
OutputDestination
Destination for rendered output.
OutputMode
Controls how output is rendered.
RegistryError
Error type for template registry operations.
ResolvedTemplate
How a template’s content is stored or accessed.
SetupError
Error type for setup operations.
StyleDefinition
Parsed style definition from YAML.
StyleValidationError
Error returned when style validation fails.
StyleValue
A style value that can be either a concrete style or an alias to another style.
StylesheetError
Error type for stylesheet parsing failures.
UnknownTagKind
The kind of unknown tag encountered.

Constants§

DEFAULT_MISSING_STYLE_INDICATOR
Default prefix shown when a style name is not found.
STYLESHEET_EXTENSIONS
Recognized stylesheet file extensions in priority order.
TEMPLATE_EXTENSIONS
Recognized template file extensions in priority order.

Functions§

build_embedded_registry
Builds a registry map from embedded entries with extension priority handling.
detect_color_mode
Detects the user’s preferred color mode from the OS.
extension_priority
Returns the extension priority for a filename (lower = higher priority).
flatten_json_for_csv
Flattens a JSON Value into a list of records for CSV export.
parse_css
Parses a CSS stylesheet and builds theme variants.
parse_stylesheet
Parses a YAML stylesheet and builds theme variants.
render
Renders a template with automatic terminal color detection.
render_auto
Auto-dispatches between template rendering and direct serialization.
render_auto_with_context
Auto-dispatches with context injection support.
render_auto_with_spec
Auto-dispatches with granular control over structured output.
render_with_context
Renders a template with additional context objects injected.
render_with_mode
Renders a template with explicit output mode and color mode control.
render_with_output
Renders a template with explicit output mode control.
render_with_vars
Renders a template with additional variables injected into the context.
rgb_to_ansi256
Converts an RGB triplet to the nearest ANSI 256-color palette index.
rgb_to_truecolor
Placeholder helper for true-color output.
set_theme_detector
Overrides the detector used to determine whether the user prefers a light or dark theme.
strip_extension
Strips a recognized extension from a filename.
truncate_to_width
Truncates a string to fit within a maximum display width, adding ellipsis if needed.
validate_template
Validates a template for unknown style tags.
walk_dir
Walks a directory recursively and collects files with recognized extensions.
walk_template_dir
Walks a template directory and collects template files.
write_binary_output
Writes binary content to the specified destination.
write_output
Writes text content to the specified destination.

Type Aliases§

EmbeddedStyles
Type alias for embedded stylesheets.
EmbeddedTemplates
Type alias for embedded templates.

Derive Macros§

Seekable
Derives the Seekable trait for query-enabled structs.
Tabular
Derives a TabularSpec from struct field annotations.
TabularRow
Derives optimized row extraction for tabular formatting.