[前][次][番号順一覧][スレッド一覧]

ruby-changes:73669

From: tompng <ko1@a...>
Date: Thu, 22 Sep 2022 00:37:50 +0900 (JST)
Subject: [ruby-changes:73669] 9f68687879 (master): [ruby/irb] Scan every single characters in IRB::Color.scan

https://git.ruby-lang.org/ruby.git/commit/?id=9f68687879

From 9f686878794291b088d07866c00f8056a0c7dec7 Mon Sep 17 00:00:00 2001
From: tompng <tomoyapenguin@g...>
Date: Sun, 7 Aug 2022 20:58:17 +0900
Subject: [ruby/irb] Scan every single characters in IRB::Color.scan

https://github.com/ruby/irb/commit/d14e56a65d
---
 lib/irb/color.rb       | 55 +++++++++++++++++++++++++-------------------------
 test/irb/test_color.rb |  2 ++
 2 files changed, 30 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: https://github.com/ruby/ruby/blob/trunk/lib/irb/color.rb#L128
 
         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: https://github.com/ruby/ruby/blob/trunk/lib/irb/color.rb#L151
               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: https://github.com/ruby/ruby/blob/trunk/lib/irb/color.rb#L166
       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
diff --git a/test/irb/test_color.rb b/test/irb/test_color.rb
index 6ad64a0ae2..73e9b389c2 100644
--- a/test/irb/test_color.rb
+++ b/test/irb/test_color.rb
@@ -88,6 +88,8 @@ module TestIRB https://github.com/ruby/ruby/blob/trunk/test/irb/test_color.rb#L88
         "foo(*%W(bar))" => "foo(*#{RED}#{BOLD}%W(#{CLEAR}#{RED}bar#{CLEAR}#{RED}#{BOLD})#{CLEAR})",
         "$stdout" => "#{GREEN}#{BOLD}$stdout#{CLEAR}",
         "__END__" => "#{GREEN}__END__#{CLEAR}",
+        "foo\n__END__\nbar" => "foo\n#{GREEN}__END__#{CLEAR}\nbar",
+        "foo\n<<A\0\0bar\nA\nbaz" => "foo\n#{RED}<<A#{CLEAR}^@^@bar\n#{RED}A#{CLEAR}\nbaz",
       }
 
       # specific to Ruby 2.7+
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]