| Crates.io | fusabi-tui |
| lib.rs | fusabi-tui |
| version | 0.2.0 |
| created_at | 2025-12-01 20:24:27.316139+00 |
| updated_at | 2025-12-06 03:33:23.460131+00 |
| description | Terminal UI library for Fusabi - providing Ratatui bindings and widgets |
| homepage | |
| repository | https://github.com/raibid-labs/fusabi-tui |
| max_upload_size | |
| id | 1960577 |
| size | 253,144 |
Terminal UI library for Fusabi - providing Ratatui bindings and widgets
fusabi-tui is a Rust library that exposes the powerful Ratatui terminal UI framework to Fusabi scripts (F# for configuration). This enables rich, interactive terminal interfaces to be built declaratively using F# syntax.
Status: Production-ready - Extracted from Hibana project, fully tested and documented
Add to your Cargo.toml:
[dependencies]
fusabi-tui = "0.1.0"
use fusabi_tui::widgets::{TableData, ColumnDef, render_table};
use ratatui::layout::Constraint;
let columns = vec![
ColumnDef {
header: "GPU".to_string(),
width: Constraint::Length(10),
},
ColumnDef {
header: "Utilization".to_string(),
width: Constraint::Length(15),
},
];
let rows = vec![
vec!["GPU 0".to_string(), "85%".to_string()],
vec!["GPU 1".to_string(), "92%".to_string()],
];
let table = TableData::new(columns, rows)
.title("GPU Stats")
.borders(true);
// In your render loop:
frame.render_widget(render_table(&table), area);
use fusabi_tui::canvas::{GraphCanvas, GraphData, GraphNode, GraphEdge};
let mut graph = GraphData::new();
// Add nodes
graph.add_node(GraphNode::builder()
.id("source")
.label("Data Source")
.position(0.0, 0.0)
.build());
graph.add_node(GraphNode::builder()
.id("sink")
.label("Data Sink")
.position(10.0, 5.0)
.selected(true) // Highlight this node
.build());
// Add edges
graph.add_edge(GraphEdge::new("source", "sink")
.label("1.5K events/s"));
// Render
let canvas = GraphCanvas::new(&graph, None); // Auto-calculate bounds
frame.render_widget(canvas, area);
use fusabi_tui::formatting::{format_number, format_bytes, format_latency, format_duration};
use std::time::Duration;
// Format large numbers with K/M/B/T suffixes
assert_eq!(format_number(1_500), "1.50K");
assert_eq!(format_number(2_500_000), "2.50M");
assert_eq!(format_number(3_000_000_000), "3.00B");
// Format byte sizes with appropriate units
assert_eq!(format_bytes(1024), "1.00 KB");
assert_eq!(format_bytes(1_048_576), "1.00 MB");
assert_eq!(format_bytes(1_073_741_824), "1.00 GB");
// Format latency (input in microseconds)
assert_eq!(format_latency(500), "500μs");
assert_eq!(format_latency(1_500), "1.50ms");
assert_eq!(format_latency(2_000_000), "2.00s");
// Format duration (input as std::time::Duration)
assert_eq!(format_duration(Duration::from_secs(45)), "45s");
assert_eq!(format_duration(Duration::from_secs(125)), "2m 5s");
assert_eq!(format_duration(Duration::from_secs(3665)), "1h 1m");
// From a Fusabi script (.fsx)
open Fusabi.TUI
// Create a simple list widget
let list = List.create [
"Item 1"
"Item 2"
"Item 3"
]
// Define a vertical layout
let layout = Layout.vertical [
Constraint.Percentage 50
Constraint.Min 10
]
The library is organized into five main modules:
src/widgets/)Provides type-safe builders for Ratatui widgets:
src/layouts/)Constraint-based layout system for dividing terminal space:
src/canvas/)Low-level drawing primitives for custom graphics:
src/formatting/)Human-readable formatting utilities for common data types:
use fusabi_tui::{format_number, format_bytes, format_latency};
println!("{}", format_number(1_500_000)); // "1.50M"
println!("{}", format_bytes(2048)); // "2.00 KB"
println!("{}", format_latency(1500)); // "1.50ms"
src/bindings/)Fusabi VM integration layer:
bindings feature)Total Tests: 59
- Canvas tests: 27 (nodes, edges, bounds, graph rendering)
- Formatting tests: 20 (numbers, bytes, time formatting)
- Widget tests: 10 (table rendering, column definitions)
- Library tests: 2 (version, module structure)
See the examples/ directory for working demonstrations:
simple_list.rs: Basic list widget usage and renderinglayout_demo.rs: Constraint-based layout system demonstrationgraph_demo.rs: Interactive graph visualization with nodes and edgestable_demo.rs: Table widget with multiple columns and data rowsRun examples with:
cargo run --example formatting_demo
cargo run --example graph_demo
cargo run --example table_demo
The library supports optional features via Cargo feature flags:
[dependencies]
fusabi-tui = { version = "0.1.0", features = ["bindings"] }
Available features:
bindings - Enables Fusabi VM integration (requires fusabi dependency)
FusabiTuiModule for registering native functionsTo use the library without Fusabi integration:
[dependencies]
fusabi-tui = { version = "0.1.0", default-features = false }
Fusabi Bindings: The bindings module currently has limitations due to Fusabi's Rc<RefCell<T>> design (not Send+Sync). Full widget lifecycle management from F# scripts is not yet supported. Currently available:
Layout System: The layouts module is currently a stub. Full constraint-based layout is planned for v0.2.0.
Widget Coverage: Currently implemented widgets:
Add dependency:
[dependencies]
fusabi-tui = { path = "../fusabi-tui" } # Or version from crates.io
ratatui = "0.28"
Import types:
use fusabi_tui::{
formatting::{format_number, format_bytes, format_latency, format_duration},
widgets::{TableData, ColumnDef, render_table},
canvas::{GraphCanvas, GraphData, GraphNode, GraphEdge},
};
Use in render loop:
use ratatui::prelude::*;
use fusabi_tui::widgets::render_table;
fn ui(frame: &mut Frame, table_data: &TableData) {
let area = frame.size();
frame.render_widget(render_table(table_data), area);
}
If you're using the bindings feature:
use fusabi_tui::bindings::FusabiTuiModule;
use fusabi::Engine;
let mut engine = Engine::new();
let tui_module = FusabiTuiModule::new();
tui_module.register(&mut engine)?;
// Now F# scripts can call:
// - tui_format_number(n: int) -> string
// - tui_format_bytes(bytes: int) -> string
// - tui_format_latency(us: int) -> string
// - tui_format_duration(secs: int) -> string
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run benchmarks
cargo bench
Generate and view the full API documentation:
cargo doc --open
Current Documentation (latest development):
Versioned Documentation:
docs/versions/ as they are releasedThis library is designed to work with:
For detailed integration patterns, see Plugin Runtime Integration Guide.
This is part of the Raibid Labs ecosystem. Contributions welcome!
cargo testcargo fmtcargo clippy -- -D warningsLicensed under either of:
at your option.
Version: 0.1.0 Last Updated: 2025-01-26