# Way of handling CLI interface for chat program

**URL:** <https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924>\
**Category:** Ruby\
**Created:** [January 3, 2008, 8:13pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924 "2008-01-03T20:13:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![michael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4bbf92/32.png) [@michael](https://www.ruby-forum.com/u/michael)\
**Post date:** [January 3, 2008, 8:13pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924/1 "2008-01-03T20:13:49Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![michael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4bbf92/32.png) [@michael](https://www.ruby-forum.com/u/michael)\
**Post date:** [January 3, 2008, 8:25pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924/2 "2008-01-03T20:25:35Z")

</div>

On Jan 3, 2008 8:13 PM, Michael [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
If I understood correctly, James’ Highline library might just be what  
you need  
[http://rubyforge.org/projects/highline/](http://rubyforge.org/projects/highline/)

## HTH Robert

[http://ruby-smalltalk.blogspot.com/](http://ruby-smalltalk.blogspot.com/)

* * *

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

---

<div class="post-metadata">

**Author:** ![michael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4bbf92/32.png) [@michael](https://www.ruby-forum.com/u/michael)\
**Post date:** [January 3, 2008, 8:28pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924/3 "2008-01-03T20:28:32Z")

</div>

On Jan 3, 2008 12:13 PM, Michael [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![michael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4bbf92/32.png) [@michael](https://www.ruby-forum.com/u/michael)\
**Post date:** [January 3, 2008, 10:54pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924/4 "2008-01-03T22:54:18Z")

</div>

On 1/3/08, Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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?

---

<div class="post-metadata">

**Author:** ![michael](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/4bbf92/32.png) [@michael](https://www.ruby-forum.com/u/michael)\
**Post date:** [January 3, 2008, 11:46pm UTC](https://www.ruby-forum.com/t/way-of-handling-cli-interface-for-chat-program/124924/5 "2008-01-03T23:46:02Z")

</div>

On Jan 3, 2008, at 3:53 PM, Michael wrote:

> ## $ ./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 G. II
