Struct Repl

Source
pub struct Repl<'a> { /* 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<'a> Repl<'a>

Source

pub fn builder() -> ReplBuilder<'a>

Start ReplBuilder with default values.

Examples found in repository?
examples/matryoshka.rs (line 18)
4fn matryoshka(name: String) -> anyhow::Result<Repl<'static>> {
5    let prompt = format!("{}> ", name);
6
7    let cloned_prompt = prompt.clone();  // need to move it into closure
8    let new = command! {
9        "Enter new repl",
10        (name:String) => |name: String| {
11            let name = cloned_prompt.clone() + &name;
12            let mut repl = matryoshka(name)?;
13            repl.run()?;
14            Ok(CommandStatus::Done)
15        }
16    };
17
18    let repl = Repl::builder()
19        .prompt(prompt)
20        .add("new", new)
21        .build()?;
22
23    Ok(repl)
24}
More examples
Hide additional examples
examples/minimal.rs (line 5)
4fn main() -> anyhow::Result<()> {
5    let mut repl = Repl::builder()
6        .add("hello", command! {
7            "Say hello",
8            (name: String) => |name| {
9                println!("Hello {}!", name);
10                Ok(CommandStatus::Done)
11            }
12        })
13        .add("add", command! {
14            "Add X to Y",
15            (X:i32, Y:i32) => |x, y| {
16                println!("{} + {} = {}", x, y, x + y);
17                Ok(CommandStatus::Done)
18            }
19        })
20        .build().context("Failed to create repl")?;
21
22    repl.run().context("Critical REPL error")?;
23
24    Ok(())
25}
examples/from_str.rs (line 8)
7fn main() -> anyhow::Result<()> {
8    let mut repl = Repl::builder()
9        .add("ls", command! {
10            "List files in a directory",
11            (dir: PathBuf) => |dir: PathBuf| {
12                for entry in dir.read_dir()? {
13                    println!("{}", entry?.path().to_string_lossy());
14                }
15                Ok(CommandStatus::Done)
16            }
17        })
18        .add("ipaddr", command! {
19            "Just parse and print the given IP address",
20            (ip: IpAddr) => |ip: IpAddr| {
21                println!("{}", ip);
22                Ok(CommandStatus::Done)
23            }
24        })
25        .build().context("Failed to create repl")?;
26
27    repl.run().context("Critical REPL error")
28}
examples/overload.rs (line 5)
4fn main() -> anyhow::Result<()> {
5    let mut repl = Repl::builder()
6        .add("describe", command! {
7            "Variant 1",
8            () => || {
9                println!("No arguments");
10                Ok(CommandStatus::Done)
11            }
12        })
13        .add("describe", command! {
14            "Variant 2",
15            (a: i32, b: i32) => |a, b| {
16                println!("Got two integers: {} {}", a, b);
17                Ok(CommandStatus::Done)
18            }
19        })
20        .add("describe", command! {
21            "Variant 3",
22            (a: i32, b: String) => |a, b| {
23                println!("An integer `{}` and a string `{}`", a, b);
24                Ok(CommandStatus::Done)
25            }
26        })
27        .build().context("Failed to create repl")?;
28
29    repl.run().context("Critical REPL error")?;
30
31    Ok(())
32}
examples/shared_mut_state.rs (line 14)
5fn main() -> anyhow::Result<()> {
6    // To use a value in multiple commands we need shared ownership
7    // combined with some kind of references.
8    // This could be Rc<RefCell<_>>, but in this example it's possible
9    // to avoid smart pointers and just use two references &RefCell<_>.
10    let counter = RefCell::new(0);
11    let ref1 = &counter;
12    let ref2 = &counter;
13
14    let mut repl = Repl::builder()
15        .add("inc", command! {
16            "Increment counter",
17            () => || {
18                *ref1.borrow_mut() += 1;
19                println!("counter = {}", ref1.borrow());
20                Ok(CommandStatus::Done)
21            },
22        })
23        .add("dec", command! {
24            "Decrement counter",
25            () => || {
26                *ref2.borrow_mut() -= 1;
27                println!("counter = {}", ref2.borrow());
28                Ok(CommandStatus::Done)
29            },
30        })
31        .build().context("Failed to create repl")?;
32
33    repl.run().context("Critical REPL error")?;
34
35    Ok(())
36}
examples/mut_state.rs (line 8)
4fn main() -> anyhow::Result<()> {
5    let mut outside_x = String::from("Out x");
6    let mut outside_y = String::from("Out y");
7
8    let mut repl = Repl::builder()
9        .description("Example REPL")
10        .prompt("=> ")
11        .text_width(60 as usize)
12        .add("count", command! {
13            "Count from X to Y",
14            (X:i32, Y:i32) => |x, y| {
15                for i in x..=y {
16                    print!(" {}", i);
17                }
18                println!();
19                Ok(CommandStatus::Done)
20            }
21        })
22        .add("say", command! {
23            "Say X",
24            (:f32) => |x| {
25                println!("x is equal to {}", x);
26                Ok(CommandStatus::Done)
27            },
28        })
29        .add("outx", command! {
30            "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.",
31            () => || {
32                outside_x += "x";
33                println!("{}", outside_x);
34                Ok(CommandStatus::Done)
35            },
36        })
37        // this shows how to create Command manually with the help of the validator! macro
38        // one could also implement arguments validation manually
39        .add("outy", easy_repl::Command {
40            description: "Use mutably outside var y".into(),
41            args_info: vec!["appended".into()],
42            handler: Box::new(|args| {
43                let validator = validator!(i32);
44                validator(args)?;
45                outside_y += args[0];
46                println!("{}", outside_y);
47                Ok(CommandStatus::Done)
48            }),
49        })
50        .build().context("Failed to create repl")?;
51
52    repl.run().context("Critical REPL error")?;
53
54    Ok(())
55}
Source

