# Print message if user does nothing for x seconds?

**URL:** <https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640>\
**Category:** Ruby\
**Created:** [November 11, 2006, 8:20pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640 "2006-11-11T20:20:22Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 8:20pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/1 "2006-11-11T20:20:22Z")

</div>

Hi all,

Only just started using ruby so this may be really simple to do, but  
here goes:

I’m trying to write a program that asks a user to enter their sex using  
“gets” but if the user doesn’t type anything for about 5 seconds I want  
to print a message, like “Please enter something…” then go back to the  
gets prompt. I’ve tried using the “sleep x” method but it doesn’t seem  
to work because once gets has been initiated it gets stuck there until  
something is entered.

Oh I don’t have to use gets, but this is the only method of input I’m  
aware of at the moment

Hope this makes sense,  
Ben

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 8:22pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/2 "2006-11-11T20:22:23Z")

</div>

Ben T. wrote:

> something is entered.
> 
> Oh I don’t have to use gets, but this is the only method of input I’m  
> aware of at the moment

This is tricky on Windows… what platform are you on?

Hal

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 8:30pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/3 "2006-11-11T20:30:25Z")

</div>

Hal F. wrote:

> > doesn’t seem to work because once gets has been initiated it gets  
> > stuck there until something is entered.
> > 
> > Oh I don’t have to use gets, but this is the only method of input I’m  
> > aware of at the moment
> 
> This is tricky on Windows… what platform are you on?
> 
> Hal

Windows… D’oh!

Is there any better ways to get input from the user that’d make is  
easier?

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:08pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/4 "2006-11-11T21:08:30Z")

</div>

On Sun, 12 Nov 2006, Ben T. wrote:

> entered.
> 
> Oh I don’t have to use gets, but this is the only method of input I’m aware  
> of at the moment
> 
> Hope this makes sense,  
> Ben

if you’re on windows give up now. otherwise try this:

```
 harp:~ > cat a.rb
 require 'timeout'

 def prompt question, opts = {}
   timeout = Integer(opts['timeout'] || opts[:timeout] || 42)
   max = Integer(opts['max'] || opts[:max] || 42)
   default = opts['default'] || opts[:default]
   prod = (opts['prod'] || opts[:prod] || 'hey! wake up!').to_s

   answer = default
   prompt = "\r#{ question }: "
   prod = "\r#{ prod }"

   if prompt.size > prod.size
     prod += (' ' * (prompt.size - prod.size))
   end
   if prod.size > prompt.size
     prompt += (' ' * (prod.size - prompt.size))
   end

   max.times{
     begin
       print prompt
       STDOUT.flush
       Timeout::timeout(timeout){ answer = gets }
       break
     rescue Timeout::Error
       print prod
       STDOUT.flush
       sleep 2
     end
   }

   answer
 end

 answer = prompt 'the question', 'timeout' => 5, 'max' => 2

 p 'answer' => answer

```

-a

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:36pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/5 "2006-11-11T21:36:34Z")

</div>

David V. wrote:

> > to work because once gets has been initiated it gets stuck there until  
> > Read the data in a thread, or use nonblocking io (currently crude at  
> > best, with only eventmachine to help as a project that shown up on my  
> > radar - and that seems to be oriented towards networking)
> 
> Also, what you describe there is a very rude thing to do to your user,  
> basically you’re accusing them of having no attention span and the  
> program is attention-seeking to compensate.
> 
> David V.

Yeah, I’d never even think of doing it normally, it was just put in a  
small program specification for uni. It’s not an assignment or anything  
so I’ll probably just leave that part out if it’s hard to implement.

The part of the specification was:

```
3. Keep the program running until the user shouts “BYE”. If, while

```

the program is running, nothing is happening Grandma should shout  
“WHAT? CAT GOT YOUR TONGUE? SPEAK UP, I SAY!"

I’ll just leave the “cat got your tongue” part out for now. Managed to  
keep the program running until the user shouts “BYE” easy enough, just  
the second part causing problems.

Thanks for the help.

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:36pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/6 "2006-11-11T21:36:34Z")

</div>

On 11/nov/06, at 21:07, removed\_email\_address@domain.invalid wrote:

> ```
> end
> }
> 
> answer
> end
> 
> answer = prompt 'the question', 'timeout' => 5, 'max' => 2
> 
> p 'answer' => answer
> 
> ```

Nice! May I suggest adding an optional validation block?  
I hope you don’t mind if I slightly modify your code:

def prompt question, opts = {}, &validation  
timeout = Integer(opts[‘timeout’] || opts[:timeout] || 42)  
max = Integer(opts[‘max’] || opts[:max] || 42)  
default = opts[‘default’] || opts[:default]  
prod = (opts[‘prod’] || opts[:prod] || ‘hey! wake up!’).to\_s  
invalid = (opts[‘invalid’] || opts[:invalid] || ‘try again’).to\_s

answer = default  
prompt = "\r#{ question }: "  
prod = “\r#{ prod }”

if prompt.size \> prod.size  
prod += (’ ’ \* (prompt.size - prod.size))  
end  
if prod.size \> prompt.size  
prompt += (’ ’ \* (prod.size - prompt.size))  
end

max.times{  
begin  
print prompt  
STDOUT.flush  
Timeout::timeout(timeout){ answer = gets }  
if validation && !validation.call(answer)  
answer = default  
puts invalid  
else  
break  
end  
rescue Timeout::Error  
print prod  
STDOUT.flush  
sleep 2  
end  
}

answer  
end

answer = prompt(‘the question’, ‘timeout’ =\> 5, ‘max’ =\> 2) { |s| s  
== “valid input\n” }

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:40pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/7 "2006-11-11T21:40:35Z")

</div>

removed\_email\_address@domain.invalid wrote:

> > back to the gets prompt. I’ve tried using the “sleep x” method but it  
> > if you’re on windows give up now. otherwise try this:  
> > answer = default  
> > max.times{  
> > }
> 
> -a

Thanks for the reply. Unfortunately I am on windows.

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/8 "2006-11-11T21:12:31Z")

</div>

Ben T. wrote:

> something is entered.
> 
> Oh I don’t have to use gets, but this is the only method of input I’m  
> aware of at the moment
> 
> Hope this makes sense,  
> Ben

Read the data in a thread, or use nonblocking io (currently crude at  
best, with only eventmachine to help as a project that shown up on my  
radar - and that seems to be oriented towards networking)

Also, what you describe there is a very rude thing to do to your user,  
basically you’re accusing them of having no attention span and the  
program is attention-seeking to compensate.

David V.

---

<div class="post-metadata">

**Author:** ![nbits](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/8c91f0/32.png) [@nbits](https://www.ruby-forum.com/u/nbits)\
**Post date:** [November 11, 2006, 9:48pm UTC](https://www.ruby-forum.com/t/print-message-if-user-does-nothing-for-x-seconds/75640/9 "2006-11-11T21:48:36Z")

</div>

Ben T. wrote:

> Thanks for the reply. Unfortunately I am on windows.

Actually I think this should partially work on Windows.

As I recall, I found that as long as the user typed  
_nothing_, timeout was possible. But if the user  
typed a character or more and just didn’t finish, it  
wouldn’t time out.

Hal
