From a9428d4e6601949112fe2194b9ae64c70d8d6f99 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Mon, 30 Dec 2024 00:19:40 -0800 Subject: [PATCH] docs: add examples to readme - Add a readme.rs example - Use VHS to generate the output gifs - Adds a script to generate and publish all the gifs in one go - Images are published to VHS rather than committed to the repo to avoid bloating the repo size See for more info on VHS Alternative to: #258 --- README.md | 158 +++++++++++++++++++++++++ examples/readme.rs | 122 +++++++++++++++++++ examples/vhs/confirm-with-default.tape | 12 ++ examples/vhs/confirm.tape | 12 ++ examples/vhs/editor.tape | 13 ++ examples/vhs/fuzzy-select.tape | 17 +++ examples/vhs/input.tape | 12 ++ examples/vhs/multi-select.tape | 21 ++++ examples/vhs/password.tape | 12 ++ examples/vhs/publish-all.sh | 21 ++++ examples/vhs/select.tape | 17 +++ examples/vhs/sort.tape | 21 ++++ 12 files changed, 438 insertions(+) create mode 100644 examples/readme.rs create mode 100644 examples/vhs/confirm-with-default.tape create mode 100644 examples/vhs/confirm.tape create mode 100644 examples/vhs/editor.tape create mode 100644 examples/vhs/fuzzy-select.tape create mode 100644 examples/vhs/input.tape create mode 100644 examples/vhs/multi-select.tape create mode 100644 examples/vhs/password.tape create mode 100755 examples/vhs/publish-all.sh create mode 100644 examples/vhs/select.tape create mode 100644 examples/vhs/sort.tape diff --git a/README.md b/README.md index 2eb7ede9..7348aa72 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,164 @@ Best paired with other libraries in the family: * [console](https://github.com/console-rs/console) * [indicatif](https://github.com/console-rs/indicatif) +## Usage + +Add the library to your `Cargo.toml`: + +```shell +cargo add dialoguer +``` + +## Examples + +### Confirm + +Docs: [dialoguer::Confirm](https://docs.rs/dialoguer/latest/dialoguer/struct.Confirm.html) + +```rust +use dialoguer::{theme::ColorfulTheme, Confirm}; + +if Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Do you want to continue?") + .interact()? +{ + println!("Looks like you want to continue"); +} +``` + +![confirm](https://vhs.charm.sh/vhs-5ianSRV6gBIQw8zHbXZs7X.gif) + +With a default value: + +```rust +use dialoguer::{theme::ColorfulTheme, Confirm}; + +if Confirm::new() + .with_prompt("Do you want to continue?") + .default(true) + .interact()? +{ + println!("Looks like you want to continue"); +} +``` + +![confirm-with-default](https://vhs.charm.sh/vhs-KumYDsqM2KSxaMUHRr8IV.gif) + +## Input + +Docs: [dialoguer::Input](https://docs.rs/dialoguer/latest/dialoguer/struct.Input.html) + +```rust +use dialoguer::{theme::ColorfulTheme, Input}; + +let name: String = dialoguer::Input::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your name?") + .interact()?; +println!("Hello, {name}"); +``` + +![input](https://vhs.charm.sh/vhs-7EYUy5VCybcotdxrL8QCXk.gif) + +## Password + +Docs: [dialoguer::Password](https://docs.rs/dialoguer/latest/dialoguer/struct.Password.html) + +```rust +use dialoguer::{theme::ColorfulTheme, Password}; + +let password: String = Password::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter your password") + .interact()?; +println!("Your password is: {password}"); +``` + +![password](https://vhs.charm.sh/vhs-1HTgKYmFc09dNtuHu5hWOO.gif) + +## Editor + +Docs: [dialoguer::Editor](https://docs.rs/dialoguer/latest/dialoguer/struct.Editor.html) + +```rust +use dialoguer::Editor; + +match dialoguer::Editor::new().edit("Some content")? { + Some(content) => println!("Content: {content:?}"), + None => println!("File was not saved"), +} +``` + +![editor](https://vhs.charm.sh/vhs-3DISbkWUNwMms076djOQ3e.gif) + +## Select + +Docs: [dialoguer::Select](https://docs.rs/dialoguer/latest/dialoguer/struct.Select.html) + +```rust +use dialoguer::{theme::ColorfulTheme, Select}; + +let items = vec!["Apple", "Banana", "Cherry"]; +let selection = Select::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your favourite fruit?") + .items(&items) + .interact()?; +println!("You picked: {selection}", selection = items[selection]); +``` + +![select](https://vhs.charm.sh/vhs-3ylAvmWOIiBkYexnG7j4F9.gif) + +## FuzzySelect + +Docs: [dialoguer::FuzzySelect](https://docs.rs/dialoguer/latest/dialoguer/struct.FuzzySelect.html) + +```rust +use dialoguer::{theme::ColorfulTheme, FuzzySelect}; + +let items = vec!["Apple", "Banana", "Cherry"]; +let selection = FuzzySelect::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your favourite fruit?") + .items(&items) + .interact()?; +println!("You picked: {selection}", selection = items[selection]); +``` + +![fuzzy-select](https://vhs.charm.sh/vhs-3JUdbUNwnUKWVjk6J5XoKh.gif) + +## MultiSelect + +Docs: [dialoguer::MultiSelect](https://docs.rs/dialoguer/latest/dialoguer/struct.MultiSelect.html) + +```rust +use dialoguer::{theme::ColorfulTheme, MultiSelect}; + +let items = vec!["Apple", "Banana", "Cherry"]; +let selection = MultiSelect::with_theme(&ColorfulTheme::default()) + .with_prompt("What are your favourite fruits?") + .items(&items) + .interact()?; +let selected_items: Vec<_> = selection.iter().map(|i| items[*i]).collect(); +println!("You picked: {selected_items:?}"); +``` + +![multi-select](https://vhs.charm.sh/vhs-5Jje1Pdxsw4w5jLJjeWNbI.gif) + +## Sort + +Docs: [dialoguer::Sort](https://docs.rs/dialoguer/latest/dialoguer/struct.Sort.html) + +```rust +use dialoguer::{theme::ColorfulTheme, Sort}; + +let items = vec!["Apple", "Banana", "Cherry"]; +let selection = Sort::with_theme(&ColorfulTheme::default()) + .with_prompt("Sort the fruits") + .items(&items) + .interact()?; +let sorted_items: Vec<_> = selection.iter().map(|i| items[*i]).collect(); +println!("You sorted: {sorted_items:?}"); +``` + +![sort](https://vhs.charm.sh/vhs-mcxq0aABXECgIdafLBNZN.gif) + ## License and Links * [Documentation](https://docs.rs/dialoguer/) diff --git a/examples/readme.rs b/examples/readme.rs new file mode 100644 index 00000000..178e6959 --- /dev/null +++ b/examples/readme.rs @@ -0,0 +1,122 @@ +//! The purpose of this example is to provide simple examples of how to use each of the dialoguer +//! prompts. + +use std::{env::args, thread, time::Duration}; + +#[cfg(feature = "fuzzy-select")] +use dialoguer::FuzzySelect; +use dialoguer::{theme::ColorfulTheme, Confirm, MultiSelect, Password, Select, Sort}; + +fn main() -> dialoguer::Result<()> { + match args().nth(1) { + None => println!("No argument provided"), + Some(arg) => run(arg)?, + } + Ok(()) +} + +fn run(arg: String) -> Result<(), dialoguer::Error> { + match arg.as_str() { + "confirm" => confirm()?, + "confirm-with-default" => confirm_with_default()?, + "input" => input()?, + "password" => password()?, + "editor" => editor()?, + "select" => select()?, + "multi-select" => multi_select()?, + #[cfg(feature = "fuzzy-select")] + "fuzzy-select" => fuzzy_select()?, + "sort" => sort()?, + _ => println!("Invalid argument"), + } + thread::sleep(Duration::from_secs(3)); // give the VHS tape time to capture the effect + Ok(()) +} + +fn confirm() -> dialoguer::Result<()> { + if Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Do you want to continue?") + .interact()? + { + println!("Looks like you want to continue"); + } + Ok(()) +} + +fn confirm_with_default() -> dialoguer::Result<()> { + if Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Do you want to continue?") + .default(true) + .interact()? + { + println!("Looks like you want to continue"); + } + Ok(()) +} + +fn input() -> dialoguer::Result<()> { + let name: String = dialoguer::Input::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your name?") + .interact()?; + println!("Hello, {name}"); + Ok(()) +} + +fn password() -> dialoguer::Result<()> { + let password: String = Password::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter your password") + .interact()?; + println!("Your password is: {password}"); + Ok(()) +} + +fn editor() -> dialoguer::Result<()> { + match dialoguer::Editor::new().edit("Some content")? { + Some(content) => println!("Content: {content:?}"), + None => println!("File was not saved"), + } + Ok(()) +} + +fn select() -> dialoguer::Result<()> { + let items = vec!["Apple", "Banana", "Cherry"]; + let selection = Select::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your favourite fruit?") + .items(&items) + .interact()?; + println!("You picked: {selection}", selection = items[selection]); + Ok(()) +} + +#[cfg(feature = "fuzzy-select")] +fn fuzzy_select() -> dialoguer::Result<()> { + let items = vec!["Apple", "Banana", "Cherry"]; + let selection = FuzzySelect::with_theme(&ColorfulTheme::default()) + .with_prompt("What is your favourite fruit?") + .items(&items) + .interact()?; + println!("You picked: {selection}", selection = items[selection]); + Ok(()) +} + +fn multi_select() -> dialoguer::Result<()> { + let items = vec!["Apple", "Banana", "Cherry"]; + let selection = MultiSelect::with_theme(&ColorfulTheme::default()) + .with_prompt("What are your favourite fruits?") + .items(&items) + .interact()?; + let selected_items: Vec<_> = selection.iter().map(|i| items[*i]).collect(); + println!("You picked: {selected_items:?}"); + Ok(()) +} + +fn sort() -> dialoguer::Result<()> { + let items = vec!["Apple", "Banana", "Cherry"]; + let selection = Sort::with_theme(&ColorfulTheme::default()) + .with_prompt("Sort the fruits") + .items(&items) + .interact()?; + let sorted_items: Vec<_> = selection.iter().map(|i| items[*i]).collect(); + println!("You sorted: {sorted_items:?}"); + Ok(()) +} diff --git a/examples/vhs/confirm-with-default.tape b/examples/vhs/confirm-with-default.tape new file mode 100644 index 00000000..93e0f7a9 --- /dev/null +++ b/examples/vhs/confirm-with-default.tape @@ -0,0 +1,12 @@ +Output target/confirm-with-default.gif + +Set Width 1200 +Set Height 250 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme confirm-with-default" Enter +Show +Sleep 2s +Enter +Sleep 2s diff --git a/examples/vhs/confirm.tape b/examples/vhs/confirm.tape new file mode 100644 index 00000000..cd9349ff --- /dev/null +++ b/examples/vhs/confirm.tape @@ -0,0 +1,12 @@ +Output target/confirm.gif + +Set Width 1200 +Set Height 250 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme confirm" Enter +Show +Sleep 2s +Type "y" +Sleep 2s diff --git a/examples/vhs/editor.tape b/examples/vhs/editor.tape new file mode 100644 index 00000000..85130df7 --- /dev/null +++ b/examples/vhs/editor.tape @@ -0,0 +1,13 @@ +Output target/editor.gif + +Set Width 1200 +Set Height 250 +Set Theme "Aardvark Blue" + +Hide +Type "EDITOR=vim cargo run --quiet --example readme editor" Enter +Show +Sleep 2s +Type "CHello, World!" Escape +Type "ZZ" +Sleep 2s diff --git a/examples/vhs/fuzzy-select.tape b/examples/vhs/fuzzy-select.tape new file mode 100644 index 00000000..838b0d19 --- /dev/null +++ b/examples/vhs/fuzzy-select.tape @@ -0,0 +1,17 @@ +Output target/fuzzy-select.gif + +Set Width 1200 +Set Height 350 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme --features=fuzzy-select fuzzy-select" Enter +Show +Sleep 2s +Type "a" +Sleep 1s +Down +Sleep 1s +Enter + +Sleep 2s diff --git a/examples/vhs/input.tape b/examples/vhs/input.tape new file mode 100644 index 00000000..74eedcfd --- /dev/null +++ b/examples/vhs/input.tape @@ -0,0 +1,12 @@ +Output target/input.gif + +Set Width 1200 +Set Height 250 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme input" Enter +Show +Sleep 2s +Type "pksunkara" Enter +Sleep 2s diff --git a/examples/vhs/multi-select.tape b/examples/vhs/multi-select.tape new file mode 100644 index 00000000..173c33e4 --- /dev/null +++ b/examples/vhs/multi-select.tape @@ -0,0 +1,21 @@ +Output target/multi-select.gif + +Set Width 1200 +Set Height 350 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme multi-select" Enter +Show +Sleep 2s +Down +Sleep 1s +Space +Sleep 1s +Down +Sleep 1s +Space +Sleep 1s +Enter + +Sleep 2s diff --git a/examples/vhs/password.tape b/examples/vhs/password.tape new file mode 100644 index 00000000..d3352def --- /dev/null +++ b/examples/vhs/password.tape @@ -0,0 +1,12 @@ +Output target/input.gif + +Set Width 1200 +Set Height 250 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme password" Enter +Show +Sleep 2s +Type "Password123!" Enter +Sleep 2s diff --git a/examples/vhs/publish-all.sh b/examples/vhs/publish-all.sh new file mode 100755 index 00000000..32535a83 --- /dev/null +++ b/examples/vhs/publish-all.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Publish all VHS examples to the VHS website. +# requires https://github.com/charmbracelet/vhs to be installed + +examples=( + confirm + confirm-with-default + input + password + editor + select + fuzzy-select + multi-select + sort +) +for example in "${examples[@]}"; do + echo "Publishing ${example}..." + vhs --quiet --publish examples/vhs/${example}.tape +done diff --git a/examples/vhs/select.tape b/examples/vhs/select.tape new file mode 100644 index 00000000..98511685 --- /dev/null +++ b/examples/vhs/select.tape @@ -0,0 +1,17 @@ +Output target/select.gif + +Set Width 1200 +Set Height 350 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme select" Enter +Show +Sleep 2s +Down +Sleep 1s +Down +Sleep 1s +Enter + +Sleep 2s diff --git a/examples/vhs/sort.tape b/examples/vhs/sort.tape new file mode 100644 index 00000000..8cac9694 --- /dev/null +++ b/examples/vhs/sort.tape @@ -0,0 +1,21 @@ +Output target/select.gif + +Set Width 1200 +Set Height 350 +Set Theme "Aardvark Blue" + +Hide +Type "cargo run --quiet --example readme sort" Enter +Show +Sleep 2s +Space +Sleep 1s +Down +Sleep 1s +Down +Sleep 1s +Up +Sleep 1s +Enter + +Sleep 2s