#repl #shell #interactive #interpreter #cli #command-arguments

easy-repl

An easy to use REPL, ideal when there is a need to crate an ad-hoc shell

3 unstable releases

0.2.1 Jul 13, 2022
0.2.0 Jul 13, 2022
0.1.0 May 17, 2021

#884 in Command-line interface

Download history 731/week @ 2023-12-17 32/week @ 2023-12-24 267/week @ 2023-12-31 696/week @ 2024-01-07 577/week @ 2024-01-14 672/week @ 2024-01-21 414/week @ 2024-01-28 887/week @ 2024-02-04 939/week @ 2024-02-11 378/week @ 2024-02-18 917/week @ 2024-02-25 1173/week @ 2024-03-03 1159/week @ 2024-03-10 1268/week @ 2024-03-17 1249/week @ 2024-03-24 1301/week @ 2024-03-31

5,015 downloads per month
Used in 2 crates (via routes)

MIT/Apache

39KB
686 lines

easy-repl crates.io docs.rs

An easy to use REPL, ideal when there is a need to crate an ad-hoc shell.

This is a Rust library that provides a fast and convenient way to generate a REPL 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.

See the crate documentation and the examples/ directory for more information.


lib.rs:

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

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:

> hello world
Hello world!

It comes with argument number checking...

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

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

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

> a 1 2
1 + 2 = 3

but if the input is ambigious, an error will be printed with command suggestions:

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

Dependencies

~8–20MB
~251K SLoC