chronodekar
chronodekar

Reputation: 2746

How do I create a timeout for user input in TCL?

I have a large TCL script that, at points asks the user questions like, "Please enter your choice : A, B or C ?"

The user has to type in the character and press "Enter" to continue to script. Is there anyway I can automate this in TCL? Something like, if the user doesn't enter anything within 10 seconds, by default option A will be taken and the script will continue?

I've looked around and it seems that the only way TCL accepts inputs is with the "gets" command - but this is blocking and won't proceed until the user enters something. Is there anything else I can use?

ANSWER:

Colin's reply is what ultimately led me to the answer I was looking for (along with a bit of googling). To those interested here is the code I ended up using,

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

What the above does is ask a question and wait for 5 seconds for a user key-press. It will accept ONLY 1 key as input (user doesn't need to press enter). It then prints out a response. The if statement is just to demonstrate how one could make decisions based on the above code. For better or worse, it won't run without "stty" support from your operating system.

Upvotes: 2

Views: 5059

Answers (1)

Colin Macleod
Colin Macleod

Reputation: 4382

For a neat solution see proc gets-with-timeout in the middle of this wiki page, but note

  1. Its action on timeout is {puts "Are you fall asleep?"; exit} which you should probably change to {set GetsInput "my default input"}
  2. It depends on waiting in the Tcl event loop - that's what vwait does. An embedded Tcl installation might not allow the event loop to work, depending how it's been integrated.

If you can't get this to work, a cruder approach would be just:

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

This makes stdin non-blocking, writes a prompt, waits 10 seconds, then reads a line of input if it has been entered, just continuing if nothing has been entered. The downside is it waits the full 10 sec even if the user types their input immediately.

Upvotes: 4

Related Questions