diff options
author | tompng <tomoyapenguin@gmail.com> | 2022-08-07 20:58:17 +0900 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2022-09-22 00:37:38 +0900 |
commit | 9f686878794291b088d07866c00f8056a0c7dec7 (patch) | |
tree | 79a0aefe7f6c578cf4aec23dea398a56b38de311 /lib/irb/color.rb | |
parent | 2c6fdc4d65af035769e969dbe5d5718e859973d3 (diff) | |
download | ruby-9f686878794291b088d07866c00f8056a0c7dec7.tar.gz |
[ruby/irb] Scan every single characters in IRB::Color.scan
https://github.com/ruby/irb/commit/d14e56a65d
Diffstat (limited to 'lib/irb/color.rb')
-rw-r--r-- | lib/irb/color.rb | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/lib/irb/color.rb b/lib/irb/color.rb index 8307af25a9..401966d181 100644 --- a/lib/irb/color.rb +++ b/lib/irb/color.rb @@ -128,10 +128,14 @@ module IRB # :nodoc: symbol_state = SymbolState.new colored = +'' - length = 0 - end_seen = false scan(code, allow_last_error: !complete) do |token, str, expr| + # handle uncolorable code + if token.nil? + colored << Reline::Unicode.escape_for_print(str) + next + end + # IRB::ColorPrinter skips colorizing fragments with any invalid token if ignore_error && ERROR_TOKENS.include?(token) return Reline::Unicode.escape_for_print(code) @@ -147,15 +151,7 @@ module IRB # :nodoc: colored << line end end - length += str.bytesize - end_seen = true if token == :on___end__ - end - - # give up colorizing incomplete Ripper tokens - unless end_seen or length == code.bytesize - return Reline::Unicode.escape_for_print(code) end - colored end @@ -170,33 +166,38 @@ module IRB # :nodoc: end def scan(code, allow_last_error:) - pos = [1, 0] - verbose, $VERBOSE = $VERBOSE, nil RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no| lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no) + byte_pos = 0 + line_positions = [0] + inner_code.lines.each do |line| + line_positions << line_positions.last + line.bytesize + end + + on_scan = proc do |elem| + str = elem.tok + start_pos = line_positions[elem.pos[0] - 1] + elem.pos[1] + end_pos = start_pos + str.bytesize + next if start_pos < byte_pos + + yield(nil, inner_code.byteslice(byte_pos...start_pos), nil) if byte_pos < start_pos + yield(elem.event, str, elem.state) + byte_pos = end_pos + end + if lexer.respond_to?(:scan) # Ruby 2.7+ lexer.scan.each do |elem| - str = elem.tok next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message - next if ([elem.pos[0], elem.pos[1] + str.bytesize] <=> pos) <= 0 - - str.each_line do |line| - if line.end_with?("\n") - pos[0] += 1 - pos[1] = 0 - else - pos[1] += line.bytesize - end - end - - yield(elem.event, str, elem.state) + on_scan.call(elem) end else - lexer.parse.each do |elem| - yield(elem.event, elem.tok, elem.state) + lexer.parse.sort_by(&:pos).each do |elem| + on_scan.call(elem) end end + # yield uncolorable DATA section + yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize end ensure $VERBOSE = verbose |