aboutsummaryrefslogtreecommitdiffstats
path: root/lib/irb/color.rb
diff options
context:
space:
mode:
authortompng <tomoyapenguin@gmail.com>2022-08-07 20:58:17 +0900
committergit <svn-admin@ruby-lang.org>2022-09-22 00:37:38 +0900
commit9f686878794291b088d07866c00f8056a0c7dec7 (patch)
tree79a0aefe7f6c578cf4aec23dea398a56b38de311 /lib/irb/color.rb
parent2c6fdc4d65af035769e969dbe5d5718e859973d3 (diff)
downloadruby-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.rb55
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