[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Way of handling CLI interface for chat program.

Michael

1/3/2008 7:13:00 PM

Hello, folks.

I'm trying to write simple CLI program which will be some kind of
chat, but i have faced with some output problem.
Is it possible to output over current line in stdout?

User types something in prompt> and at this moment message from
another user arrives. Currently, I'm using readline, and if i just
<puts "\n#{user}: #{message}\n"> I'll end with following

screen 2:
------------------------------------------
$ ./chat.rb
prompt> hello, peo <-he was typing
UserA: Ruby is cool!!!!1111

------------------------------------------

So, my goal is output "UserA.." over my prompt>, to not confuse user
and do not make him retype everything on every event.

------------------------------------------
$ ./chat.rb
UserA: Ruby is cool!!!!1111
prompt> hello, peo <-he is still typing..
------------------------------------------

Thanks for any help.

4 Answers

Robert Dober

1/3/2008 7:24:00 PM

0

On Jan 3, 2008 8:13 PM, Michael <misha@onet.ru> wrote:
If I understood correctly, James' Highline library might just be what you need
http://rubyforge.org/projects...

HTH
Robert
--
http://ruby-smalltalk.blo...

---
Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

Tim Pease

1/3/2008 7:28:00 PM

0

On Jan 3, 2008 12:13 PM, Michael <misha@onet.ru> wrote:
> Hello, folks.
>
> I'm trying to write simple CLI program which will be some kind of
> chat, but i have faced with some output problem.
> Is it possible to output over current line in stdout?


STDOUT.write "\rThis will overwrite the current line"

The "\r" is the carriage return character, and it will return the
insert point to the beginning of the current line. The only caveat is
that the new line you are writing needs to be at least as long as the
line you wish to overwrite. If it is not, you will have remnants of
the previous line at the end of your output.

Another option would be to use the "highline" gem.

Blessings,
TwP

Michael

1/3/2008 9:54:00 PM

0

On 1/3/08, Tim Pease <tim.pease@gmail.com> wrote:
> STDOUT.write "\rThis will overwrite the current line"
>
> The "\r" is the carriage return character, and it will return the
> insert point to the beginning of the current line. The only caveat is
> that the new line you are writing needs to be at least as long as the
> line you wish to overwrite. If it is not, you will have remnants of
> the previous line at the end of your output.

You can issue STDOUT.write("\e[K"), it will erase whole line and you
won't bother about it length, but it's not what i'm asking for :(
sorry for my English, I'll try be more specific.

Consider the following example:
---------------------------------------------------
th = Thread.new { loop do puts "Hello, Ruby!"; sleep(10) end }
while (line = Readline.readline("prompt> ", true))
puts "#{line}: processed"
end
---------------------------------------------------

This code will produce such results:
---------------------------------------------------
$ ./cli.rb
Hello, Ruby!
prompt> I WAS TYPING HERE FOR 10 SECONDSHello, Ruby!
---------------------------------------------------
And what I want, it's ALL lines be put above my input prompt, and not
interrupting me while I'm typing.

> Another option would be to use the "highline" gem.

Yeah, thank you and Robert for that pointing (really good ideads
inside!), but brief looking shows that it is not suitable for my
purpose of non-standard outputting.

One way to solve this problem which i see is safe current line of
input, including "prompt> ", erase it, output event, and output saved
line again, hopefully it will be fast enough and user won't see
anything, but how can i get current line, anyway?

James Gray

1/3/2008 10:46:00 PM

0

On Jan 3, 2008, at 3:53 PM, Michael wrote:
> Consider the following example:
> ---------------------------------------------------
> th = Thread.new { loop do puts "Hello, Ruby!"; sleep(10) end }
> while (line = Readline.readline("prompt> ", true))
> puts "#{line}: processed"
> end
> ---------------------------------------------------
>
> This code will produce such results:
> ---------------------------------------------------
> $ ./cli.rb
> Hello, Ruby!
> prompt> I WAS TYPING HERE FOR 10 SECONDSHello, Ruby!
> ---------------------------------------------------
> And what I want, it's ALL lines be put above my input prompt, and not
> interrupting me while I'm typing.

This doesn't clear the lines as you were asking for, but hopefully it
will give you new ideas:

#!/usr/bin/env ruby -wKU

require "thread"
require "timeout"

require "rubygems"
require "highline/system_extensions"

incoming_messages = Queue.new
output_buffer = String.new

# simulate incoming server messages
Thread.new do
loop do
incoming_messages << "AnnoyingUser: Hi, I'm still here!"
sleep 5
end
end

# main event loop
prompt = true
loop do
# handle output
unless incoming_messages.empty?
puts unless prompt
puts incoming_messages.shift until incoming_messages.empty?
prompt = true
end
puts incoming_messages.shift until incoming_messages.empty?

# prompt
if prompt
print ">> #{output_buffer}"
$stdout.flush
prompt = false
end

# fetch input
begin
Timeout.timeout(0.1) do
if char = HighLine::SystemExtensions.get_character.chr
output_buffer << char
print char
$stdout.flush
end
end
rescue Timeout::Error
# do nothing -- we'll try again later
end

# handle full lines of input
if output_buffer[-1, 1] == "\n"
incoming_messages << "Sending '#{output_buffer.chomp}' to
server..."
output_buffer = String.new
prompt = true
end
end

__END__

James Edward Gray II