shelp/
lib.rs

1//! `shelp` is a library to create a functional and good looking REPL without having to worry about
2//! the generic setup and interacting and the terminal. It provides a configurable interface,
3//! allowing you to only need to deal with the language specific parts of the REPL.
4//!
5//! There are special 2 commands handled by the repl:
6//! - `clear` - clears the screen
7//! - `exit`  - exits
8//! These can be changed with the [`repl.set_clear_keyword()`](Repl::set_clear_keyword) and
9//! [`repl.set_exit_keyword()`](Repl::set_exit_keyword) respectively. Any other special commands can
10//! be handled within the execution loop.
11//!
12//! ## How to use
13//!
14//! Take some program that just prints the input back:
15//! ```
16//! use shelp::{Repl, Color};
17//! let repl = Repl::newd("> ", ". ", None);
18//! let mut repl = repl.iter(Color::Green);
19//!
20//! // Now 'claer' clears the screen instead of 'clear'.
21//! repl.set_clear_keyword("claer");
22//!
23//! // for command in repl {
24//! //     // Other special commands can be handled here
25//! //     if command == "my_special_command" {
26//! //         println!("Special command triggered!");
27//! //         continue;
28//! //     }
29//! //
30//! //     <Do something>
31//! // }
32//! // NOTE the above is commented out for doc test reasons
33//! ```
34//! Here no [`LangInterface`] is specified, so the default is used.
35//! A [`LangInterface`] can be specified by implementing the trait and passing it as the generic
36//! type argument.
37//!
38//! ```
39//! use std::io::{self, prelude::*};
40//! use shelp::{Repl, Color, LangInterface, Result};
41//! // You can use any library, but currently only crossterm is used in the library for terminal.
42//! use crossterm::style::Colorize;
43//!
44//! struct MyLangInterface;
45//! // We want to override the linting so numbers are coloured, but we don't have a specific way of
46//! // getting the indentation, so we do not override that.
47//! impl LangInterface for MyLangInterface {
48//!     fn print_line(_: &mut io::Stdout, lines: &[String], index: usize) -> Result<()> {
49//!         // NOTE this is simple linting and has no multi-line context. For more information on
50//!         // the reason all lines are given, see LangInterface::print_line
51//!         for i in lines[index].chars() {
52//!             if i.is_numeric() {
53//!                 print!("{}", i.magenta());
54//!             } else {
55//!                 print!("{}", i);
56//!             }
57//!         }
58//!         Ok(())
59//!     }
60//! }
61//!
62//! // Use a particular capacity
63//! let mut repl = Repl::<MyLangInterface>::with_capacity("> ", ". ", 128, None);
64//!
65//! // loop {
66//! //     // You can have dynamic colours if you don't use the iterator. It also allows you to use the
67//! //     // errors instead of them being ignored.
68//! //     // NOTE here it is unwrapped, but it should be dealt with in a better way.
69//! //     let command = repl.next(Color::Blue).unwrap();
70//! //
71//! //     <Do something>
72//! // }
73//! // NOTE the above is commented out for doc test reasons
74//! ```
75
76#[macro_use]
77mod macros;
78pub(crate) mod lang;
79mod repl;
80
81pub use crossterm::{style::Color, Result};
82pub use lang::LangInterface;
83pub use repl::iter::ReplIter;
84pub use repl::Repl;