pub fn help(&self) -> String

Returns formatted help message.

Source

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

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

Source

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

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

Examples found in repository?
examples/matryoshka.rs (line 13)
4fn matryoshka(name: String) -> anyhow::Result<Repl<'static>> {
5    let prompt = format!("{}> ", name);
6
7    let cloned_prompt = prompt.clone();  // need to move it into closure
8    let new = command! {
9        "Enter new repl",
10        (name:String) => |name: String| {
11            let name = cloned_prompt.clone() + &name;
12            let mut repl = matryoshka(name)?;
13            repl.run()?;
14            Ok(CommandStatus::Done)
15        }
16    };
17
18    let repl = Repl::builder()
19        .prompt(prompt)
20        .add("new", new)
21        .build()?;
22
23    Ok(repl)
24}
25
26fn main() -> anyhow::Result<()> {
27    let mut repl = matryoshka("".into())?;
28    repl.run().context("Critical REPL error")?;
29    Ok(())
30}
More examples
Hide additional examples
examples/minimal.rs (line 22)
4fn main() -> anyhow::Result<()> {
5    let mut repl = Repl::builder()
6        .add("hello", command! {
7            "Say hello",
8            (name: String) => |name| {
9                println!("Hello {}!", name);
10                Ok(CommandStatus::Done)
11            }
12        })
13        .add("add", command! {
14            "Add X to Y",
15            (X:i32, Y:i32) => |x, y| {
16                println!("{} + {} = {}", x, y, x + y);
17                Ok(CommandStatus::Done)
18            }
19        })
20        .build().context("Failed to create repl")?;
21
22    repl.run().context("Critical REPL error")?;
23
24    Ok(())
25}
examples/from_str.rs (line 27)
7fn main() -> anyhow::Result<()> {
8    let mut repl = Repl::builder()
9        .add("ls", command! {
10            "List files in a directory",
11            (dir: PathBuf) => |dir: PathBuf| {
12                for entry in dir.read_dir()? {
13                    println!("{}", entry?.path().to_string_lossy());
14                }
15                Ok(CommandStatus::Done)
16            }
17        })
18        .add("ipaddr", command! {
19            "Just parse and print the given IP address",
20            (ip: IpAddr) => |ip: IpAddr| {
21                println!("{}", ip);
22                Ok(CommandStatus::Done)
23            }
24        })
25        .build().context("Failed to create repl")?;
26
27    repl.run().context("Critical REPL error")
28}
examples/overload.rs (line 29)
4fn main() -> anyhow::Result<()> {
5    let mut repl = Repl::builder()
6        .add("describe", command! {
7            "Variant 1",
8            () => || {
9                println!("No arguments");
10                Ok(CommandStatus::Done)
11            }
12        })
13        .add("describe", command! {
14            "Variant 2",
15            (a: i32, b: i32) => |a, b| {
16                println!("Got two integers: {} {}", a, b);
17                Ok(CommandStatus::Done)
18            }
19        })
20        .add("describe", command! {
21            "Variant 3",
22            (a: i32, b: String) => |a, b| {
23                println!("An integer `{}` and a string `{}`", a, b);
24                Ok(CommandStatus::Done)
25            }
26        })
27        .build().context("Failed to create repl")?;
28
29    repl.run().context("Critical REPL error")?;
30
31    Ok(())
32}
examples/shared_mut_state.rs (line 33)
5fn main() -> anyhow::Result<()> {
6    // To use a value in multiple commands we need shared ownership
7    // combined with some kind of references.
8    // This could be Rc<RefCell<_>>, but in this example it's possible
9    // to avoid smart pointers and just use two references &RefCell<_>.
10    let counter = RefCell::new(0);
11    let ref1 = &counter;
12    let ref2 = &counter;
13
14    let mut repl = Repl::builder()
15        .add("inc", command! {
16            "Increment counter",
17            () => || {
18                *ref1.borrow_mut() += 1;
19                println!("counter = {}", ref1.borrow());
20                Ok(CommandStatus::Done)
21            },
22        })
23        .add("dec", command! {
24            "Decrement counter",
25            () => || {
26                *ref2.borrow_mut() -= 1;
27                println!("counter = {}", ref2.borrow());
28                Ok(CommandStatus::Done)
29            },
30        })
31        .build().context("Failed to create repl")?;
32
33    repl.run().context("Critical REPL error")?;
34
35    Ok(())
36}
examples/mut_state.rs (line 52)
4fn main() -> anyhow::Result<()> {
5    let mut outside_x = String::from("Out x");
6    let mut outside_y = String::from("Out y");
7
8    let mut repl = Repl::builder()
9        .description("Example REPL")
10        .prompt("=> ")
11        .text_width(60 as usize)
12        .add("count", command! {
13            "Count from X to Y",
14            (X:i32, Y:i32) => |x, y| {
15                for i in x..=y {
16                    print!(" {}", i);
17                }
18                println!();
19                Ok(CommandStatus::Done)
20            }
21        })
22        .add("say", command! {
23            "Say X",
24            (:f32) => |x| {
25                println!("x is equal to {}", x);
26                Ok(CommandStatus::Done)
27            },
28        })
29        .add("outx", command! {
30            "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.",
31            () => || {
32                outside_x += "x";
33                println!("{}", outside_x);
34                Ok(CommandStatus::Done)
35            },
36        })
37        // this shows how to create Command manually with the help of the validator! macro
38        // one could also implement arguments validation manually
39        .add("outy", easy_repl::Command {
40            description: "Use mutably outside var y".into(),
41            args_info: vec!["appended".into()],
42            handler: Box::new(|args| {
43                let validator = validator!(i32);
44                validator(args)?;
45                outside_y += args[0];
46                println!("{}", outside_y);
47                Ok(CommandStatus::Done)
48            }),
49        })
50        .build().context("Failed to create repl")?;
51
52    repl.run().context("Critical REPL error")?;
53
54    Ok(())
55}

Auto Trait Implementations§

§

impl<'a> Freeze for Repl<'a>

§

impl<'a> !RefUnwindSafe for Repl<'a>

§

impl<'a> !Send for Repl<'a>

§

impl<'a> !Sync for Repl<'a>

§

impl<'a> Unpin for Repl<'a>

§

impl<'a> !UnwindSafe for Repl<'a>

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> 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.