Repl

Struct Repl 

Source
pub struct Repl { /* private fields */ }
Expand description

Read-eval-print loop.

REPL is ment do be constructed using the builder pattern via Repl::builder(). Commands are added during building and currently cannot be added/removed/modified after Repl has been built. This is because the names are used to generate Trie with all the names for fast name lookup and completion.

Repl can be used in two ways: one can use the Repl::run method directly to just start the evaluation loop, or Repl::next can be used to get back control between loop steps.

Implementations§

Source§

impl Repl

Source

pub fn builder() -> ReplBuilder

Start ReplBuilder with default values.

Examples found in repository?
examples/from_str.rs (line 79)
77async fn main() -> anyhow::Result<()> {
78    #[rustfmt::skip]
79    let mut repl = Repl::builder()
80        .add("ls", Command::new(
81            "List files in a directory",
82            vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "dir")],
83            Box::new(LsCommandHandler::new()),
84        ))
85        .add("ipaddr", Command::new(
86            "Just parse and print the given IP address".into(),
87            vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "ip")],
88            Box::new(IpAddrCommandHandler::new()),
89        ))
90        .build()
91        .context("Failed to create repl")?;
92
93    repl.run().await.context("Critical REPL error")
94}
More examples
Hide additional examples
examples/minimal.rs (line 87)
67async fn main() -> anyhow::Result<()> {
68    let hello_cmd = Command::new(
69        "Say hello",
70        vec![CommandArgInfo::new_with_name(
71            CommandArgType::String,
72            "name",
73        )],
74        Box::new(SayHelloCommandHandler::new()),
75    );
76
77    let add_cmd = Command::new(
78        "Add X to Y",
79        vec![
80            CommandArgInfo::new_with_name(CommandArgType::I32, "X"),
81            CommandArgInfo::new_with_name(CommandArgType::I32, "Y"),
82        ],
83        Box::new(AddCommandHandler::new()),
84    );
85
86    #[rustfmt::skip]
87    let mut repl = Repl::builder()
88        .add("hello", hello_cmd)
89        .add("add", add_cmd)
90        .build()
91        .context("Failed to create repl")?;
92
93    repl.run().await.context("Critical REPL error")?;
94
95    Ok(())
96}
examples/overload.rs (line 95)
93async fn main() -> anyhow::Result<()> {
94    #[rustfmt::skip]
95    let mut repl = Repl::builder()
96        .add("describe", Command::new(
97            "Variant 1",
98            vec![],
99            Box::new(DescribeCommandHandler::new()),
100        ))
101        .add("describe", Command::new(
102        	"Variant 2",
103        	vec![
104        		CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
105        		CommandArgInfo::new_with_name(CommandArgType::I32, "b"),
106        	],
107        	Box::new(DescribeCommandHandler::new()),
108        ))           
109        .add("describe", Command::new(
110            "Variant 3",
111            vec![
112        		CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
113        		CommandArgInfo::new_with_name(CommandArgType::String, "b"),
114        	],
115        	Box::new(DescribeCommandHandler::new()),
116        ))
117        .build()
118        .context("Failed to create repl")?;
119
120    repl.run().await.context("Critical REPL error")?;
121
122    Ok(())
123}
examples/mut_state.rs (line 109)
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}
examples/errors.rs (line 136)
134async fn main() -> anyhow::Result<()> {
135    #[rustfmt::skip]
136    let mut repl = Repl::builder()
137        .add("ok", Command::new(
138            "Run a command that just succeeds",
139            vec![],
140            Box::new(OkCommandHandler::new()),
141        ))
142        .add("error", Command::new(
143            "Command with recoverable error handled by the REPL",
144            vec![CommandArgInfo::new_with_name(CommandArgType::String, "text")],
145            Box::new(RecoverableErrorHandler::new()),
146        ))
147        .add("critical", Command::new(
148            "Command returns a critical error that must be handled outside of REPL",
149            vec![CommandArgInfo::new_with_name(CommandArgType::String, "text")],
150            Box::new(CriticalErrorHandler::new()),
151        ))
152        .add("roulette", Command::new(
153            "Feeling lucky?",
154            vec![],
155            Box::new(RouletteErrorHandler::new(Instant::now())),
156        ))
157        .build()
158        .context("Failed to create repl")?;
159
160    let repl_res = repl.run().await;
161    match repl_res {
162        Ok(_) => Ok(()),
163        Err(_) => {
164            println!("Repl halted. Quitting.");
165            Ok(())
166        }
167    }
168}
Source

