mut_state/
mut_state.rs

1use anyhow::{self, Context};
2use mini_async_repl::{
3    command::{
4        lift_validation_err, validate, Command, CommandArgInfo, CommandArgType, ExecuteCommand,
5    },
6    CommandStatus, Repl,
7};
8use std::cell::RefCell;
9use std::future::Future;
10use std::pin::Pin;
11use std::rc::Rc;
12
13struct CountCommandHandler {}
14impl CountCommandHandler {
15    pub fn new() -> Self {
16        Self {}
17    }
18    async fn handle_command(&mut self, x: i32, y: i32) -> anyhow::Result<CommandStatus> {
19        for i in x..=y {
20            print!(" {}", i);
21        }
22        println!();
23        Ok(CommandStatus::Done)
24    }
25}
26impl ExecuteCommand for CountCommandHandler {
27    fn execute(
28        &mut self,
29        args: Vec<String>,
30        args_info: Vec<CommandArgInfo>,
31    ) -> Pin<Box<dyn Future<Output = anyhow::Result<CommandStatus>> + '_>> {
32        let valid = validate(args.clone(), args_info.clone());
33        if let Err(e) = valid {
34            return Box::pin(lift_validation_err(Err(e)));
35        }
36
37        let x = args[0].parse::<i32>();
38        let y = args[1].parse::<i32>();
39
40        match (x, y) {
41            (Ok(x), Ok(y)) => Box::pin(self.handle_command(x, y)),
42            _ => panic!("Unreachable, validator should have covered this"),
43        }
44    }
45}
46
47struct SayCommandHandler {}
48impl SayCommandHandler {
49    pub fn new() -> Self {
50        Self {}
51    }
52    async fn handle_command(&mut self, x: f32) -> anyhow::Result<CommandStatus> {
53        println!("x is equal to {}", x);
54        Ok(CommandStatus::Done)
55    }
56}
57impl ExecuteCommand for SayCommandHandler {
58    fn execute(
59        &mut self,
60        args: Vec<String>,
61        args_info: Vec<CommandArgInfo>,
62    ) -> Pin<Box<dyn Future<Output = anyhow::Result<CommandStatus>> + '_>> {
63        let valid = validate(args.clone(), args_info.clone());
64        if let Err(e) = valid {
65            return Box::pin(lift_validation_err(Err(e)));
66        }
67
68        let x = args[0].parse::<f32>();
69        match x {
70            Ok(x) => Box::pin(self.handle_command(x)),
71            _ => panic!("Unreachable, validator should have covered this"),
72        }
73    }
74}
75
76struct OutXCommandHandler {
77    outside_x: Rc<RefCell<String>>,
78}
79impl OutXCommandHandler {
80    pub fn new(outside_x: Rc<RefCell<String>>) -> Self {
81        Self { outside_x }
82    }
83    async fn handle_command(&mut self) -> anyhow::Result<CommandStatus> {
84        let mut x = self.outside_x.borrow_mut();
85        *x += "x";
86        println!("{}", x);
87        Ok(CommandStatus::Done)
88    }
89}
90impl ExecuteCommand for OutXCommandHandler {
91    fn execute(
92        &mut self,
93        args: Vec<String>,
94        args_info: Vec<CommandArgInfo>,
95    ) -> Pin<Box<dyn Future<Output = anyhow::Result<CommandStatus>> + '_>> {
96        let valid = validate(args.clone(), args_info.clone());
97        if let Err(e) = valid {
98            return Box::pin(lift_validation_err(Err(e)));
99        }
100        Box::pin(self.handle_command())
101    }
102}
103
104#[tokio::main]
105async fn main() -> anyhow::Result<()> {
106    let outside_x = Rc::new(RefCell::new(String::from("Out x")));
107
108    #[rustfmt::skip]
109    let mut repl = Repl::builder()
110        .description("Example REPL")
111        .prompt("=> ")
112        .text_width(60 as usize)
113        .add("count", Command::new(
114        	"Count from X to Y",
115        	vec![
116        		CommandArgInfo::new_with_name(CommandArgType::I32, "X"),
117        		CommandArgInfo::new_with_name(CommandArgType::I32, "Y"),
118        	],
119        	Box::new(CountCommandHandler::new()),
120        ))
121        .add("say", Command::new(
122        	"Say X",
123        	vec![CommandArgInfo::new_with_name(CommandArgType::F32, "X")],
124        	Box::new(SayCommandHandler::new()),
125        ))
126        .add("outx", Command::new(
127        	"Use mutably outside var x. This command has a really long description so we need to wrap it somehow, it is interesting how actually the wrapping will be performed.",
128        	vec![],
129        	Box::new(OutXCommandHandler::new(outside_x.clone())),
130        ))
131        .build().context("Failed to create repl")?;
132
133    repl.run().await.context("Critical REPL error")?;
134
135    Ok(())
136}