repl/
repl.rs

1use console::style;
2use libpt_cli::printing;
3use libpt_cli::repl::{DefaultRepl, Repl};
4use libpt_log::{debug, Logger};
5
6use clap::Subcommand;
7use strum::EnumIter;
8
9// this is where you define what data/commands/arguments the REPL accepts
10#[derive(Subcommand, Debug, EnumIter, Clone)]
11enum ReplCommand {
12    /// wait for LEN seconds
13    Wait {
14        /// wait so long
15        len: u64,
16    },
17    /// echo the given texts
18    Echo {
19        /// the text you want to print
20        text: Vec<String>,
21        /// print with a fancy border and colors
22        #[arg(short, long)]
23        fancy: bool,
24    },
25    /// hello world
26    Hello,
27    /// leave the repl
28    Exit,
29}
30
31fn main() -> anyhow::Result<()> {
32    // You would normally make a proper cli interface with clap before entering the repl. This is
33    // omitted here for brevity
34    let _logger = Logger::builder().display_time(false).build();
35
36    // the compiler can infer that we want to use the ReplCommand enum.
37    let mut repl = DefaultRepl::<ReplCommand>::default();
38
39    debug!("entering the repl");
40    loop {
41        // repl.step() should be at the start of your loop
42        // It is here that the repl will get the user input, validate it, and so on
43        match repl.step() {
44            Ok(c) => c,
45            Err(e) => {
46                // if the user requested the help, print in blue, otherwise in red as it's just an
47                // error
48                if let libpt_cli::repl::error::Error::Parsing(e) = &e {
49                    if e.kind() == clap::error::ErrorKind::DisplayHelp {
50                        println!("{}", style(e).cyan());
51                        continue;
52                    }
53                }
54                println!("{}", style(e).red().bold());
55                continue;
56            }
57        };
58
59        // now we can match our defined commands
60        //
61        // only None if the repl has not stepped yet
62        match repl.command().to_owned().unwrap() {
63            ReplCommand::Exit => break,
64            ReplCommand::Wait { len } => {
65                debug!("len: {len}");
66                let spinner = indicatif::ProgressBar::new_spinner();
67                spinner.enable_steady_tick(std::time::Duration::from_millis(100));
68                std::thread::sleep(std::time::Duration::from_secs(len));
69                spinner.finish();
70            }
71            ReplCommand::Hello => println!("Hello!"),
72            ReplCommand::Echo { text, fancy } => {
73                if !fancy {
74                    println!("{}", text.join(" "))
75                } else {
76                    printing::blockprint(text.join(" "), console::Color::Cyan)
77                }
78            }
79        }
80    }
81    Ok(())
82}