Skip to main content

prompt

Function prompt 

Source
pub fn prompt(
    message: impl Into<String>,
) -> PromptBuilder<ZString, Cancellable, impl FnMut(&mut String) -> Result<bool>>
Available on crate features print and prompt only.
Expand description

§Prompting

The prompt feature allows displaying prompts in the console to accept user input. The prompts are thread-safe and synchronized with the printer. When a prompt is active, outputs to the console will be buffered inside the printer. Progress bars will also be paused.

The --yes, --non-interactive, and --interactive CLI flags are enabled with the prompt feature, see Command Line Interface for more information.

The PromptBuilder is the main struct used to configure the prompt. The entry point to configuration are cu::prompt() and cu::yesno(). The default configuration are as follows:

  • cu::prompt(message): No validation, returns None if user presses Ctrl-C
  • cu::yesno(messsage): Accepts case-insensitive y, n, yes or no, appends " [y/n]" to the input message, and pressing Ctrl-C is the same as answering “no”.

Call .run() to show the prompt and wait for the input:

match cu::prompt("please enter your name").run()? {
    None => cu::info!("cancelled"), // pressed Ctrl-C
    Some(name) => cu::info!("user entered: {name}"),
}

§Macros

The cu::prompt! or the cu::yesno! macro are shorthands to show prompt for the most common scenarios. They also accept format args:

  • cu::prompt!(format_args): No validation, bails if user presses Ctrl-C
  • cu::yesno!(format_args): Same behavior as cu::yesno(message)

These are designed to “just work” with ? in 99% of the cases.

§Builder Methods

For advanced configurations, refer to the following builder methods

  • password: Hides the input when typing in console. Also will force reading from terminal if stdin is not terminal.
  • trim_trailing_whitespace: If disabled, trailing whitespaces are not trimmed. The output will still not contain CRLF or LF at the end. (Default is enabled - will trim whitespace).
  • validate_with: attaches a validation function. The prompt will loop until the validation passed or an error occurs.
  • if_cancel: Set a default value to return if Ctrl-C is pressed. This will make the prompt not return Option, but the inner value directly. (Note the default value does not go through the validator)
  • or_cancel: Return a “canceled by user” error if Ctrl-C is pressed. This also appends “(Ctrl-C to cancel)” to the prompt message.

Example:

let expected = "rust";
let answer: cu::ZString = cu::prompt(
    format!("what's your favorite programming language? please answer {}", expected)
).validate_with(
    |answer| {
        if answer == expected {
            return Ok(true);
        }
        if answer == "javascript" {
            cu::bail!("that's not good");
        }
        cu::error!("try again");
        Ok(false)
    }
)
.if_cancel("javascript")
.run()?;
if answer == "javascript" {
    cu::info!("hey, did you press Ctrl-C?");
} else {
    cu::info!("your answer: {answer}");
}

§Async

Use .co_run().await? instead of .run() in async contexts to wait for the answer using the async runtime instead of blocking the current thread.

When using the macros, add async to the beginning of the input

let answer = cu::prompt!(async "how are you today?")?;
cu::info!("you: {answer}");

§Multiple Prompts

If multiple prompts are requested (for example from many threads), they are put into a FIFO queue. Only one prompt will be displayed to the user at a time.

§Interaction with Progress Bars

If there are both progress bars and a prompt active, the prompt is displayed below the progress bars. This lines up with the common expectation that prompts are shown at the bottom of the output. Progress bars will also be paused - otherwise the user will be typing their answer all over in the animated area.

This brings one interesting use case, which is printing other messages related to the prompt before the prompt. For example:

// ... imagine a progress bar is active here
cu::warn!(
    "this is an important warning about the prompt! read this carefully when answering!"
);
let _ = cu::prompt!("please enter important information")?;

The warning message is guaranteed to be printed before the prompt. However, because there are progress bars active, the warning message and the prompt will be separated by the progress bar. The user might miss the important message.

W] this is an important warning about the prompt! read this carefully when answering!
 ][42/100] progress running...
!] please enter important information
-:

The way to address this is to print any message related to the prompt within the prompt macro:

// ... imagine a progress bar is active here
let _ = cu::prompt!(r"this is an important warning about the prompt! read this carefully when answering!
please enter important information")?;

output:

 ][42/100] progress running...
!] this is an important warning about the prompt! read this carefully when answering!
 | please enter important information
-: