Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/superhawk610/douglas
A tiny TUI framework built on the Elm architecture.
https://github.com/superhawk610/douglas
elm terminal tui ui
Last synced: about 2 months ago
JSON representation
A tiny TUI framework built on the Elm architecture.
- Host: GitHub
- URL: https://github.com/superhawk610/douglas
- Owner: superhawk610
- License: mit
- Created: 2022-05-11T07:16:25.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-05-13T08:09:23.000Z (over 2 years ago)
- Last Synced: 2024-10-31T06:51:32.488Z (about 2 months ago)
- Topics: elm, terminal, tui, ui
- Language: Rust
- Homepage:
- Size: 55.7 KB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
![douglas](./assets/banner.png)
Douglas is a tiny terminal UI framework built on the [Elm architecture][elm].
It's heavily inspired by [bubbletea][bubbletea] and [iced][iced].[elm]: https://guide.elm-lang.org/architecture/
[bubbletea]: https://github.com/charmbracelet/bubbletea
[iced]: https://github.com/iced-rs/iced## Usage
Building a UI with Douglas is a cinch!
```rust
use douglas::{Config, Program};struct App;
impl Program for App {
type Message = ();fn view(&self) -> String {
"Hello, world!\n".into()
}
}fn main() {
App.run(&mut Config::default()).unwrap();
}
```Granted, this isn't very exciting. Douglas apps just need 3 ingredients:
1. `init` initialize your state model, and perform any setup
2. `update` handle messages and user input
3. `view` render your UI (you've seen this already!)```rust
use douglas::{Command, Config, Mailbox, Program};// declare your state model
struct App {
counter: usize,
}// setup a constructor
impl App {
fn new() -> Self {
Self {
counter: 0,
}
}
}// declare message type
enum Message {
Increment,
Decrement,
}impl Program for App {
type Message = Message;fn init(&mut self, _: Mailbox) -> Command {
// send an Increment message right away
Command::send(Message::Increment)
}fn update(&mut self, message: Self::Message) -> Command {
// you can pattern match on incoming messages
match message {
Message::Increment => self.counter += 1,
Message::Decrement => self.counter -= 1,
}Command::none()
}fn view(&self) -> String {
format!("count: {}\n", self.counter)
}
}fn main() {
let app = App::new();
let config = Config::default();
app.run(&mut config).unwrap();
}
```Finally, if you need to do any cleanup, you may implement `exit`:
```rust
use douglas::Program;impl Program for App {
// (...snip...)fn exit(self) {
println!("Goodbye, cruel world!");
}
}
```## Handling Events
In addition to `update`, apps may implement `on_event` to send messages in
response to terminal events such as keypresses:```rust
use douglas::{Command, Program};
use crossterm::event::{Event, KeyCode, KeyEvent};impl Program for App {
// (...snip...)fn on_event(event: Event) -> Command {
match event {
Event::Key(KeyEvent { code: KeyCode::Up, .. }) =>
Command::send(Message::Increment),
_ => Command::none()
}
}
}
```## External Interaction
Sometimes it's useful to respond to events that occur outside of your program's
lifecycle, like responding when data becomes available on the network or sending
a message on a recurring interval. You can use your program's mailbox:```rust
use douglas::{Command, Mailbox, Program, Timer};
use crossterm::event::{Event, KeyCode, KeyEvent};
use std::time::Duration;struct App {
timer: Timer,
}#[derive(Clone)]
enum Message {
Tick,
}impl App {
fn new() -> Self {
Self {
timer: Timer::new(Duration::from_millis(1_000), Message::Tick),
}
}
}impl Program for App {
// (...snip...)fn init(&mut self, mailbox: Mailbox) -> Command {
self.timer.start(mailbox);Command::none()
}// make sure to clean up!
fn exit(mut self) {
self.timer.stop();
}
}
```## Examples
You can check out the [`examples`](./examples) directory to see some projects in
action. You can also run an example directly:```bash
cargo run --package hello_world
```## Contributing
This project is a work in progress. All contributions are welcome!
This project adheres to the Contributor Covenant [code of
conduct](./CODE_OF_CONDUCT.md). Please be nice to each other
:slightly_smiling_face:## License
This project is made available under the [MIT License](./LICENSE). Copyright
2022 Aaron Ross, all rights reserved.