1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#![deny(missing_docs)]

//! An easy to use REPL, ideal when there is a need to crate an ad-hoc shell.
//!
//! This library provides a fast and convenient way to generate a
//! [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)
//! for your application. It comes with easy to use [`command!`] macro that
//! will automatically validate and parse command arguments, doing all the type
//! checking for you. The REPL comes with handy help messages, input validation,
//! hints and TAB-completion. Many REPL features can be configured.
//!
//! # Example
//!
//! This is a basic example corresponding to `examples/minimal.rs`. For more examples
//! see the `examples/` directory, which among others shows how to handle errors, access
//! variables outside of handler closures and how to create REPL inside REPL, inside REPL, inside...
//!
//! ```rust
//! use easy_repl::{Repl, CommandStatus, command};
//!
//! let mut repl = Repl::builder()
//!     .add("hello", command! {
//!         "Say hello",
//!         (name: String) => |name| {
//!             println!("Hello {}!", name);
//!             Ok(CommandStatus::Done)
//!         }
//!     })
//!     .add("add", command! {
//!         "Add X to Y",
//!         (X:i32, Y:i32) => |x, y| {
//!             println!("{} + {} = {}", x, y, x + y);
//!             Ok(CommandStatus::Done)
//!         }
//!     })
//!     .build().expect("Failed to create repl");
//!
//! repl.run().expect("Critical REPL error");
//! ```
//!
//! The generated REPL can be used as:
//! ```text
//! > hello world
//! Hello world!
//! ```
//!
//! It comes with argument number checking...
//! ```text
//! > add 1
//! Error: wrong number of arguments: got 1, expected 2
//! Usage: add X:i32 Y:i32
//! > hello easy repl
//! Error: wrong number of arguments: got 2, expected 1
//! Usage: hello name:String
//! > hello "easy repl"
//! Hello easy repl!
//! ```
//!
//! ...and type checking!
//! ```text
//! > add 1 world
//! Error: failed to parse argument value 'world': invalid digit found in string
//! Usage: add X:i32 Y:i32
//! ```
//!
//! It includes automatic `help` and `quit` commands. The help message is auto-generated:
//! ```text
//! > help
//! Available commands:
//!   add X:i32 Y:i32    Add X to Y
//!   hello name:String  Say hello
//!
//! Other commands:
//!   help  Show this help message
//!   quit  Quit repl
//! ```
//!
//! By default user does not have to use full command names, if the command name can be
//! resloved unambigiously (i.e. prefix matches only a single command), e.g.
//! ```text
//! > a 1 2
//! 1 + 2 = 3
//! ```
//! but if the input is ambigious, an error will be printed with command suggestions:
//! ```text
//! > h world
//! Command not found: h
//! Candidates:
//!   hello
//!   help
//! Use 'help' to see available commands.
//! ```
//!
//! The REPL also by default automatically implements command hints and TAB-completion (see [`rustyline::hint`], [`rustyline::completion`]).

pub mod command;
mod completion;
pub mod repl;

pub use anyhow;

pub use command::{Command, CommandStatus, Critical, CriticalError};
pub use repl::Repl;