pub fn help(&self) -> String

Returns formatted help message.

Source

pub async fn next(&mut self) -> Result<LoopStatus>

Run a single REPL iteration and return whether this is the last one or not.

Source

pub async fn run(&mut self) -> Result<()>

Run the evaluation loop until LoopStatus::Break is received.

Examples found in repository?
examples/from_str.rs (line 93)
77async fn main() -> anyhow::Result<()> {
78    #[rustfmt::skip]
79    let mut repl = Repl::builder()
80        .add("ls", Command::new(
81            "List files in a directory",
82            vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "dir")],
83            Box::new(LsCommandHandler::new()),
84        ))
85        .add("ipaddr", Command::new(
86            "Just parse and print the given IP address".into(),
87            vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "ip")],
88            Box::new(IpAddrCommandHandler::new()),
89        ))
90        .build()
91        .context("Failed to create repl")?;
92
93    repl.run().await.context("Critical REPL error")
94}
More examples
Hide additional examples
examples/minimal.rs (line 93)
67async fn main() -> anyhow::Result<()> {
68    let hello_cmd = Command::new(
69        "Say hello",
70        vec![CommandArgInfo::new_with_name(
71            CommandArgType::String,
72            "name",
73        )],
74        Box::new(SayHelloCommandHandler::new()),
75    );
76
77    let add_cmd = Command::new(
78        "Add X to Y",
79        vec![
80            CommandArgInfo::new_with_name(CommandArgType::I32, "X"),
81            CommandArgInfo::new_with_name(CommandArgType::I32, "Y"),
82        ],
83        Box::new(AddCommandHandler::new()),
84    );
85
86    #[rustfmt::skip]
87    let mut repl = Repl::builder()
88        .add("hello", hello_cmd)
89        .add("add", add_cmd)
90        .build()
91        .context("Failed to create repl")?;
92
93    repl.run().await.context("Critical REPL error")?;
94
95    Ok(())
96}
examples/overload.rs (line 120)
93async fn main() -> anyhow::Result<()> {
94    #[rustfmt::skip]
95    let mut repl = Repl::builder()
96        .add("describe", Command::new(
97            "Variant 1",
98            vec![],
99            Box::new(DescribeCommandHandler::new()),
100        ))
101        .add("describe", Command::new(
102        	"Variant 2",
103        	vec![
104        		CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
105        		CommandArgInfo::new_with_name(CommandArgType::I32, "b"),
106        	],
107        	Box::new(DescribeCommandHandler::new()),
108        ))           
109        .add("describe", Command::new(
110            "Variant 3",
111            vec![
112        		CommandArgInfo::new_with_name(CommandArgType::I32, "a"),
113        		CommandArgInfo::new_with_name(CommandArgType::String, "b"),
114        	],
115        	Box::new(DescribeCommandHandler::new()),
116        ))
117        .build()
118        .context("Failed to create repl")?;
119
120    repl.run().await.context("Critical REPL error")?;
121
122    Ok(())
123}
examples/mut_state.rs (line 133)
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}
examples/errors.rs (line 160)
134async fn main() -> anyhow::Result<()> {
135    #[rustfmt::skip]
136    let mut repl = Repl::builder()
137        .add("ok", Command::new(
138            "Run a command that just succeeds",
139            vec![],
140            Box::new(OkCommandHandler::new()),
141        ))
142        .add("error", Command::new(
143            "Command with recoverable error handled by the REPL",
144            vec![CommandArgInfo::new_with_name(CommandArgType::String, "text")],
145            Box::new(RecoverableErrorHandler::new()),
146        ))
147        .add("critical", Command::new(
148            "Command returns a critical error that must be handled outside of REPL",
149            vec![CommandArgInfo::new_with_name(CommandArgType::String, "text")],
150            Box::new(CriticalErrorHandler::new()),
151        ))
152        .add("roulette", Command::new(
153            "Feeling lucky?",
154            vec![],
155            Box::new(RouletteErrorHandler::new(Instant::now())),
156        ))
157        .build()
158        .context("Failed to create repl")?;
159
160    let repl_res = repl.run().await;
161    match repl_res {
162        Ok(_) => Ok(()),
163        Err(_) => {
164            println!("Repl halted. Quitting.");
165            Ok(())
166        }
167    }
168}

Auto Trait Implementations§

§

impl Freeze for Repl

§

impl !RefUnwindSafe for Repl

§

impl !Send for Repl

§

impl !Sync for Repl

§

impl Unpin for Repl

§

impl !UnwindSafe for Repl

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.