Giter Club home page Giter Club logo

reline's Introduction

Gem Version CI

This is a screen capture of IRB improved by Reline.

IRB improved by Reline

Reline

Reline is compatible with the API of Ruby's stdlib 'readline', GNU Readline and Editline by pure Ruby implementation.

Usage

Single line editing mode

It's compatible with the readline standard library.

See the document of readline stdlib or bin/example.

Multi-line editing mode

require "reline"

prompt = 'prompt> '
use_history = true

begin
  while true
    text = Reline.readmultiline(prompt, use_history) do |multiline_input|
      # Accept the input until `end` is entered
      multiline_input.split.last == "end"
    end

    puts 'You entered:'
    puts text
  end
# If you want to exit, type Ctrl-C
rescue Interrupt
  puts '^C'
  exit 0
end
$ ruby example.rb
prompt> aaa
prompt> bbb
prompt> end
You entered:
aaa
bbb
end

See also: test/reline/yamatanooroti/multiline_repl

Documentation

Reline::Face

You can modify the text color and text decorations in your terminal emulator. See doc/reline/face.md

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/reline.

Run tests

Note Please make sure you have libvterm installed for yamatanooroti tests (integration tests).

If you use Homebrew, you can install it by running brew install libvterm.

WITH_VTERM=1 bundle install
WITH_VTERM=1 bundle exec rake test test_yamatanooroti

Releasing

rake release
gh release create vX.Y.Z --generate-notes

License

The gem is available as open source under the terms of the Ruby License.

Acknowledgments for rb-readline

In developing Reline, we have used some of the rb-readline implementation, so this library includes copyright notice, list of conditions and the disclaimer under the 3-Clause BSD License. Reline would never have been developed without rb-readline. Thank you for the tremendous accomplishments.

reline's People

Contributors

acammack-r7 avatar aycabta avatar dependabot[bot] avatar elfham avatar etiennebarrie avatar fnordfish avatar hasumikin avatar hsbt avatar ima1zumi avatar ioquatix avatar jeremyevans avatar jethrodaniel avatar k0kubun avatar ko1 avatar larskanis avatar mame avatar msp-greg avatar nobu avatar olleolleolle avatar osyo-manga avatar otavioschwanck avatar peterzhu2118 avatar richardmcmillen avatar silverphoenix99 avatar sorah avatar sshock avatar st0012 avatar tompng avatar yo4 avatar znz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reline's Issues

