Promptuity = Prompt + Ingenuity
Promptuity is a library that provides interactive prompts. It is highly extensible, allowing you to build your original prompts from scratch. It brings ingenuity to various projects.
## Table Of Contents - [Concept](#concept) - [Quick Start](#quick-start) - [Examples](#examples) - [Documentation](#documentation) - [Prompts](#prompts) - [Input](#input) - [Password](#password) - [Number](#number) - [Select](#select) - [MultiSelect](#multiselect) - [Confirm](#confirm) - [Autocomplete](#autocomplete) - [Themes](#themes) - [MinimalTheme](#minimaltheme) - [FancyTheme](#fancytheme) - [Customize](#customize) - [Build your own Prompt](#build-your-own-prompt) - [Build your own Theme](#build-your-own-theme) - [Error Handling](#error-handling) - [Testing](#testing) - [Alternatives](#alternatives) - [Inspired](#inspired) - [Contributing](#contributing) - [CHANGELOG](#changelog) - [License](#license) ## Concept - :zap: **Not easy, But simple** - Avoids APIs with implicit behavior, aiming to provide as transparent APIs as possible. - The amount of code required to start a prompt may be more compared to other libraries. - :hammer: **Extensible** - You can customize built-in prompts or build your prompts from scratch. - The built-in prompts are minimal, assuming that prompt requirements vary by project. - :nail_care: **Beautiful** - Offers two types of built-in Themes. - Themes can also be fully customized to fit your ideal. ## Quick Start ![Quick Start DEMO](./assets/quick_start.gif) The basic usage is as follows. ```rust use promptuity::prompts::{Confirm, Input, Select, SelectOption}; use promptuity::themes::FancyTheme; use promptuity::{Error, Promptuity, Term}; fn main() -> Result<(), Error> { let mut term = Term::default(); let mut theme = FancyTheme::default(); let mut p = Promptuity::new(&mut term, &mut theme); p.term().clear()?; p.with_intro("Survey").begin()?; let name = p.prompt(Input::new("Please enter your username").with_placeholder("username"))?; let _ = p.prompt(Confirm::new("Are you a full-time software developer?").with_default(true))?; let _ = p.prompt( Select::new( "Select your primary programming language", vec![ SelectOption::new("Rust", "rust"), SelectOption::new("Go", "go"), SelectOption::new("C++", "cpp"), SelectOption::new("C", "c"), SelectOption::new("TypeScript", "typescript"), SelectOption::new("JavaScript", "javascript"), SelectOption::new("Deno", "deno"), SelectOption::new("Python", "python"), SelectOption::new("Java", "java"), SelectOption::new("Dart", "dart"), SelectOption::new("Other", "other"), ], ) .with_hint("Submit with Space or Enter."), )?; p.with_outro(format!("Thank you for your response, {}!", name)) .finish()?; Ok(()) } ``` ## Examples If you want to see more examples, please refer to the [examples](./examples/) directory. ## Documentation Please refer to the [documentation](https://docs.rs/promptuity). ## Prompts [`promptuity::prompts`](https://docs.rs/promptuity/latest/promptuity/prompts/index.html) offers five built-in prompts. To implement your original prompt, please see the [Build your own Prompt](#build-your-own-prompt) section. ### Input ![Input Demo](./assets/prompt_input.gif) A prompt for general text input. ```rust let name = p.prompt( Input::new("What is your accout name?") .with_placeholder("username") .with_hint("Only alphanumeric characters are allowed.") .with_validator(|value: &String| { if value.chars().all(|c| c.is_alphanumeric()) { Ok(()) } else { Err("Invalid format".into()) } }), )?; ``` ### Password ![Password Demo](./assets/prompt_password.gif) A text input prompt where the input is not displayed. ```rust let secret = p.prompt( Password::new("Set a password for your account") .with_hint("Please enter more than 6 alphanumeric characters.") .with_validator(|value: &String| { if value.len() < 6 { Err("Password must be at least 6 characters long".into()) } else { Ok(()) } }), )?; ``` ### Number ![Number Demo](./assets/prompt_number.gif) A prompt for inputting only integer values. ```rust let age = p.prompt(Number::new("How old are you?").with_min(0).with_max(120))?; ``` ### Select ![Select Demo](./assets/prompt_select.gif) A prompt for selecting a single element from a list of options. ```rust let color = p.prompt( Select::new( "What is your favorite color?", vec![ SelectOption::new("Red", "#ff0000"), SelectOption::new("Green", "#00ff00").with_hint("recommended"), SelectOption::new("Blue", "#0000ff"), ], ) .as_mut(), )?; ``` ### MultiSelect ![MultiSelect Demo](./assets/prompt_multi_select.gif) A prompt for selecting multiple elements from a list of options. ```rust let color = p.prompt( MultiSelect::new( "What are your favorite colors?", vec![ MultiSelectOption::new("Red", "#ff0000"), MultiSelectOption::new("Green", "#00ff00").with_hint("recommended"), MultiSelectOption::new("Blue", "#0000ff"), ], ) .as_mut(), )?; ``` ### Confirm ![Confirm Demo](./assets/prompt_confirm.gif) A prompt for inputting a Yes/No choice. ```rust let like = p.prompt( Confirm::new("Do you like dogs?") .with_hint("This is just a sample prompt :)") .with_default(true), )?; ``` ### Autocomplete > [!NOTE] > Autocomplete is not provided as a built-in feature. This is because the optimal behavior for Fuzzy Match and key bindings varies by project. > While not provided as a built-in, a reference implementation is available in [examples/autocomplete.rs](./examples/autocomplete.rs). Please adapt this to suit your project's needs. ## Themes Promptuity offers two different built-in themes. To implement your original Theme, please see the [Build your own Theme](#build-your-own-theme) section. ### MinimalTheme MinimalTheme is similar to [Inquirer](https://github.com/SBoudrias/Inquirer.js). It provides a compact UI. ![MinimalTheme Screenshot](./assets/theme_minimal.png) ```rust use promptuity::themes::MinimalTheme; fn main() { let mut theme = MinimalTheme::default(); // ... } ``` ### FancyTheme FancyTheme is similar to [clack](https://github.com/natemoo-re/clack). It provides a rich UI. ![FancyTheme Screenshot](./assets/theme_fancy.png) ```rust use promptuity::themes::FancyTheme; fn main() { let mut theme = FancyTheme::default(); // ... } ``` ## Customize This section provides guidance on how to construct original prompts and Themes. ### Build your own Prompt Creating an original prompt can be achieved by implementing the [`Prompt`](https://docs.rs/promptuity/latest/promptuity/trait.Prompt.html) trait. By implementing three lifecycle methods, you can build prompts that are usable with [`Promptuity::prompt`](https://docs.rs/promptuity/latest/promptuity/struct.Promptuity.html#method.prompt). Promptuity prompts consist of the following elements: | Item | Description | | :-- | :-- | | **Message** | Displays the question content of the prompt. | | **Input** | A single-line item that accepts user key inputs. | | **Body** | A multi-line item that accepts user key inputs. | | **Hint** | Displays a message to assist with prompt input. | - Prompts that accept single-line inputs, like `Input` or `Password`, do not utilize **Body**. - Prompts that do not accept inputs, like `Select` or `MultiSelect`, do not utilize **Input**. Keep these points in mind when building your prompts. #### 0. Setting Up a Custom Prompt Let's use the implementation of a custom prompt similar to `Confirm` as an example. ```rust use promptuity::Prompt; struct CustomConfirm { message: String, hint: Option