charmed-bubbletea 0.1.2

A powerful TUI framework based on The Elm Architecture
Documentation
# Bubbletea

An Elm-architecture TUI framework for Rust: pure `update`/`view`, command-driven
effects, and a deterministic event loop.

## TL;DR

**The Problem:** Terminal apps often mix state mutation and I/O in ways that are
hard to test and reason about.

**The Solution:** Bubbletea separates pure state transitions from effects.
`Model` + `Message` + `Cmd` gives you a testable core and a predictable runtime.

**Why Bubbletea**

- **Predictable**: pure `update` and `view` functions.
- **Composable**: child models compose cleanly.
- **Testable**: drive updates with messages and assert on views.
- **Async-ready**: optional async runtime support.

## Role in the charmed_rust (FrankenTUI) stack

Bubbletea is the runtime core. `bubbles`, `huh`, `glow`, and `wish` all build on
bubbletea’s `Model` abstraction. `lipgloss` styles the output, and `harmonica`
provides time-based motion helpers used in animations.

## Crates.io package

Package name: `charmed-bubbletea`  
Library crate name: `bubbletea`

## Installation

```toml
[dependencies]
bubbletea = { package = "charmed-bubbletea", version = "0.1.2" }
```

Enable optional features:

```toml
bubbletea = { package = "charmed-bubbletea", version = "0.1.2", features = ["async", "macros"] }
```

## Quick Start

```rust
use bubbletea::{Cmd, Message, Model, Program};

struct Counter {
    count: i32,
}

impl Model for Counter {
    fn update(&mut self, msg: Message) -> Cmd {
        if let Some(delta) = msg.downcast_ref::<i32>() {
            self.count += delta;
        }
        Cmd::none()
    }

    fn view(&self) -> String {
        format!("Count: {}", self.count)
    }
}

fn main() {
    Program::new(Counter { count: 0 }).run().unwrap();
}
```

## Core Concepts

- **Model**: your application state and logic.
- **Message**: events that drive state transitions.
- **Cmd**: effect descriptions (I/O, timers, async work).
- **Program**: event loop runner.

## API Overview

Key types live in `crates/bubbletea/src/`:

- `model.rs`: `Model` trait and lifecycle hooks.
- `message.rs`: `Message` type and downcasting helpers.
- `cmd.rs`: command helpers (`Cmd::none`, `Cmd::batch`, `Cmd::quit`).
- `program.rs`: event loop and runner configuration.
- `key.rs`: key event types and helpers.

## Feature Flags

- `macros`: derive macros for `Model` via `bubbletea-macros`.
- `async`: async runtime integration (tokio-based).
- `thread-pool`: batch commands with rayon.

## Testing Guidance

Test `update` and `view` directly:

```rust
let mut app = Counter { count: 0 };
app.update(Message::new(1));
assert_eq!(app.view(), "Count: 1");
```

For headless runs:

```rust
let model = Program::new(app).without_renderer().run().unwrap();
```

## Troubleshooting

- **No input events**: ensure the program is running in a tty.
- **Output garbled**: disable alternate screen or set a compatible `TERM`.
- **Async commands not running**: enable the `async` feature and use `tokio`.

## Limitations

- Terminal rendering is bound by terminal capabilities.
- High-frequency animation depends on your event loop tick rate.

## FAQ

**Can I use bubbletea without lipgloss?**  
Yes. Bubbletea renders strings; you can render them any way you want.

**Do I need the macros crate?**  
No. It’s optional and only adds ergonomics.

**Is async required?**  
No. Synchronous apps work out of the box.

## About Contributions

Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via `gh` and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.

## License

MIT. See `LICENSE` at the repository root.