easy_repl/
lib.rs

1#![deny(missing_docs)]
2
3//! An easy to use REPL, ideal when there is a need to crate an ad-hoc shell.
4//!
5//! This library provides a fast and convenient way to generate a
6//! [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)
7//! for your application. It comes with easy to use [`command!`] macro that
8//! will automatically validate and parse command arguments, doing all the type
9//! checking for you. The REPL comes with handy help messages, input validation,
10//! hints and TAB-completion. Many REPL features can be configured.
11//!
12//! # Example
13//!
14//! This is a basic example corresponding to `examples/minimal.rs`. For more examples
15//! see the `examples/` directory, which among others shows how to handle errors, access
16//! variables outside of handler closures and how to create REPL inside REPL, inside REPL, inside...
17//!
18//! ```rust
19//! use easy_repl::{Repl, CommandStatus, command};
20//!
21//! let mut repl = Repl::builder()
22//!     .add("hello", command! {
23//!         "Say hello",
24//!         (name: String) => |name| {
25//!             println!("Hello {}!", name);
26//!             Ok(CommandStatus::Done)
27//!         }
28//!     })
29//!     .add("add", command! {
30//!         "Add X to Y",
31//!         (X:i32, Y:i32) => |x, y| {
32//!             println!("{} + {} = {}", x, y, x + y);
33//!             Ok(CommandStatus::Done)
34//!         }
35//!     })
36//!     .build().expect("Failed to create repl");
37//!
38//! repl.run().expect("Critical REPL error");
39//! ```
40//!
41//! The generated REPL can be used as:
42//! ```text
43//! > hello world
44//! Hello world!
45//! ```
46//!
47//! It comes with argument number checking...
48//! ```text
49//! > add 1
50//! Error: wrong number of arguments: got 1, expected 2
51//! Usage: add X:i32 Y:i32
52//! > hello easy repl
53//! Error: wrong number of arguments: got 2, expected 1
54//! Usage: hello name:String
55//! > hello "easy repl"
56//! Hello easy repl!
57//! ```
58//!
59//! ...and type checking!
60//! ```text
61//! > add 1 world
62//! Error: failed to parse argument value 'world': invalid digit found in string
63//! Usage: add X:i32 Y:i32
64//! ```
65//!
66//! It includes automatic `help` and `quit` commands. The help message is auto-generated:
67//! ```text
68//! > help
69//! Available commands:
70//!   add X:i32 Y:i32    Add X to Y
71//!   hello name:String  Say hello
72//!
73//! Other commands:
74//!   help  Show this help message
75//!   quit  Quit repl
76//! ```
77//!
78//! By default user does not have to use full command names, if the command name can be
79//! resloved unambigiously (i.e. prefix matches only a single command), e.g.
80//! ```text
81//! > a 1 2
82//! 1 + 2 = 3
83//! ```
84//! but if the input is ambigious, an error will be printed with command suggestions:
85//! ```text
86//! > h world
87//! Command not found: h
88//! Candidates:
89//!   hello
90//!   help
91//! Use 'help' to see available commands.
92//! ```
93//!
94//! The REPL also by default automatically implements command hints and TAB-completion (see [`rustyline::hint`], [`rustyline::completion`]).
95
96pub mod command;
97mod completion;
98pub mod repl;
99
100pub use anyhow;
101
102pub use command::{Command, CommandStatus, Critical, CriticalError};
103pub use repl::Repl;