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

ruby-changes:63933

From: aycabta <ko1@a...>
Date: Sat, 5 Dec 2020 03:09:32 +0900 (JST)
Subject: [ruby-changes:63933] 55cc397a87 (master): [ruby/reline] Suppress callbacks in pasting

https://git.ruby-lang.org/ruby.git/commit/?id=55cc397a87

From 55cc397a87dbfaa5d95168ce05f9a0d20339c657 Mon Sep 17 00:00:00 2001
From: aycabta <aycabta@g...>
Date: Tue, 20 Oct 2020 08:39:12 +0900
Subject: [ruby/reline] Suppress callbacks in pasting

IRB uses Reline's 3 dynamic real-time callbacks with calling Ripper;
output_modifier_proc, prompt_proc, and auto_indent_proc. These processing
times make the paste time too long.

https://github.com/ruby/reline/commit/beec3399a8

diff --git a/lib/reline.rb b/lib/reline.rb
index eb18d0d..2862f5b 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -235,13 +235,19 @@ module Reline https://github.com/ruby/ruby/blob/trunk/lib/reline.rb#L235
       line_editor.rerender
 
       begin
+        prev_pasting_state = false
         loop do
+          prev_pasting_state = Reline::IOGate.in_pasting?
           read_io(config.keyseq_timeout) { |inputs|
             inputs.each { |c|
               line_editor.input_key(c)
               line_editor.rerender
             }
           }
+          if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
+            prev_pasting_state = false
+            line_editor.rerender_all
+          end
           break if line_editor.finished?
         end
         Reline::IOGate.move_cursor_column(0)
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index 80fccd7..f11dbb8 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -80,6 +80,22 @@ class Reline::ANSI https://github.com/ruby/ruby/blob/trunk/lib/reline/ansi.rb#L80
     nil
   end
 
+  def self.in_pasting?
+    not Reline::IOGate.empty_buffer?
+  end
+
+  def self.empty_buffer?
+    unless @@buf.empty?
+      return false
+    end
+    rs, = IO.select([@@input], [], [], 0.00001)
+    if rs and rs[0]
+      false
+    else
+      true
+    end
+  end
+
   def self.ungetc(c)
     @@buf.unshift(c)
   end
diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb
index 85f1f13..3b40888 100644
--- a/lib/reline/general_io.rb
+++ b/lib/reline/general_io.rb
@@ -67,6 +67,10 @@ class Reline::GeneralIO https://github.com/ruby/ruby/blob/trunk/lib/reline/general_io.rb#L67
   def self.set_winch_handler(&handler)
   end
 
+  def self.in_pasting?
+    false
+  end
+
   def self.prep
   end
 
diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index e5ecc8b..5558a1b 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -56,6 +56,14 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L56
     reset_variables(encoding: encoding)
   end
 
+  def simplified_rendering?
+    if finished?
+      false
+    else
+      not @rerender_all and not finished? and Reline::IOGate.in_pasting?
+    end
+  end
+
   private def check_multiline_prompt(buffer, prompt)
     if @vi_arg
       prompt = "(arg: #{@vi_arg}) "
@@ -66,6 +74,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L74
     else
       prompt = @prompt
     end
+    return [prompt, calculate_width(prompt, true), [prompt] * buffer.size] if simplified_rendering?
     if @prompt_proc
       prompt_list = @prompt_proc.(buffer)
       prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
@@ -297,6 +306,11 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L306
     @byte_pointer = new_byte_pointer
   end
 
+  def rerender_all
+    @rerender_all = true
+    rerender
+  end
+
   def rerender
     return if @line.nil?
     if @menu_info
@@ -523,6 +537,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L537
       end
     end
     Reline::IOGate.erase_after_cursor
+    Reline::IOGate.move_cursor_column(0)
     if with_control
       # Just after rendring, so the cursor is on the last line.
       if finished?
@@ -537,7 +552,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L552
   end
 
   private def modify_lines(before)
-    return before if before.nil? || before.empty?
+    return before if before.nil? || before.empty? || simplified_rendering?
 
     if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: finished?)
       after.lines("\n").map { |l| l.chomp('') }
@@ -836,7 +851,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L851
     unless completion_occurs
       @completion_state = CompletionState::NORMAL
     end
-    if @is_multiline and @auto_indent_proc
+    if @is_multiline and @auto_indent_proc and not simplified_rendering?
       process_auto_indent
     end
   end
@@ -1038,6 +1053,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L1053
 
   def finish
     @finished = true
+    @rerender_all = true
     @config.reset
   end
 
diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb
index 2a406e3..b09290b 100644
--- a/lib/reline/windows.rb
+++ b/lib/reline/windows.rb
@@ -199,6 +199,20 @@ class Reline::Windows https://github.com/ruby/ruby/blob/trunk/lib/reline/windows.rb#L199
     @@output_buf.unshift(c)
   end
 
+  def self.in_pasting?
+    not self.empty_buffer?
+  end
+
+  def self.empty_buffer?
+    if not @@input_buf.empty?
+      false
+    elsif @@kbhit.call == 0
+      true
+    else
+      false
+    end
+  end
+
   def self.get_screen_size
     csbi = 0.chr * 22
     @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
-- 
cgit v0.10.2


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

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