I have a ruby script that is simultaneously and asynchronously receiving and displaying messages from a server, and allowing user input on the console. When a message is received, it is currently being written in the middle of what the user is typing. The input itself isn't garbled, but it looks horrible. Ideally, it would save the users current input, output the message, and then restore the input on the next line. I've done this in c by intercepting every key stroke, but all I remember is that it was a major hassle. I'm fairly new to ruby, so I'm not sure if there is a good way to do this, or how to do it.
Example: User is typing >abcde
, and message hello
comes in, and user types fgh
after. The console would now show:
>abcdehellofgh
and user can continue typing at the end. I would like it to show:
hello
>abcdefgh
The two important parts of my proposal are:
1. system("stty raw -echo") # to instantly get any typed character in combination with
2. using STDIN.getc with a string-var serving as an input-buffer to reprint the user input.
Pressing 9 (& boolean variable incoming_message) is used for ultra-simple simulation for your server-messages.
(Being more realistic would bloat the example without adding much, since you have to adapt the idea for your scenario anyway.)
Press x for exit.
Sample output:
$ ruby simultaneous_input_and_output.rb
Hello World!9
The incoming message is: true
Hello World!9x
You entered:
Hello World!9x
End!
#!/usr/bin/ruby
$input_buffer = "";
incoming_message = false
begin
system("stty raw -echo")
begin
str = STDIN.getc
print str.chr
$input_buffer = $input_buffer + str.chr
if str.chr == '9'
incoming_message = true
end
if incoming_message
puts "\nThe incoming message is: " + incoming_message.to_s
print $input_buffer
incoming_message = false
end
end while (str.chr != 'x')
ensure
system("stty -raw echo")
end
puts "\n\nYou entered:"
puts $input_buffer
puts "End!"
P.S.:
for system("stty raw -echo") see (User Jay)
How to get a single character without pressing enter?
I'm going to be facing pretty much the same problem.
I've decided to change my approach. I'm going to write a simple client that has a text entry box at the bottom and a message window for the rest of the screen.
The client and the server will exchange data using some sort of message format -- YAML, probably, since it works so well with Ruby, but it could be something considerably simpler.
(I'm not sure this is precisely an answer to your question, however.)