Startup error: undefined method `grapheme_clusters' for String

I am getting the following error when trying to start Rails console in a production environment:

[root@ip-172-1-2-51 server]# /usr/local/bin/bundle exec rails console
Loading production environment (Rails 5.2.3)
This version of IRB is drastically different from the previous version.
If you hit any issues, you can use "irb --legacy" to run the old version.
If you want to just erase this message, please use "irb --multiline".
/var/www/server/vendor/bundle/ruby/2.4/gems/reline-0.0.7/lib/reline/line_editor.rb:1020:in `calculate_width': undefined method `grapheme_clusters' for "":String (NoMethodError)
    from /var/www/server/vendor/bundle/ruby/2.4/gems/reline-0.0.7/lib/reline/line_editor.rb:349:in `rerender'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/reline-0.0.7/lib/reline.rb:210:in `inner_readline'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/reline-0.0.7/lib/reline.rb:160:in `readmultiline'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/input-method.rb:259:in `gets'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:518:in `block (2 levels) in eval_input'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:694:in `signal_status'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:517:in `block in eval_input'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:164:in `lex'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:136:in `block (2 levels) in each_top_level_statement'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:133:in `loop'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:133:in `block in each_top_level_statement'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:132:in `catch'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb/ruby-lex.rb:132:in `each_top_level_statement'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:536:in `eval_input'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:471:in `block in run'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:470:in `catch'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:470:in `run'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/irb-1.1.0/lib/irb.rb:399:in `start'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/commands/console/console_command.rb:64:in `start'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/commands/console/console_command.rb:19:in `start'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/commands/console/console_command.rb:96:in `perform'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/command/base.rb:65:in `perform'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/command.rb:46:in `invoke'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/railties-5.2.3/lib/rails/commands.rb:18:in `<main>'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `block in require_with_bootsnap_lfi'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require_with_bootsnap_lfi'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/bootsnap-1.4.5/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `block in require'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257:in `load_dependency'
    from /var/www/server/vendor/bundle/ruby/2.4/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require'
    from bin/rails:4:in `<main>'

IRB seems to work normally locally. Any ideas what might be wrong?

Passing input through with `Open3` to a subprocess using `Reline.readline` crashes

Take the following script named test.rb:

# frozen_string_literal: true

require "open3"

if ENV["SUBPROCESS"]
  if ENV["RELINE"]
    require "reline"
    readline_module = Reline
  else
    require "readline"
    readline_module = Readline
  end

  readline_module.readline("y or n? ")
else
  res, _ = Open3.capture2e({ "SUBPROCESS" => "true" }, "ruby test.rb", stdin_data: "y\n")

  puts res
end

If I run it with ruby test.rb so that it uses the builtin readline, it does what I expect and prints "y or no? y" to the script.

However, if I run it through RELINE=true ruby test.rb so that it uses reline, it prints the following:

$ RELINE=true ruby test.rb 
stty: 'standard input': Inappropriate ioctl for device
stty: 'standard input': Inappropriate ioctl for device
stty: 'standard input': Inappropriate ioctl for device
▽/home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline/ansi.rb:70:in `pos': Illegal seek @ rb_io_tell - <STDOUT> (Errno::ESPIPE)
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline/ansi.rb:70:in `rescue in cursor_pos'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline/ansi.rb:57:in `cursor_pos'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:325:in `may_req_ambiguous_char_width'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:199:in `inner_readline'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:179:in `readline'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/2.6.0/forwardable.rb:230:in `readline'
	from test.rb:14:in `<main>'
/home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline/ansi.rb:59:in `raw': Inappropriate ioctl for device (Errno::ENOTTY)
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline/ansi.rb:59:in `cursor_pos'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:325:in `may_req_ambiguous_char_width'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:199:in `inner_readline'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/reline-0.0.4/lib/reline.rb:179:in `readline'
	from /home/deivid/.rbenv/versions/2.6.5/lib/ruby/2.6.0/forwardable.rb:230:in `readline'
	from test.rb:14:in `<main>'

LineEditor#complete_internal_proc - test_simple_completion, test_completion_encoding issues

I've never really tried to test many encoding issues using MinGW & and a standard EN-US windows system.

Currently, MinGW is failing on TestRelineAsReadline#test_simple_completion. See ruby-loco and ruby/ruby

The issue seems to be in the last line of:
- here -

private def complete_internal_proc(list, is_menu)
preposing, target, postposing = retrieve_completion_block
list = list.select { |i|
if i and i.encoding != Encoding::US_ASCII and i.encoding != @encoding

-Ruby master-

  private def complete_internal_proc(list, is_menu)
    preposing, target, postposing = retrieve_completion_block
    list = list.select { |i|
      if i and not Encoding.compatible?(target.encoding, i.encoding)

Encoding.compatible? has an odd setup for parameters. Instead of passing encodings as above, I tried passing strings, as in:

if i and not Encoding.compatible?(target, i)

the test passes, but the following fails:

TestRelineAsReadline#test_completion_encoding [ruby/test/readline/test_readline.rb:272]:
[Bug #5941].
Encoding::CompatibilityError expected but nothing was raised.

Again, I'm essentially stupid when it comes to encodings...

Character widths in Windows are font dependent

Windows console characters widths depend on the selected font. One such character is the "€". Most fonts treat it as a single width char, but the font "NSimSun" treats it as double size char. See the following screenshot.
image

I entered the characters "€aaa", but the "€" overwrites the first "a", since Reline treats it as single width char.

As a solution I implemented a dynamic character width detection for GNU readline here. It worked pretty well. Is this something you would like to implement in Reline?

escape sequences in prompt does not work

How to reproduce:

require "reline"
Reline.readline("\e[1m;hoge\e[0m;")

expected:

hoge

actual:

^[[1m;hoge\[[0m;

Cause

Reline::LineEditor#render_partial uses Reline::LineEditor#escaped_print internally, but escaped_print force to change "\x1b" to "^[".
so, escape sequences in prompt never work.
Reline::LineEditor#render_partial knows prompt, so use normal output method such as primt for prompt.

Pressing key "€" in irb crashes with RangeError on Windows

With codepage 850 and ruby's default encoding settings irb crashes with the following trace when "€" is entered:

irb(main):001:0> Traceback (most recent call last):
        31: from C:/Ruby27-x64/bin/irb.cmd:31:in `<main>'
        30: from C:/Ruby27-x64/bin/irb.cmd:31:in `load'
        29: from C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
        28: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:398:in `start'
        27: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:469:in `run'
        26: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:469:in `catch'
        25: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:470:in `block in run'
        24: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:535:in `eval_input'
        23: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:134:in `each_top_level_statement'
        22: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:134:in `catch'
        21: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:135:in `block in each_top_level_statement'
        20: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:135:in `loop'
        19: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:138:in `block (2 levels) in each_top_level_statement'
        18: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/ruby-lex.rb:166:in `lex'
        17: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:516:in `block in eval_input'
        16: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:693:in `signal_status'
        15: from C:/Ruby27-x64/lib/ruby/2.7.0/irb.rb:517:in `block (2 levels) in eval_input'
        14: from C:/Ruby27-x64/lib/ruby/2.7.0/irb/input-method.rb:258:in `gets'
        13: from C:/Ruby27-x64/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline'
        12: from C:/Ruby27-x64/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline'
        11: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:170:in `readmultiline'
        10: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:232:in `inner_readline'
         9: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:232:in `loop'
         8: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:233:in `block in inner_readline'
         7: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:262:in `read_io'
         6: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:262:in `loop'
         5: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:303:in `block in read_io'
         4: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:234:in `block (2 levels) in inner_readline'
         3: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:234:in `each'
         2: from C:/Ruby27-x64/lib/ruby/2.7.0/reline.rb:235:in `block (3 levels) in inner_readline'
         1: from C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:829:in `input_key'
C:/Ruby27-x64/lib/ruby/2.7.0/reline/line_editor.rb:768:in `normal_char': 8364 out of char range (RangeError)

