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
#![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 command::{Command, CommandStatus, Critical, CriticalError};
pub use repl::Repl;