libpt_cli/repl/mod.rs
1//! Create easy and well defined REPLs
2//!
3//! A REPL is a [Read-Eval-Print-Loop](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop).
4//! Well known examples for REPLs are shells (like bash).
5//!
6//! This module offers a convenient way to create a well-defined REPL without a lot of complicated
7//! code and with a visually pleasing aesthetic. An example REPL implementation can be found in the
8//! examples.
9//!
10//! The basic idea is that the user defines the commands with an enum and uses [claps](clap)
11//! `#[derive(Subcommand)]`. A loop is then used to read from the stdin into a buffer, that buffer
12//! is put to [clap] for parsing, similar to how [clap] would parse commandline arguments.
13
14use std::fmt::Debug;
15
16pub mod error;
17use error::Error;
18mod default;
19pub use default::*;
20
21use clap::{Parser, Subcommand};
22
23/// Common Trait for repl objects
24///
25/// Unless you want to implement custom features (not just commands), just use [`DefaultRepl`].
26pub trait Repl<C>: Parser + Debug
27where
28 C: Debug + Subcommand + strum::IntoEnumIterator,
29{
30 /// create a new repl
31 fn new() -> Self;
32 /// get the command that was parsed from user input
33 ///
34 /// Will only be [None] if the repl has not had [step](Repl::step) executed yet.
35 fn command(&self) -> &Option<C>;
36 /// advance the repl to the next iteration of the main loop
37 ///
38 /// This should be used at the start of your loop.
39 ///
40 /// Note that the help menu is an Error: [`clap::error::ErrorKind::DisplayHelp`]
41 ///
42 /// # Errors
43 ///
44 /// * [`Error::Input`] – [dialoguer] User Input had some kind of I/O Error
45 /// * [`Error::Parsing`] – [clap] could not parse the user input, or user requested help
46 /// * [`Error::Other`] – Any other error with [anyhow], [`DefaultRepl`] does not use this but custom implementations might
47 fn step(&mut self) -> Result<(), Error>;
48}