lv-tui-code-highlight 0.3.0

Syntax highlighting for the lv-tui framework
Documentation

lv-tui

A reactive TUI framework for Rust. Component tree, reactive state, CSS-like styling, event bubbling, focus management — everything you need to build complex terminal applications.

use lv_tui::prelude::*;
use lv_tui::Component;

#[derive(Component)]
struct Counter {
    #[reactive(paint, copy)]
    count: i32,
}

impl Counter {
    fn new() -> Self { Self { count: 0 } }
}

impl Component for Counter {
    fn render(&self, cx: &mut RenderCx) {
        cx.line(format!("count: {}", self.get_count()));
        cx.line("press + to increment, q to quit");
    }

    fn event(&mut self, event: &Event, cx: &mut EventCx) {
        if event.is_key(Key::Char('+')) { self.set_count(self.get_count() + 1, cx); }
        if event.is_key(Key::Char('q')) { cx.quit(); }
    }
}

fn main() -> lv_tui::Result<()> {
    App::new(Counter::new()).run()
}

Features

  • Component tree — compose UIs with Column, Row, Stack, Block, Scroll, Overlay
  • Reactive state#[reactive(paint)] auto-triggers repaint on change
  • Event bubbling — Capture → Target → Bubble with stop_propagation()
  • Focus management — Tab/Shift+Tab navigation with Focus/Blur events
  • CSS-like stylesheets — type/class/id selectors with style inheritance
  • Unicode — CJK/Emoji wide characters, text wrap, truncation, alignment
  • Async taskscx.spawn() for background work with TaskComplete events
  • Debug view — press d to visualize component borders and labels

Widgets

Widget Description
Label Text display with styling
Input Single-line text input with cursor
Column Vertical layout container
Row Horizontal layout container
Stack Layered/z-order container
Block Border + padding wrapper with optional title
Scroll Scrollable content container
Overlay Modal dialog with background dimming
Table Data table with headers, selection, and sorting
Tabs Tabbed container with keyboard navigation
Select Dropdown with keyboard navigation
Checkbox Toggleable boolean with label
RadioGroup Mutually exclusive radio selection
ProgressBar Unicode 8-segment progress bar
Dialog Border + key bindings (Esc/Enter) wrapper
SplitPane Resizable split panels (Ctrl+arrows)
VirtualList Virtual-scrolling list for large datasets

Text System

All widgets accept impl Into<Text>, giving you three levels of control:

use lv_tui::prelude::*;

// Simple: plain text
Label::new("hello")

// Styled: use Stylize trait
Label::new(Line::from(vec![
    "Error: ".red().bold(),
    Span::new("not found"),
]))

// Multi-line: build Text from Lines
Label::new(Text::from(vec![
    Line::from(Span::new("Title").bold()),
    Line::from(Span::new("Body")),
]))

Getting Started

Quick example

Create a settings form with checkboxes, radio group, and keyboard navigation:

use lv_tui::prelude::*;
use lv_tui::widgets::*;

struct App { content: Column }

impl App {
    fn new() -> Self {
        Self {
            content: Column::new()
                .child(Label::new("Settings").style(Style::default().bold()))
                .child(Label::new(""))
                .child(Checkbox::new("Enable notifications"))
                .child(Checkbox::new("Auto-save").checked())
                .child(Label::new(""))
                .child(Label::new("Theme:"))
                .child(RadioGroup::new(vec![
                    "Light".into(), "Dark".into(), "System".into(),
                ]))
                .child(Label::new(""))
                .child(Label::new("Tab: switch  Space: toggle  q: quit")
                    .style(Style::default().fg(Color::Gray))),
        }
    }
}

impl Component for App {
    fn render(&self, cx: &mut RenderCx) { self.content.render(cx); }
    fn event(&mut self, e: &Event, cx: &mut EventCx) {
        if e.is_key(Key::Char('q')) { cx.quit(); return; }
        self.content.event(e, cx);
    }
    fn layout(&mut self, r: lv_tui::geom::Rect, cx: &mut lv_tui::component::LayoutCx) { self.content.layout(r, cx); }
    fn measure(&self, c: lv_tui::layout::Constraint, _cx: &mut lv_tui::component::MeasureCx) -> lv_tui::geom::Size {
        lv_tui::geom::Size { width: c.max.width, height: c.max.height }
    }
    fn focusable(&self) -> bool { false }
}

fn main() -> lv_tui::Result<()> {
    lv_tui::app::App::new(App::new()).run()
}

Theme support

use lv_tui::prelude::*;

fn main() -> lv_tui::Result<()> {
    set_theme(Theme::Light); // or Theme::Dark (default)
    // ... rest of app
}

Clipboard

fn event(&mut self, event: &Event, cx: &mut EventCx) {
    // Copy selected text to system clipboard (OSC 52)
    cx.copy_to_clipboard("copied text");
}
[dependencies]
lv-tui = "0.3"
cargo run --example counter
cargo run --example demo_app

License

MIT