1use anathema::component::*;
2use anathema::prelude::*;
3use anathema_extras::{Input, InputChange, Text};
4
5#[derive(Debug, Default, State)]
6struct IndexState {
7 items: Value<List<String>>,
8 inserts: Value<usize>,
9 deletes: Value<usize>,
10}
11
12#[derive(Debug, Default)]
13struct Index;
14
15impl Component for Index {
16 type Message = ();
17 type State = IndexState;
18
19 #[allow(unused_variables, unused_mut)]
20 fn on_event(
21 &mut self,
22 event: &mut UserEvent<'_>,
23 state: &mut Self::State,
24 _: Children<'_, '_>,
25 _: Context<'_, '_, Self::State>,
26 ) {
27 match event.name() {
28 "new_item" => state.items.push_back(event.data::<Text>().to_string()),
29 "changed" => match event.data::<InputChange>() {
30 InputChange::Insert(_, _) => *state.inserts.to_mut() += 1,
31 InputChange::Remove(_, _) => *state.deletes.to_mut() += 1,
32 },
33 _ => (),
34 }
35 }
36
37 fn accept_focus(&self) -> bool {
38 false
39 }
40}
41
42fn main() {
43 let doc = Document::new("@index");
44
45 let mut backend = TuiBackend::builder()
46 .enable_alt_screen()
47 .enable_raw_mode()
48 .hide_cursor()
49 .finish()
50 .unwrap();
51 backend.finalize();
52
53 let mut builder = Runtime::builder(doc, &backend);
54 builder
55 .default::<Input>("input", Input::template())
56 .unwrap();
57 builder
58 .default::<Index>("index", template_str().to_template())
59 .unwrap();
60 let res = builder.finish(&mut backend, |runtime, backend| runtime.run(backend));
61
62 if let Err(e) = res {
63 eprintln!("{e}");
64 }
65}
66
67fn template_str() -> &'static str {
68 "
69 border
70 vstack
71 hstack
72 border [sides: 'right']
73 text 'inserts '
74 span [foreground: 'yellow'] state.inserts ' '
75 text ' deletes '
76 span [foreground: 'red'] state.deletes
77 border
78 @input (on_enter->new_item, on_change->changed) [clear_on_enter: true]
79 text [foreground: 'dark_grey'] 'placeholder'
80 border
81 vstack
82 for item in state.items
83 text item
84 "
85}