ruby / reline

The compatible library with the API of Ruby's stdlib 'readline'

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

I think I finally found a real bug - or, at the least, a difference in behaviour between Reline and Readline

rubyFeedback opened this issue · comments

Hey again reline-devs,

I think I finally found a bug, at the least an issue on my computer setup.

I also wrote a .rb file that can reproduce this behaviour - at the least on my machine.

So, without further ado, first the .rb file content that shows the behaviour - you should
be able to easily copy/paste it, I made sure that it works standalone (although you
may need the readline gem and perhaps the reline gem installed to test its
behaviour):

require 'reline'
require 'readline'

RED   = "\u001b[31m"
RESET = "\u001b[0m"

alias e puts
alias ee print

# Determine the mode - change the following between the
# three symbols :reline, :readline and :stdin.
USE_THIS_MODE = :stdin # :readline # :reline

def show_the_prompt
  ee Dir.pwd+'/'
end

loop {
  show_the_prompt
  case USE_THIS_MODE
  when :stdin
    user_input = $stdin.gets.chomp
  when :reline
    user_input = Reline.readline('',true)
  when :readline
    user_input = Readline.readline('',true)
    e
  end
  case user_input
  when 'q','exit'
    break
  else
    ee RED+user_input+RESET
  end
}

Alright.

So, how to use this? The CONSTANT called USE_THIS_MODE can be
used to toggle between three modes:

:reline
:readline
:stdin

By default it will use :stdin. This is the normal behaviour. Please run
that script - you will see that on pressing enter, a new line is shown,
and then the current working directory is displayed via the method
call show_the_prompt().

Now, please try it again, but change the value of the constant from
:stdin to :readline. Then run the file again.

The behaviour between :readline and :stdin is the same. The only
difference as far as I can tell is that via readline we get additionally
the input history, so we can access it via the arrow-keys on the
keyboard. (We could also use tab completion, but for this demo
I only wanted to showcase the issue at hand, not to get overly
fancy.)

Now switch that constant to :reline please. When I do so and run
it, I get a different behaviour: I don't get any output. But, oddly
enough, when I hit the enter key multiple times, and do so
quickly, then sometimes I suddenly have input. To me it seems
as if Reline is doing some buffering internally and that leads
to awkward behaviour. When I use Readline then that behaviour
does not show up, so either this is a bug in Reline, or at the least
another incompatibility. It is a bit confusing and I think for the time
being I have to prefer Readline.

The API I use is:

Reline.readline('',true)

Which I do for Readline too:

Readline.readline('',true)

Not sure if that causes any difference in behaviour or another method
should be used. If you folks can not see any difference behaviour if
you try all three variants then perhaps something else is messed up
on my system - but it can not be completely messed up, because
$stdin and Readline work just fine, whereas Reline does not, so I
suspect that Reline is doing something that leads to swallowing
input or something like that. Or perhaps it is related to print(), I
am not sure.

Can anyone try the above .rb script in each of the three variants
and then see if there is a difference? If there is not then perhaps
my computer is messed up.

Readline doesn't clear current line so you can do something like this

require 'readline'
print 'pro'
sleep 1
Readline.readline('mpt>')
# prompt> (looks like prompt is `prompt>` but it has problem described below)

In Reline, you can see pro is displayed only 1 sec, Reline clears current line and prompt will be mpt>

require 'reline'
print 'pro'
sleep 1
Reline.readline('mpt>')
# mpt>

I prefer Reline's behavior because Readline's behavior have problem

require 'readline'
print 'pro'
input = Readline.readline('mpt>')
p input: input
# press `helloworld [\C-a] ! [enter]` will get
# prom!helloworldld ← prompt and input is displayed broken
# {:input=>"!helloworld"} ← input is correct

These kind of Readline's behavior (maybe a bug, unexpected usage, undefined behavior or something) might be fixed or changed in the future and will depend on Readline's version.
IMO I don't think Reline should follow it.