This doesn't happen when ruby is called with -Eutf-8 parameter.
RubyInstaller-2.7.0 sets RUBYOPT=-Eutf-8 per default, so that this issue only arises when this default setting is disabled.

Windows / MinGW CI failures in byebug with reline

Thanks for reline!

Although I'm kind of a 'puts' debugger, I've run byebug with reline, and it seems fine.

But, trying to get byebug CI working with reline has been messy. Open3 is used in the test suite.

I tried the following, based on what I saw in the CI tests here:

require "reline"
Reline.send(:remove_const, :IOGate) if Reline.const_defined?(:IOGate)
Reline.const_set :IOGate, Reline::GeneralIO
Reline.core.config.instance_variable_set :@test_mode, true
Reline.core.config.reset

Wondering it you have any thoughts? I don't know either repo that well, so I thought I'd check if it's an easy fix...

JFYI, at present, byebug uses rb-readline for Windows CI.

history_size is set to a boolean value instead of an integer in config.rb

If ~/.inputrc contains the line "set history-size 5000", irb will exit with "false can't be coerced into Integer" after an expression has been entered. The below code in config.rb sets @history_size to false instead of the number 5000.

def bind_variable(name, value)
  case name
  when *VARIABLE_NAMES then
    instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')

As a quick fix I added the below condition to config.rb.

  when 'history-size'
    if value.match?(/\A-?\d+\Z/)
      @history_size = value.to_i
    end

Complex code breaks rendering

  def each_top_level_statement
    initialize_input
    catch(:TERM_INPUT) do
      loop do
        begin
          prompt
          unless l = lex
            throw :TERM_INPUT if @line == ''
          else
            @line_no += l.count("\n")
            next if l == "\n"
            @line.concat l
            if @code_block_open or @ltype or @continue or @indent > 0
              next
            end
          end
          if @line != "\n"
            @line.force_encoding(@io.encoding)
            yield @line, @exp_line_no
          end
          break if @io.eof?
          @line = ''
          @exp_line_no = @line_no

          @indent = 0
        rescue TerminateLineInput
          initialize_input
          prompt
        end
      end
    end
  end

reline handles ^C differently than readline

When user types ^C (ctrl-c) during Readline.readline, SIGINT is sent to the program, which in turn converted to an Interrupt exception. Reline.readline, however, returns a String with "\x03".

By bisecting I suppose this behaviour change was introduced in 8670d33 (#54)

Steps to reproduce:

  1. Start bundle exec bin/example.
  2. Type ^C.
  3. Expect the program to halt.

io-console requires gcc

Before version 0.1, we could install reline (used by irb) without installing tools like gcc and make.

With the new dependency of io-console (#91), installing reline requires additional tools to install. This has impacted our docker image build pipeline and will likely lead to larger image sizes.

This issue is just for awareness in case it was not intentional or others run into it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.