input/
input.rs

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}