Как создать тайм-аут для пользовательского ввода в TCL?

У меня есть большой TCL-скрипт, который иногда задает пользователю такие вопросы, как «Пожалуйста, введите свой выбор: A, B или C?»

Пользователь должен ввести символ и нажать «Enter», чтобы продолжить сценарий. Могу ли я в любом случае автоматизировать это в TCL? Что-то вроде того, если пользователь ничего не вводит в течение 10 секунд, по умолчанию будет выбран вариант A, и сценарий продолжится?

Я осмотрелся, и кажется, что единственный способ, которым TCL принимает входные данные, - это команда «gets», но это блокирует и не будет продолжаться, пока пользователь что-то не введет. Есть ли что-нибудь еще, что я могу использовать?

ОТВЕЧАТЬ:

Ответ Колина - это то, что в конечном итоге привело меня к ответу, который я искал (вместе с небольшим поиском в Google). Для тех, кто заинтересован, вот код, который я в итоге использовал,

puts "Are you happy right now?"
puts "\(Press \"n\" or \"N\" within 5 seconds if you say \"No\"\)\nANSWER:"
global GetsInput
exec /bin/stty raw <@stdin
set id [after 5000 {set GetsInput "Y"}]
fileevent stdin readable {set GetsInput [read stdin 1]}
vwait ::GetsInput
after cancel $id
set raw_data $GetsInput
exec /bin/stty -raw <@stdin
uplevel #0 "unset GetsInput"
set user_input [string toupper $raw_data]

puts "\n"
if [ string equal $user_input "N"] {
    puts "You are making me upset as well!!\n"
} else {
    puts "I'm happy for you too !! (^_^)\n"
}

unset raw_data user_input

То, что делает выше, - это задать вопрос и подождать 5 секунд, пока пользователь не нажмет клавишу. Он примет ТОЛЬКО 1 ключ в качестве ввода (пользователю не нужно нажимать ввод). Затем он распечатывает ответ. Оператор if просто демонстрирует, как можно принимать решения на основе приведенного выше кода. К лучшему или к худшему, он не будет работать без поддержки "stty" со стороны вашей операционной системы.


person chronodekar    schedule 18.02.2010    source источник


Ответы (1)


Для аккуратного решения см. proc gets-with-timeout в середине этой вики-страницы, но обратите внимание

  1. Его действие по тайм-ауту - {puts "Are you fall asleep?"; exit}, которое вы, вероятно, должны изменить на {set GetsInput "my default input"}.
  2. Это зависит от ожидания в цикле событий Tcl - это то, что делает vwait. Встроенная установка Tcl может не позволить работать циклу событий, в зависимости от того, как он был интегрирован.

Если вы не можете заставить это работать, более грубый подход будет просто:

fconfigure stdin -blocking 0
puts -nonewline "Enter data:"
flush stdout
after 10000
gets stdin data
puts "Got data '$data'"

Это делает stdin неблокирующим, записывает приглашение, ждет 10 секунд, затем читает строку ввода, если она была введена, и просто продолжает, если ничего не было введено. Недостатком является ожидание полных 10 секунд, даже если пользователь сразу вводит свой ввод.

person Colin Macleod    schedule 18.02.2010
comment
Колин, этот вики-код выглядит так, как мне нужно (по крайней мере, тестовый скрипт в другой системе Fedora работает)! Я собираюсь попробовать свое приложение и вернуться к вам по нему. - person chronodekar; 18.02.2010
comment
Мне потребовалось несколько доработок, но я получил нужный мне функционал. Я добавляю это к моему вопросу и отмечаю это как ответ. На самом деле, я собирался отказаться от этого, пока не увидел твой ответ, Колин!! - person chronodekar; 19.02.2010