Context

R3BL TUI library & suite of apps focused on developer productivity

We are working on building command line apps in Rust which have rich text user interfaces (TUI). We want to lean into the terminal as a place of productivity, and build all kinds of awesome apps for it.

  1. 🔮 Instead of just building one app, we are building a library to enable any kind of rich TUI development w/ a twist: taking concepts that work really well for the frontend mobile and web development world and re-imagining them for TUI & Rust.

  2. 🌎 We are building apps to enhance developer productivity & workflows.

r3blrsutils_macro

This crate is related to the first thing that's described above. It provides lots of useful functionality to help you build TUI (text user interface) apps, along w/ general niceties & ergonomics that all Rustaceans 🦀 can enjoy 🎉:

Macros

Procedural

All the procedural macros are organized in 3 crates using an internal or core crate: the public crate, an internal or core crate, and the proc macro crate.

style! macro

Here's an example of the style! macro:

rust style! { id: "my_style", /* Optional. */ attrib: [dim, bold] /* Optional. */ padding: 10, /* Optional. */ color_fg: TuiColor::Blue, /* Optional. */ color_bg: TuiColor::Red, /* Optional. */ }

color_fg and color_bg can take any of the following:

  1. Color enum value.
  2. Rgb value.
  3. Variable holding either of the above.

Builder derive macro

This derive macro makes it easy to generate builders when annotating a struct or enum. It generates It has full support for generics. It can be used like this.

```rust

[derive(Builder)]

struct Point where X: std::fmt::Display + Clone, Y: std::fmt::Display + Clone, { x: X, y: Y, }

let mypt: Point = PointBuilder::new() .setx(1 as i32) .set_y(2 as i32) .build();

asserteq!(mypt.x, 1); asserteq!(mypt.y, 2); ```

makestructsafetoshareandmutate!

This function like macro (with custom syntax) makes it easy to manage shareability and interior mutability of a struct. We call this pattern the "manager" of "things").

🪄 You can read all about it here.

  1. This struct gets wrapped in a RwLock for thread safety.
  2. That is then wrapped inside an Arc so we can share it across threads.
  3. Additionally it works w/ Tokio so that it is totally async. It also fully supports generics and trait bounds w/ an optional where clause.

Here's a very simple usage:

rust make_struct_safe_to_share_and_mutate! { named MyMapManager<K, V> where K: Default + Send + Sync + 'static, V: Default + Send + Sync + 'static containing my_map of_type std::collections::HashMap<K, V> }

Here's an async example.

```rust

[tokio::test]

async fn testcustomsyntaxnowhereclause() { makestructsafetoshareandmutate! { named StringMap // where is optional and is missing here. containing mymap of_type std::collections::HashMap }

let mymanager: StringMap = StringMap::default(); let lockedmap = mymanager.mymap.read().await; asserteq!(lockedmap.len(), 0); drop(locked_map); } ```

makesafeasyncfnwrapper!

This function like macro (with custom syntax) makes it easy to share functions and lambdas that are async. They should be safe to share between threads and they should support either being invoked or spawned.

🪄 You can read all about how to write proc macros here.

  1. A struct is generated that wraps the given function or lambda in an Arc<RwLock<>> for thread safety and interior mutability.
  2. A get() method is generated which makes it possible to share this struct across threads.
  3. A from() method is generated which makes it easy to create this struct from a function or lambda.
  4. A spawn() method is generated which makes it possible to spawn the enclosed function or lambda asynchronously using Tokio.
  5. An invoke() method is generated which makes it possible to invoke the enclosed function or lambda synchronously.

Here's an example of how to use this macro.

```rust use r3blrsutils::makesafeasyncfnwrapper;

makesafeasyncfnwrapper! { named SafeMiddlewareFnWrapper containing fnmut oftype FnMut(A) -> Option } ```

Here's another example.

```rust use r3blrsutils::makesafeasyncfnwrapper;

makesafeasyncfnwrapper! { named SafeSubscriberFnWrapper containing fnmut oftype FnMut(S) -> () } ```

Other crates that depend on this

This crate is a dependency of r3bl_rs_utils crate (the "main" library).

Issues, comments, feedback, and PRs

Please report any issues to the issue tracker. And if you have any feature requests, feel free to add them there too 👍.