Как предотвратить «опережающий ввод»

#rust #command-line-interface

#Ржавчина #интерфейс командной строки

Вопрос:

Я хочу использовать диалоговое окно crate, чтобы позволить пользователю проверять и исправлять некоторые предлагаемые данные.

Зависимости Cargo.toml

 [dependencies]
dialoguer = "0.7"
 

src/main.rs

 use dialoguer::Input;

fn main() {
    // searching the web
    std::thread::sleep(std::time::Duration::from_secs(5));
    let suggestion = "Catpictures".to_string();

    let data : String = Input::new()
        .with_prompt("suggested")
        .with_initial_text(suggestion)
        .interact_text()
        .expect("failed to correct suggestion");
}
 

Моя проблема в том, что, пока программа ищет предложение, пользователь может начать печатать и нажать ENTER.
Затем программа отображает предложение и немедленно принимает ответ.
Я хотел бы предотвратить такое поведение.

Текущее поведение:

  • запуск программы
  • нажатие enter (по какой-либо причине)
  • программа отображает предложение и немедленно принимает предложение

желаемое поведение:

  • запуск программы
  • нажатие enter (по какой-либо причине)
  • программа отображает предложение
  • пользователь может отредактировать предложение и принять его с помощью enter

Есть ли способ очистить ввод?

Комментарии:

1. Что вы хотите, чтобы произошло вместо этого, и какую реакцию ваших пользователей, которые вводят с опережением, вы представляете?

Ответ №1:

Ни в стандартной библиотеке, ни dialoguer в функциях нет функций для очистки stdin.

Одним из обходных путей является использование AsyncReader из crossterm_input ящика, в котором вы можете опрашивать входные данные (события) из stdin. Таким образом, вы сможете очистить любой ожидающий ввод перед использованием dialoguer .

 // crossterm_input = "0.5"
fn clear_stdin() {
    let input = crossterm_input::input();
    let mut async_stdin = input.read_async();
    while let Some(_) = async_stdin.next() {}
}
 

Ваш обновленный пример будет выглядеть следующим образом:

 use dialoguer::Input;

fn main() {
    // searching the web
    thread::sleep(time::Duration::from_millis(200));
    let suggestion = "Catpictures".to_string();

    clear_stdin();

    let data = Input::new()
        .with_prompt("suggested")
        .with_initial_text(suggestion)
        .interact_text()
        .expect("failed to correct suggestion");
}
 

Комментарии:

1. Еще не удалось заставить это вести себя так, как ожидалось. Но мы рассмотрим это подробнее.. Спасибо, что указали мне на crossterm.

2. @Drei Какое поведение вы получаете? и на какой ОС вы работаете?

3. ОС — ubuntu 20. При итерации с текстом он удаляет входные данные. Также он не очищает ввод каждый раз.