2 releases

0.0.2 Aug 26, 2021
0.0.1 Aug 12, 2021

#770 in Command-line interface

MIT/Apache

45KB
643 lines

asking

Download License Docs Crate

Build async prompts.

About

Ever wanted non-blocking user input? Here you are!

Asynchronous I/O is a form of input/output processing that allows you to do something while waiting for an answer.

Features

  • Asynchronous - You can work while the user inputs something and even timeout!
  • Common patterns - Built-in common question patterns including
    • yn - yes/no questions (see yn function).
    • date - dates in %Y-%m-%d format (see date function).
    • select - choose one option (see inside method).
    • text - just a String (see text function).
    • T - your own type! (implementing or not the trait FromStr).
  • Cross-platform - Generic on writer and reader!
  • Help messages - Help the user to input a correct answer.
  • Test with feedback - Test the input and, optionally, give feedback upon errors.
  • Default values - Add a value for empty inputs.
  • Standardized error handling - You can manage errors!
  • Feedback - Display a final message depending on the accepted value.
  • Extensive documentation - If you do not think so, let me know!

Limitations

  • Internal mutability of functions - All functions are stored as Arc<dyn Fn>. This allows both functions and closures, but it means that functions can not hold any mutable references (so no internal mutability).
  • Send + Sync + 'static - To allow asynchronous execution, at the end of the day, all parameters have to implement this traits. This way you can truly harness async execution of questions. If you manage to use something that does not implement these traits, then the future can only be executed synchronously.
  • Consuming methods - Methods are consuming allowing one-line constructions, while making more difficult complex construction patterns. This is because of the existence of default values. Check out C-BUILDER.

Let me know if you find anything else, I will be happy to add it!

Quick example

Give only five seconds to the user to confirm something, and continue upon no input! (instead of keep waiting)

use asking::error::Processing;
use std::time::Duration;

let question = asking::yn()
    .message("Shall I continue? (you have 5 seconds to answer)")
    .default_value(true) // value upon empty input
    .timeout(Duration::from_secs(5_u64))
    .ask();

match async_std::task::block_on(question) { // we decide to just wait, at most five secs
    Ok(true) => println!("Super!"),
    Ok(false) => println!("Okay, shutting down..."),
    Err(Processing::Timeout { .. }) => println!("I think you are not here, I will continue :)"), // Automatic decision!,
    _ => eprintln!("Error with questionnaire, try again later"),
}

Check out more examples!

Usage

With cargo-edit installed, simply type

cargo add asking

and you are good to go!

There are several crates for handling user input, I recommend checking them all out!

  • ask A simple toolset for asking questions through the terminal.
  • dialoguer A command line prompting library.
  • inquire Library for building interactive prompts on terminals.
  • promptly Simple, opinionated CLI prompting helper.
  • requestty An easy-to-use collection of interactive cli prompts.
  • rprompt Prompt user input in console applications.
  • question Ask a question, what more could you want?
  • read_input A simple CLI tool that asks for user input until the data inputted is valid.
  • termion::AsyncReader An asynchronous reader.
  • timeout-readwrite Adds timeout capabilities to Readers and Writers.

If you've got a crate that would be a good fit, open an issue and let me know. I'd love to add it!

Good matchups

Some crates are good to use together!

FAQ

Testing

Testing projects with user input can be challenging.

  • How to give input to Stdin and read from Stdout? The easiest way is using the assert_cmd crate. Check out

Dependencies

~5–15MB
~200K SLoC