ReplBuilder

Struct ReplBuilder 

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

Builder pattern implementation for Repl.

All setter methods take owned self so the calls can be chained, for example:

let repl = Repl::builder()
    .description("My REPL")
    .prompt("repl> ")
    .build()
    .expect("Failed to build REPL");

Implementations§

Source§

impl ReplBuilder

Source

pub fn description<T: Into<String>>(self, v: T) -> Self

Repl description shown in Repl::help. Defaults to an empty string.

Examples found in repository?
examples/mut_state.rs (line 110)
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}
Source

pub fn prompt<T: Into<String>>(self, v: T) -> Self

Prompt string, defaults to "> ".

Examples found in repository?
examples/mut_state.rs (line 111)
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}
Source

pub fn text_width<T: Into<usize>>(self, v: T) -> Self

Width of the text used when wrapping the help message. Defaults to 80.

Examples found in repository?
examples/mut_state.rs (line 112)
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}
Source

pub fn editor_config<T: Into<Config>>(self, v: T) -> Self

Configuration for rustyline. Some sane defaults are used.

Source

pub fn out<T: Into<Box<dyn Write>>>(self, v: T) -> Self

Where to print REPL output. By default std::io::Stderr is used.

Note that rustyline will always use std::io::Stderr or std::io::Stdout. These must be configured in ReplBuilder::editor_config, and currently there seems to be no way to use other output stream for rustyline (which probably also makes little sense).

Source

pub fn with_hints<T: Into<bool>>(self, v: T) -> Self

Print command hints. Defaults to true.

Hints will show the end of a command if there is only one avaliable. For example, assuming commands "move" and "make", in the following position (| indicates the cursor):

> mo|

a hint will be shown as

> mo|ve

but when there is only

> m|

then no hints will be shown.

Source

pub fn with_completion<T: Into<bool>>(self, v: T) -> Self

Use completion. Defaults to true.

Source

pub fn with_filename_completion<T: Into<bool>>(self, v: T) -> Self

Add filename completion, besides command completion. Defaults to false.

Source

pub fn predict_commands<T: Into<bool>>(self, v: T) -> Self

Execute commands when entering incomplete names. Defaults to true.

With this option commands can be executed by entering only part of command name. If there is only a single command mathing given prefix, then it will be executed. For example, with commands "make" and “move”, entering just mo will resolve to move and the command will be executed, but entering m will result in an error.

Source

pub fn add(self, name: &str, cmd: Command) -> Self

Add a command with given name. Use along with the [command!] macro.

Examples found in repository?
examples/from_str.rs (lines 80-84)
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 88)
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 (lines 96-100)
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 (lines 113-120)
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 (lines 137-141)
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 build(self) -> Result<Repl, BuilderError>

Finalize the configuration and return the REPL or error.

Examples found in repository?
examples/from_str.rs (line 90)
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 90)
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 117)
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 131)
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 157)
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}

Trait Implementations§

Source§

impl Default for ReplBuilder

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

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.