removed dependency on colore eyre

This commit is contained in:
JasterV 2026-01-29 02:38:59 +01:00
parent c11e3a7364
commit 7ad9f943e7
10 changed files with 75 additions and 237 deletions

183
Cargo.lock generated
View file

@ -2,21 +2,6 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "addr2line"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aho-corasick"
version = "1.1.4"
@ -53,21 +38,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "backtrace"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-link",
]
[[package]]
name = "base64"
version = "0.22.1"
@ -143,33 +113,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "color-eyre"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d"
dependencies = [
"backtrace",
"color-spantrace",
"eyre",
"indenter",
"once_cell",
"owo-colors",
"tracing-error",
]
[[package]]
name = "color-spantrace"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427"
dependencies = [
"once_cell",
"owo-colors",
"tracing-core",
"tracing-error",
]
[[package]]
name = "compact_str"
version = "0.9.0"
@ -197,7 +140,6 @@ dependencies = [
name = "counter"
version = "0.0.0"
dependencies = [
"color-eyre",
"crossterm",
"ratatui",
"teatui",
@ -380,16 +322,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "eyre"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "fancy-regex"
version = "0.11.0"
@ -457,12 +389,6 @@ dependencies = [
"wasip2",
]
[[package]]
name = "gimli"
version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]]
name = "hashbrown"
version = "0.16.1"
@ -492,12 +418,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indenter"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5"
[[package]]
name = "indoc"
version = "2.0.7"
@ -656,15 +576,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.1.1"
@ -735,15 +646,6 @@ dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.21.3"
@ -759,12 +661,6 @@ dependencies = [
"num-traits",
]
[[package]]
name = "owo-colors"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
[[package]]
name = "parking_lot"
version = "0.12.5"
@ -883,12 +779,6 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "portable-atomic"
version = "1.13.0"
@ -1063,12 +953,6 @@ version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "rustc-demangle"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -1156,15 +1040,6 @@ dependencies = [
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "signal-hook"
version = "0.3.18"
@ -1267,9 +1142,9 @@ dependencies = [
name = "teatui"
version = "0.1.0"
dependencies = [
"color-eyre",
"crossterm",
"ratatui",
"thiserror 2.0.18",
]
[[package]]
@ -1375,15 +1250,6 @@ dependencies = [
"syn 2.0.114",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "time"
version = "0.3.46"
@ -1405,47 +1271,6 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-error"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"sharded-slab",
"thread_local",
"tracing-core",
]
[[package]]
name = "typenum"
version = "1.19.0"
@ -1505,12 +1330,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "version_check"
version = "0.9.5"

View file

@ -8,6 +8,5 @@ license = "MIT"
edition = "2024"
[workspace.dependencies]
color-eyre = "0.6.3"
crossterm = "0.29.0"
ratatui = { version = "0.30", features = ["unstable-widget-ref"] }

View file

@ -6,7 +6,6 @@ edition.workspace = true
authors.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
ratatui.workspace = true
teatui = { path = "../../teatui" }

View file

@ -1,4 +1,3 @@
use color_eyre::Result;
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use ratatui::{
style::Stylize,
@ -7,8 +6,7 @@ use ratatui::{
};
use teatui::Update;
fn main() -> Result<()> {
color_eyre::install()?;
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
teatui::start(|| (Model::default(), None), update, view, run_effects)
}
@ -37,9 +35,11 @@ impl Model {
}
/// Possible side effects to execute
#[derive(Debug)]
pub enum Effect {}
/// Messages that represent a change of state in the application
#[derive(Debug)]
pub enum Message {
IncCounter,
DecCounter,
@ -92,23 +92,23 @@ impl From<crossterm::event::Event> for Message {
///
/// Given the current state (model) and an incoming message from the outside world,
/// return the next updated state
pub fn update(model: Model, msg: Message) -> Result<Update<Model, Effect>> {
pub fn update(model: Model, msg: Message) -> Update<Model, Effect> {
match msg {
Message::Exit => Ok(Update::Exit),
Message::NoOp => Ok(Update::Next(model, None)),
Message::IncCounter => Ok(Update::Next(Model::increment_counter(model), None)),
Message::DecCounter => Ok(Update::Next(Model::decrement_counter(model), None)),
Message::Exit => Update::Exit,
Message::NoOp => Update::Next(model, None),
Message::IncCounter => Update::Next(Model::increment_counter(model), None),
Message::DecCounter => Update::Next(Model::decrement_counter(model), None),
}
}
pub fn run_effects(_model: &Model, _effect: Effect) -> Result<Option<Message>> {
Ok(None)
pub fn run_effects(_model: &Model, _effect: Effect) -> Option<Message> {
None
}
/// Elm-like View function.
///
/// Given the current state (read-only), return a drawable widget.
pub fn view(model: &Model) -> Result<Paragraph<'static>> {
pub fn view(model: &Model) -> Paragraph<'static> {
let counter = model.counter;
let title = Line::from("Ratatui Actor-based Counter")
@ -124,9 +124,7 @@ Counter: {counter}
Press `Esc`, `Ctrl-C` or `q` to stop running."#
);
let widget = Paragraph::new(text)
Paragraph::new(text)
.block(Block::bordered().title(title))
.centered();
Ok(widget)
.centered()
}

View file

@ -7,6 +7,6 @@ authors.workspace = true
edition.workspace = true
[dependencies]
color-eyre.workspace = true
crossterm.workspace = true
ratatui.workspace = true
thiserror = "2"

View file

@ -1,23 +1,21 @@
//! Actor responsible of processing side effects sent by the update actor.
use color_eyre::Result;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::sync::mpsc::{Receiver, SendError, Sender};
pub(crate) fn run<M, Msg, Eff, F>(
effects_fn: F,
rx: Receiver<(M, Eff)>,
tx: Sender<Msg>,
) -> Result<()>
) -> Result<(), SendError<Msg>>
where
Msg: Send + Sync + 'static,
F: Fn(&M, Eff) -> Result<Option<Msg>>,
F: Fn(&M, Eff) -> Option<Msg>,
{
loop {
let Ok((model, effect)) = rx.recv() else {
return Ok(());
};
if let Some(msg) = effects_fn(&model, effect)? {
if let Some(msg) = effects_fn(&model, effect) {
tx.send(msg)?;
}
}

View file

@ -1,11 +1,19 @@
//! Actor responsible of reading terminal input events.
use color_eyre::Result;
use crossterm::event;
use std::sync::mpsc::Sender;
use std::fmt::Debug;
use std::sync::mpsc::{SendError, Sender};
pub(crate) fn run<M>(tx: Sender<M>) -> Result<()>
#[derive(thiserror::Error, Debug)]
pub(crate) enum EventError<M> {
#[error("Failed to send message to update process")]
MessageSend(#[from] SendError<M>),
#[error("Failed to read crossterm event")]
EventRead(#[from] std::io::Error),
}
pub(crate) fn run<M>(tx: Sender<M>) -> Result<(), EventError<M>>
where
M: From<crossterm::event::Event> + Sync + Send + 'static,
M: From<crossterm::event::Event> + Debug + Sync + Send + 'static,
{
loop {
let message = M::from(event::read()?);

View file

@ -31,9 +31,8 @@
//! ### Examples
//!
//! You can find a folder with example projects in the [examples](https://github.com/JasterV/teatui/tree/main/examples) folder.
use color_eyre::Report;
use color_eyre::Result;
use ratatui::widgets::Widget;
use std::fmt::Debug;
use std::{
sync::mpsc::{Sender, channel},
thread,
@ -63,23 +62,23 @@ pub fn start<M, Msg, Eff, W, IF, UF, VF, EF>(
update_fn: UF,
view_fn: VF,
effects_fn: EF,
) -> Result<(), Report>
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>
where
M: Clone + Send + Sync + 'static,
Eff: Send + Sync + 'static,
Msg: From<crossterm::event::Event> + Sync + Send + 'static,
M: Clone + Debug + Send + Sync + 'static,
Eff: Debug + Send + Sync + 'static,
Msg: From<crossterm::event::Event> + Debug + Sync + Send + 'static,
W: Widget,
IF: Fn() -> (M, Option<Eff>) + Send + Sync + 'static,
UF: Fn(M, Msg) -> Result<Update<M, Eff>> + Send + Sync + 'static,
VF: Fn(&M) -> Result<W> + Send + Sync + 'static,
EF: Fn(&M, Eff) -> Result<Option<Msg>> + Send + Sync + 'static,
UF: Fn(M, Msg) -> Update<M, Eff> + Send + Sync + 'static,
VF: Fn(&M) -> W + Send + Sync + 'static,
EF: Fn(&M, Eff) -> Option<Msg> + Send + Sync + 'static,
{
let terminal = ratatui::init();
let (model, effect) = init_fn();
// Channel for signaling when a task completes
let (shutdown_tx, shutdown_rx) = channel::<Result<()>>();
let (shutdown_tx, shutdown_rx) = channel::<Result<(), _>>();
// Channels for inter-thread communication
let (update_tx, update_rx) = channel::<Msg>();
@ -92,33 +91,42 @@ where
//
let model_1 = model.clone();
spawn_thread(
|| view::run(model_1, terminal, view_fn, view_rx),
|| view::run(model_1, terminal, view_fn, view_rx).map_err(Box::from),
shutdown_tx.clone(),
);
spawn_thread(
|| update::run(model, effect, update_fn, update_rx, view_tx, effects_tx),
|| update::run(model, effect, update_fn, update_rx, view_tx, effects_tx).map_err(Box::from),
shutdown_tx.clone(),
);
let effects_update_tx = update_tx.clone();
spawn_thread(
|| effects::run(effects_fn, effects_rx, effects_update_tx),
|| effects::run(effects_fn, effects_rx, effects_update_tx).map_err(Box::from),
shutdown_tx.clone(),
);
spawn_thread(|| events::run(update_tx), shutdown_tx.clone());
spawn_thread(
|| events::run(update_tx).map_err(Box::from),
shutdown_tx.clone(),
);
let result = shutdown_rx.recv();
let result = shutdown_rx.recv().ok();
ratatui::restore();
result?
match result {
Some(result) => result,
None => Ok(()),
}
}
fn spawn_thread<F>(callback: F, shutdown: Sender<Result<()>>) -> thread::JoinHandle<()>
fn spawn_thread<F>(
callback: F,
shutdown: Sender<Result<(), Box<dyn std::error::Error + Send + Sync + 'static>>>,
) -> thread::JoinHandle<()>
where
F: FnOnce() -> Result<()>,
F: FnOnce() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>>,
F: Send + 'static,
{
thread::spawn(move || {

View file

@ -1,6 +1,5 @@
//! Actor responsible of maintaining the state of the application.
use color_eyre::{Report, Result};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc::{Receiver, SendError, Sender};
/// Tells the runtime what to do with the previous message.
///
@ -12,6 +11,17 @@ pub enum Update<M, E> {
Next(M, Option<E>),
}
#[derive(thiserror::Error, Debug)]
pub(crate) enum UpdateError<M, Eff>
where
Eff: Send + Sync + 'static,
{
#[error("Failed to send message to effects handler process")]
EffectSend(#[from] SendError<(M, Eff)>),
#[error("Failed to send message to the view process")]
ViewSend(#[from] SendError<M>),
}
pub(crate) fn run<M, Msg, Eff, F>(
mut model: M,
initial_effect: Option<Eff>,
@ -19,9 +29,9 @@ pub(crate) fn run<M, Msg, Eff, F>(
rx: Receiver<Msg>,
view_tx: Sender<M>,
effects_tx: Sender<(M, Eff)>,
) -> Result<()>
) -> Result<(), UpdateError<M, Eff>>
where
F: Fn(M, Msg) -> Result<Update<M, Eff>, Report>,
F: Fn(M, Msg) -> Update<M, Eff>,
Eff: Sync + Send + 'static,
M: Clone + Sync + Send + 'static,
{
@ -34,7 +44,7 @@ where
return Ok(());
};
let update = update_fn(model, msg)?;
let update = update_fn(model, msg);
let (new_model, effect) = match update {
Update::Exit => return Ok(()),

View file

@ -1,5 +1,4 @@
//! Actor responsible of rendering the model into the terminal.
use color_eyre::Result;
use ratatui::DefaultTerminal;
use ratatui::widgets::Widget;
use std::sync::mpsc::Receiver;
@ -9,13 +8,13 @@ pub(crate) fn run<M, F, W>(
mut terminal: DefaultTerminal,
view_fn: F,
rx: Receiver<M>,
) -> Result<()>
) -> Result<(), std::io::Error>
where
W: Widget,
F: Fn(&M) -> Result<W>,
F: Fn(&M) -> W,
{
loop {
let widget = view_fn(&model)?;
let widget = view_fn(&model);
terminal.draw(|frame| frame.render_widget(widget, frame.area()))?;