[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

re-opening STDIN after it's been closed?

David Vincelli

5/14/2005 9:20:00 PM

here's a summary of a script I just wrote:

while (true) do
puts "Make your selection from the list below: \n\n"
puts "a) foo\n"
puts "b) bar\n\n"
gets
handle_action($_)
end

handle_action does stuff that isn't relevant to my question.

The program works fine except when I hit CTRL-D. After I hit CTRL-D, the
program runs in an endless loop and seems to skip over the gets statement.
Doesn't look good, I can't even break out of it (CTRL-C). Of course CTRL-D
indicates end of file. My guess is that this closes STDIN.

I just thought of a "work around", consisting of inserting

exit unless $_

after the gets statement

I think it might be better to simply re-open STDIN as if nothing had
happened.. is this a good idea and is it possible?

Thanks,

--
David Vincelli
6 Answers

nobu.nokada

5/15/2005 12:56:00 AM

0

Hi,

At Sun, 15 May 2005 06:20:24 +0900,
David Vincelli wrote in [ruby-talk:142655]:
> while (true) do
> puts "Make your selection from the list below: \n\n"
> puts "a) foo\n"
> puts "b) bar\n\n"
> gets
> handle_action($_)
> end

You should alwasy check if get succeeded.

prompt = <<PROMPT
Make your selection from the list below: \n
a) foo
b) bar

PROMPT

while (print(prompt); ans = gets)
handle_action(ans)
end

Or even better if you can use readline:

while ans = readline(prompt)
handle_action(ans)
end

> I think it might be better to simply re-open STDIN as if nothing had
> happened.. is this a good idea and is it possible?

No way to do it. If you believe STDIN is connected to tty, you
may want to do STDIN.reopen("/dev/tty").

--
Nobu Nakada


David Vincelli

5/15/2005 1:44:00 AM

0

Hi,

On 5/14/05, nobu.nokada@softhome.net <nobu.nokada@softhome.net> wrote:
>
> You should alwasy check if get succeeded.
>
> prompt = <<PROMPT
> Make your selection from the list below: \n
> a) foo
> b) bar
>
> PROMPT
>
> while (print(prompt); ans = gets)
> handle_action(ans)
> end


I haven't tried this yet but it's definately better than what I originally
posted.

> Or even better if you can use readline:
>
> while ans = readline(prompt)
> handle_action(ans)
> end


But I did try this. I don't think your usage of readline is correct. ri
tells me that readline takes a single parameter and it's the line seperator


I suppose you meant this:

while (print prompt; ans = readline)
handle_action(ans)
end

No way to do it. If you believe STDIN is connected to tty, you
> may want to do STDIN.reopen("/dev/tty").


Thanks for the tip. I'll stick to the fixed up while loop.

--
David Vincelli

nobu.nokada

5/15/2005 2:00:00 AM

0

Hi,

At Sun, 15 May 2005 10:44:00 +0900,
David Vincelli wrote in [ruby-talk:142672]:
> > Or even better if you can use readline:
> >
> > while ans = readline(prompt)
> > handle_action(ans)
> > end
>
>
> But I did try this. I don't think your usage of readline is correct. ri
> tells me that readline takes a single parameter and it's the line seperator.

Sorry, I forgot "Readline." before it.

require 'readline'
while ans = Readline.readline(prompt)
handle_action(ans)
end

--
Nobu Nakada


ES

5/15/2005 2:28:00 AM

0

David Vincelli wrote:
> Hi,
>
> On 5/14/05, nobu.nokada@softhome.net <nobu.nokada@softhome.net> wrote:
>
>>You should alwasy check if get succeeded.
>>
>>prompt = <<PROMPT
>>Make your selection from the list below: \n
>>a) foo
>>b) bar
>>
>>PROMPT
>>
>>while (print(prompt); ans = gets)
>>handle_action(ans)
>>end
>
>
>
> I haven't tried this yet but it's definately better than what I originally
> posted.
>
>
>>Or even better if you can use readline:
>>
>>while ans = readline(prompt)
>>handle_action(ans)
>>end
>
>
>
> But I did try this. I don't think your usage of readline is correct. ri
> tells me that readline takes a single parameter and it's the line seperator.
>
>
> I suppose you meant this:
>
> while (print prompt; ans = readline)
> handle_action(ans)
> end
>
> No way to do it. If you believe STDIN is connected to tty, you
>
>>may want to do STDIN.reopen("/dev/tty").
>
>
>
> Thanks for the tip. I'll stick to the fixed up while loop.
>

Have you taken a look at some libraries to help you with this?

Cmd[1] is a simple tool for creating command-line oriented interpreters
(think of sqlite/svnadmin/mysqladmin etc.)

HighLine[2] provides a higher-level interface to the command-line from
your script.

E

[1] http://rubyforge.org/pro...
[2] http://rubyforge.org/projects...

--
template<typename duck>
void quack(duck& d) { d.quack(); }


Stephen Lewis

5/15/2005 2:50:00 AM

0

On Sun, May 15, 2005 at 06:20:24AM +0900, David Vincelli wrote:

> The program works fine except when I hit CTRL-D. After I hit CTRL-D, the
> program runs in an endless loop and seems to skip over the gets statement.
> Doesn't look good, I can't even break out of it (CTRL-C). Of course CTRL-D
> indicates end of file. My guess is that this closes STDIN.
<snip>
> I think it might be better to simply re-open STDIN as if nothing had
> happened.. is this a good idea and is it possible?


I don't think it actually closes stdin - try this:

while true
puts "type something"
$stdin.gets
if $stdin.closed?
puts "it's closed"
break
elsif $stdin.eof?
puts "apparently eof"
$stdin.seek( 0, IO::SEEK_CUR )
end
end

Ruby doesn't seem to have an equivalent to clearerr(3), which might
help here - but a successful seek is supposed to reset the eof flag,
though it's fairly ugly, and isn't guaranteed to succeed (it'll
probably break with pipes for one thing). You might try an
ungetc/getc pair as another workaround, but there's probably a much
nicer way.

--
Stephen Lewis


Tanaka Akira

5/15/2005 3:32:00 PM

0

In article <20050515024916.GA7991@ws0.localdomain>,
Stephen Lewis <slewis@orcon.net.nz> writes:

> Ruby doesn't seem to have an equivalent to clearerr(3), which might
> help here - but a successful seek is supposed to reset the eof flag,
> though it's fairly ugly, and isn't guaranteed to succeed (it'll
> probably break with pipes for one thing). You might try an
> ungetc/getc pair as another workaround, but there's probably a much
> nicer way.

Since 1.8.3, Ruby calls clearerr(3) before getc(3) in IO#gets. So you
don't need to clear the eof flag in this case.
--
Tanaka Akira