diff --git a/README.md b/README.md
index 4b28b99..e20e2dc 100644
--- a/README.md
+++ b/README.md
@@ -17,21 +17,23 @@
- OSUI is a customizable terminal user interface (TUI) library written in Rust. It provides a set of components and rsx to build interactive command-line interfaces with ease.
+ OSUI is a customizable terminal user interface (TUI) library written in Rust.
```rust
use osui::prelude::*;
-fn main() -> std::io::Result<()> {
- let screen = Screen::new();
+pub fn main() {
+ let engine = Console::new();
+ engine.run(App {}).expect("Failed to run engine");
+}
+#[component]
+fn App(cx: &Arc) -> View {
rsx! {
- "Hello, World"
+ "Hello World"
}
- .draw(&screen);
-
- screen.run()
+ .view(&cx)
}
```
diff --git a/benchmark.csv b/benchmark.csv
index 65d5940..50f08bb 100644
--- a/benchmark.csv
+++ b/benchmark.csv
@@ -1,227 +1,227 @@
Iterx72,Nestingx72,Time µs
-14,14,14236
-11,8,10608
-8,13,7793
-13,7,12073
-11,6,10495
-5,2,5135
-6,12,6144
-6,3,6341
-12,7,11304
-11,5,10622
-0,9,497
-3,2,3303
-5,1,5186
-10,8,9781
-1,11,1358
-2,9,2341
-10,11,9788
-14,5,13036
-9,1,8807
-4,12,4249
-8,1,8306
-14,4,12985
-5,0,419
-4,13,4234
-10,1,9793
-3,13,3255
-0,4,625
-7,6,7066
-8,12,7954
-10,12,9876
-8,11,8015
-6,8,6104
-0,11,514
-2,10,2373
-8,2,7891
-2,14,2337
-2,13,2337
-7,12,7006
-3,10,3300
-11,10,10772
-4,5,4299
-10,14,9909
-12,5,11532
-9,10,8809
-12,12,11954
-14,11,13452
-8,8,7965
-4,0,449
-5,6,5127
-7,8,6921
-4,4,4244
-1,10,1370
-5,9,5122
-1,7,1369
-0,3,844
-8,3,7937
-9,9,8777
-13,6,12476
-9,3,8961
-2,5,2368
-1,12,1363
-5,12,5075
-13,11,12363
-6,13,5963
-0,8,484
-2,12,2370
-8,5,7946
-14,9,13504
-12,1,11839
-12,2,11601
-2,6,2329
-10,10,9602
-7,3,6970
-14,6,13394
-0,7,628
-6,9,6100
-12,13,11391
-0,12,458
-1,14,1370
-12,10,11719
-9,8,8807
-4,7,4235
-1,0,462
-3,11,3538
-11,7,10786
-11,13,10710
-11,2,10394
-3,9,3315
-4,6,4174
-13,8,12538
-9,11,8710
-12,14,11814
-13,2,12647
-8,7,8019
-3,1,3287
-4,8,4591
-4,3,4197
-6,10,5985
-5,7,5171
-12,9,11579
-10,4,9714
-12,4,11811
-2,3,2391
-8,9,7997
-9,7,8853
-11,1,10700
-11,11,10798
-13,4,12644
-6,4,6290
-6,2,5916
-2,0,427
-2,8,2355
-10,2,9637
-6,5,6069
-6,11,6048
-12,11,11921
-9,4,8754
-5,4,5111
-13,10,12518
-8,14,7837
-5,8,5127
-8,10,8085
-0,2,1028
-2,1,2400
-0,13,408
-6,14,6027
-12,8,11785
-2,2,2326
-1,2,1394
-4,1,4251
-1,1,1446
-3,0,433
-10,13,9693
-9,0,432
-1,3,1441
-9,13,8858
-9,14,8795
-11,9,10632
-12,0,417
-7,1,7013
-6,1,6097
-10,7,10114
-10,9,9876
-10,5,9802
-2,4,2363
-11,12,10781
-11,14,10677
-3,7,3262
-6,7,6201
-4,9,4380
-3,8,3345
-13,9,12485
-0,14,419
-1,6,1347
-4,2,4216
-4,14,4209
-7,9,6976
-13,0,458
-0,1,361
-5,14,5204
-14,2,13169
-5,10,5096
-1,5,1370
-8,0,431
-6,6,6031
-8,4,7809
-9,12,11983
-3,4,3276
-12,6,11921
-6,0,485
-1,13,1375
-4,11,4237
-0,10,481
-13,13,12545
-14,12,13253
-3,5,3210
-5,5,5158
-7,7,6992
-5,11,5076
-7,13,7056
-11,3,10584
-3,3,3302
-14,13,13280
-13,3,12771
-14,0,429
-7,5,7065
-7,14,6952
-8,6,7835
-2,7,2334
-2,11,2367
-11,4,10606
-7,11,6845
-14,8,13736
-0,5,844
-1,9,1333
-10,6,9721
-9,6,8769
-7,10,6998
-10,3,9810
-14,7,13311
-14,14,13481
-11,0,426
-5,3,5102
-1,4,1457
-13,14,12431
-12,3,11717
-13,5,12523
-14,10,13457
-0,6,705
-3,14,3335
-13,12,12714
-7,4,6951
-3,6,3247
-9,5,8713
-3,12,3401
-14,1,13199
-4,10,4260
-10,0,428
-5,13,5103
-0,0,421
-14,3,13070
-9,2,8816
-7,0,451
-7,2,6974
-1,8,1363
-13,1,12699
\ No newline at end of file
+14,14,11964
+0,1,1078
+5,8,1818
+10,13,2632
+14,2,3392
+0,9,520
+9,3,2360
+10,5,2551
+10,11,2548
+6,8,1738
+12,12,2922
+0,8,601
+12,4,2919
+0,11,521
+6,4,1942
+11,7,2741
+9,4,2496
+5,9,1764
+13,9,3069
+2,5,1053
+5,11,1790
+14,1,3581
+5,0,962
+0,3,845
+1,3,868
+7,8,2013
+12,3,2987
+9,8,2328
+10,7,2533
+11,1,2766
+7,1,1938
+0,5,687
+6,9,1830
+10,14,2628
+6,12,1786
+4,0,835
+4,14,2464
+10,1,2633
+12,7,2948
+2,9,1066
+4,6,2646
+7,11,1999
+5,13,1748
+13,4,3110
+13,13,3094
+3,5,1166
+11,12,2745
+1,2,814
+9,5,2419
+2,11,1117
+1,13,835
+11,11,2759
+1,12,882
+9,1,2457
+0,6,680
+5,12,1794
+9,11,2326
+10,9,2546
+10,10,2604
+13,2,3250
+13,7,3113
+7,10,1959
+1,14,833
+6,6,1886
+14,7,3339
+6,7,1824
+11,6,2756
+12,6,3007
+14,6,3315
+4,3,11464
+2,14,924
+7,12,1966
+11,14,2817
+9,10,2367
+1,11,827
+8,14,2184
+14,0,643
+11,3,2781
+2,4,1123
+12,8,2950
+13,6,3160
+3,13,1289
+7,7,1989
+3,9,1142
+3,6,1168
+4,8,2788
+14,12,3346
+1,1,805
+5,10,1781
+7,13,1988
+5,5,2015
+0,14,520
+11,8,2890
+3,10,1140
+13,10,3235
+3,14,1185
+8,10,2183
+12,10,2896
+2,8,1072
+9,6,2358
+13,1,3066
+3,8,1133
+11,10,2758
+4,13,2550
+1,0,643
+4,2,5482
+3,7,1155
+1,4,726
+3,3,1192
+4,11,2576
+8,0,619
+9,2,2444
+10,3,2581
+4,5,5400
+5,3,2444
+1,10,804
+10,2,2563
+0,7,592
+0,2,802
+1,5,741
+2,7,984
+10,0,755
+13,14,3112
+5,14,1811
+8,12,2180
+6,11,1723
+4,7,2897
+10,8,2536
+1,7,813
+6,0,699
+8,2,2187
+5,7,1811
+14,8,3304
+2,0,661
+8,13,2185
+1,9,786
+3,0,623
+12,5,3012
+8,1,2203
+8,11,2285
+14,10,3413
+4,10,2613
+11,5,2729
+6,1,2035
+12,1,2891
+5,4,2036
+2,3,1083
+14,3,3312
+3,2,1278
+5,2,2392
+8,7,2151
+5,6,2072
+3,12,1230
+2,10,954
+2,13,932
+13,8,3128
+0,12,521
+11,4,2769
+7,2,1947
+4,1,1802
+8,8,2163
+7,3,1966
+13,3,3207
+1,8,746
+12,9,2955
+10,12,2570
+9,9,2388
+4,12,2566
+7,0,619
+7,9,2004
+13,0,607
+14,9,3355
+3,4,1154
+11,2,2753
+11,13,2739
+6,13,1735
+7,6,1983
+8,3,2166
+7,14,1958
+6,2,2101
+13,5,3221
+8,4,2120
+10,4,2716
+14,5,3264
+14,13,3299
+11,9,2725
+13,11,3132
+1,6,809
+2,2,1155
+4,4,2242
+8,6,2218
+12,0,645
+7,4,1925
+2,6,1054
+9,13,2340
+13,12,3112
+14,4,3334
+3,11,1139
+12,14,3004
+4,9,2649
+0,13,527
+12,11,2976
+0,0,1559
+12,13,2952
+6,10,1749
+14,11,3365
+11,0,647
+2,12,1024
+10,6,2562
+8,5,2227
+9,12,2363
+2,1,1023
+0,10,528
+6,3,2005
+8,9,2195
+7,5,1966
+6,14,1755
+9,0,608
+14,14,3389
+9,7,2391
+0,4,688
+5,1,2574
+9,14,2353
+12,2,2975
+3,1,1276
+6,5,1804
\ No newline at end of file
diff --git a/macros/src/emit.rs b/macros/src/emit.rs
index bd31d80..60884ca 100644
--- a/macros/src/emit.rs
+++ b/macros/src/emit.rs
@@ -76,15 +76,13 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream {
{
#deps_emit
r.dynamic_scope(move |scope| {
- scope.access_children(|children| {
- if #cond {
- if children.is_empty() {
- #(#kids)*
- }
- } else {
- .children.clear();
+ if #cond {
+ if scope.children.lock().unwrap().is_empty() {
+ #(#kids)*
}
- })
+ } else {
+ scope.children.lock().unwrap().clear();
+ }
}, #deps_vec_emit);
}
}
@@ -105,7 +103,7 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream {
#deps_emit
#[allow(unused_parens)]
r.dynamic_scope(move |scope| {
- scope.access_children(|children| children.clear());
+ scope.children.lock().unwrap().clear();
for #pat in #expr {
#(#kids)*
}
diff --git a/src/component/context.rs b/src/component/context.rs
index de08664..636cf5f 100644
--- a/src/component/context.rs
+++ b/src/component/context.rs
@@ -20,7 +20,7 @@ pub struct Context {
component: AccessCell,
view: AccessCell,
event_handlers: AccessCell>>,
- scopes: AccessCell>>,
+ pub(crate) scopes: Mutex>>,
executor: Arc,
}
@@ -33,7 +33,7 @@ impl Context {
component: AccessCell::new(Arc::new(component)),
view: AccessCell::new(Arc::new(|_| {})),
event_handlers: AccessCell::new(HashMap::new()),
- scopes: AccessCell::new(Vec::new()),
+ scopes: Mutex::new(Vec::new()),
executor,
})
}
@@ -111,16 +111,11 @@ impl Context {
(h.lock().unwrap())(self, event.as_ref());
}
- self.scopes.access(move |scopes| {
- for scope in scopes {
- let event = event.clone();
- scope.access_children(move |children| {
- for (child, _) in children {
- child.emit_event(event.clone());
- }
- });
+ for scope in self.scopes.lock().unwrap().iter() {
+ for (child, _) in scope.children.lock().unwrap().iter() {
+ child.emit_event(event.clone());
}
- });
+ }
}
pub fn emit_event_threaded(
@@ -139,26 +134,16 @@ impl Context {
});
}
- let event = event.clone();
- self.scopes.access(move |scopes| {
- for scope in scopes {
- let event = event.clone();
- scope.access_children(move |children| {
- for (child, _) in children {
- child.emit_event_threaded(&event);
- }
- });
+ for scope in self.scopes.lock().unwrap().iter() {
+ for (child, _) in scope.children.lock().unwrap().iter() {
+ child.emit_event_threaded(event);
}
- });
+ }
}
pub fn scope(self: &Arc) -> Arc {
let scope = Scope::new(self.executor.clone());
-
- self.scopes.access({
- let scope = scope.clone();
- move |scopes| scopes.push(scope)
- });
+ self.scopes.lock().unwrap().push(scope.clone());
scope
}
@@ -169,11 +154,7 @@ impl Context {
dependencies: &[&dyn HookDependency],
) -> Arc {
let scope = Scope::new(self.executor.clone());
-
- self.scopes.access({
- let scope = scope.clone();
- move |scopes| scopes.push(scope)
- });
+ self.scopes.lock().unwrap().push(scope.clone());
drawer(&scope);
@@ -191,34 +172,21 @@ impl Context {
}
pub fn add_scope(self: &Arc, scope: Arc) {
- self.scopes.access(|scopes| scopes.push(scope));
+ self.scopes.lock().unwrap().push(scope);
}
pub fn draw_children(self: &Arc, ctx: &mut DrawContext) {
- let c = ctx.clone();
+ for scope in self.scopes.lock().unwrap().iter() {
+ for (child, view_wrapper) in scope.children.lock().unwrap().iter() {
+ let view = child.get_view();
- let (tx, rx) = std::sync::mpsc::channel::();
-
- self.scopes.access(move |scopes| {
- for scope in scopes {
- let mut c = c.clone();
- let tx = tx.clone();
- scope.access_children(move |children| {
- for (child, view_wrapper) in children {
- let view = child.get_view();
-
- if let Some(view_wrapper) = view_wrapper {
- view_wrapper(&mut c, view)
- } else {
- c.draw_view(c.area.clone(), view);
- }
- }
- tx.send(c.clone()).expect("Failed transmitting DrawContext");
- });
+ if let Some(view_wrapper) = view_wrapper {
+ view_wrapper(ctx, view)
+ } else {
+ ctx.draw_view(ctx.area.clone(), view);
+ }
}
- });
-
- *ctx = rx.recv().expect("Failed receiving DrawContext");
+ }
}
pub fn get_executor(self: &Arc) -> Arc {
diff --git a/src/component/scope.rs b/src/component/scope.rs
index 83201ce..6cfe6e5 100644
--- a/src/component/scope.rs
+++ b/src/component/scope.rs
@@ -1,19 +1,18 @@
-use super::{context::Context, ComponentImpl};
-use crate::{engine::CommandExecutor, View, ViewWrapper};
-use access_cell::AccessCell;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
-pub type ScopeChildren = Vec<(Arc, Option)>;
+use crate::{engine::CommandExecutor, View, ViewWrapper};
+
+use super::{context::Context, ComponentImpl};
pub struct Scope {
- children: AccessCell,
+ pub children: Mutex, Option)>>,
executor: Arc,
}
impl Scope {
pub fn new(executor: Arc) -> Arc {
Arc::new(Self {
- children: AccessCell::new(Vec::new()),
+ children: Mutex::new(Vec::new()),
executor,
})
}
@@ -27,8 +26,7 @@ impl Scope {
ctx.refresh();
- self.children
- .access(|children| children.push((ctx, view_wrapper)));
+ self.children.lock().unwrap().push((ctx, view_wrapper));
}
pub fn view(self: &Arc, view: View) {
@@ -36,19 +34,6 @@ impl Scope {
ctx.refresh();
- self.children.access(|children| children.push((ctx, None)));
- }
-
- pub fn view_wrapper(self: &Arc, view: View, view_wrapper: Option) {
- let ctx = Context::new(view, self.executor.clone());
-
- ctx.refresh();
-
- self.children
- .access(|children| children.push((ctx, view_wrapper)));
- }
-
- pub fn access_children(self: &Arc, f: impl FnOnce(&mut ScopeChildren) + Send + 'static) {
- self.children.access(f);
+ self.children.lock().unwrap().push((ctx, None));
}
}