Having looked at this question, I have the following code:
$/ = "\0"
answer = STDIN.gets
Now, I was hoping that this would allow the user to:
- enter a multi-line input, terminating by pressing Ctrl-D.
- enter a single line input, terminating by pressing Ctrl-D.
- enter a “nothing” input, terminating by pressing Ctrl-D.
However, the behaviour I actually see is that:
- The user can enter a multi-line input fine.
- The user can not enter a single line input, unless they hit Ctrl-D twice.
- The user can enter a “nothing” input if they hit Ctrl-D straight away.
So, why does the single line situation (i.e. if the user has entered some text but no newline and then hit Ctrl-D) require two presses of Ctrl-D? And why does it work then if the user enters nothing? (I have noted that if they enter nothing and hit Ctrl-D, I don’t get an empty string but the nil class – I discovered this when trying to call .empty? on the result, since it suddenly failed horribly. If there is a way to get it to return an empty string as well, that would be nice. I prefer checking .empty? to ==, and don’t particularly want to define .empty? for the nil class.)
EDIT: Since I really would like to know the “correct way” to do this in Ruby, I am offering a bounty of 200 rep. I will also accept answers that give another way of entering terminal multi-line input with a sensible “submit” procedure – I will be the judge of ‘suitable’. For example, we’re currently using two “\n”s, but that’s not suitable, as it blocks paragraphs and is unintuitive.
The basic problem is the terminal itself. See many of the related links to the right of your post. To get around this you need to put the terminal in a raw state. The following worked for me on a Solaris machine:
I’m not sure if the storing and restoring of the stty settings is necessary but I’ve seen other people do it.