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

ruby-changes:63949

From: aycabta <ko1@a...>
Date: Sat, 5 Dec 2020 03:09:47 +0900 (JST)
Subject: [ruby-changes:63949] c2bd5b84d0 (master): [ruby/reline] Support bracketed paste mode

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

From c2bd5b84d06f5e74afce72e4e4af06d7176453b2 Mon Sep 17 00:00:00 2001
From: aycabta <aycabta@g...>
Date: Thu, 26 Nov 2020 19:13:34 +0900
Subject: [ruby/reline] Support bracketed paste mode

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

diff --git a/lib/reline.rb b/lib/reline.rb
index 2862f5b..6a5f9b2 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -44,6 +44,7 @@ module Reline https://github.com/ruby/ruby/blob/trunk/lib/reline.rb#L44
       self.output = STDOUT
       yield self
       @completion_quote_character = nil
+      @bracketed_paste_finished = false
     end
 
     def encoding
@@ -243,6 +244,10 @@ module Reline https://github.com/ruby/ruby/blob/trunk/lib/reline.rb#L244
               line_editor.input_key(c)
               line_editor.rerender
             }
+            if @bracketed_paste_finished
+              line_editor.rerender_all
+              @bracketed_paste_finished = false
+            end
           }
           if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
             prev_pasting_state = false
@@ -275,8 +280,13 @@ module Reline https://github.com/ruby/ruby/blob/trunk/lib/reline.rb#L280
       buffer = []
       loop do
         c = Reline::IOGate.getc
-        buffer << c
-        result = key_stroke.match_status(buffer)
+        if c == -1
+          result = :unmatched
+          @bracketed_paste_finished = true
+        else
+          buffer << c
+          result = key_stroke.match_status(buffer)
+        end
         case result
         when :matched
           expanded = key_stroke.expand(buffer).map{ |expanded_c|
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index f11dbb8..0b1a7e1 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -1,4 +1,5 @@ https://github.com/ruby/ruby/blob/trunk/lib/reline/ansi.rb#L1
 require 'io/console'
+require 'timeout'
 
 class Reline::ANSI
   def self.encoding
@@ -67,7 +68,7 @@ class Reline::ANSI https://github.com/ruby/ruby/blob/trunk/lib/reline/ansi.rb#L68
   end
 
   @@buf = []
-  def self.getc
+  def self.inner_getc
     unless @@buf.empty?
       return @@buf.shift
     end
@@ -80,8 +81,48 @@ class Reline::ANSI https://github.com/ruby/ruby/blob/trunk/lib/reline/ansi.rb#L81
     nil
   end
 
+  @@in_bracketed_paste_mode = false
+  START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT)
+  END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT)
+  def self.getc_with_bracketed_paste
+    buffer = String.new(encoding: Encoding::ASCII_8BIT)
+    buffer << inner_getc
+    while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do
+      if START_BRACKETED_PASTE == buffer
+        @@in_bracketed_paste_mode = true
+        return inner_getc
+      elsif END_BRACKETED_PASTE == buffer
+        @@in_bracketed_paste_mode = false
+        ungetc(-1)
+        return inner_getc
+      end
+      begin
+        succ_c = nil
+        Timeout.timeout(Reline.core.config.keyseq_timeout * 100) {
+          succ_c = inner_getc
+        }
+      rescue Timeout::Error
+        break
+      else
+        buffer << succ_c
+      end
+    end
+    buffer.bytes.reverse_each do |ch|
+      ungetc ch
+    end
+    inner_getc
+  end
+
+  def self.getc
+    if Reline.core.config.enable_bracketed_paste
+      getc_with_bracketed_paste
+    else
+      inner_getc
+    end
+  end
+
   def self.in_pasting?
-    not Reline::IOGate.empty_buffer?
+    @@in_bracketed_paste_mode or (not Reline::IOGate.empty_buffer?)
   end
 
   def self.empty_buffer?
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index 370d100..c66810d 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -37,6 +37,7 @@ class Reline::Config https://github.com/ruby/ruby/blob/trunk/lib/reline/config.rb#L37
     vi-cmd-mode-icon
     vi-ins-mode-icon
     emacs-mode-string
+    enable-bracketed-paste
   }
   VARIABLE_NAME_SYMBOLS = VARIABLE_NAMES.map { |v| :"#{v.tr(?-, ?_)}" }
   VARIABLE_NAME_SYMBOLS.each do |v|
diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb
index b82e30a..7c87d95 100644
--- a/test/reline/yamatanooroti/test_rendering.rb
+++ b/test/reline/yamatanooroti/test_rendering.rb
@@ -423,6 +423,24 @@ begin https://github.com/ruby/ruby/blob/trunk/test/reline/yamatanooroti/test_rendering.rb#L423
       EOC
     end
 
+    def test_enable_bracketed_paste
+      write_inputrc <<~LINES
+        set enable-bracketed-paste on
+      LINES
+      start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl}, startup_message: 'Multiline REPL.')
+      write("\e[200~,")
+      write("def hoge\n  3\nend\n")
+      write("\e[200~.")
+      close
+      assert_screen(<<~EOC)
+        prompt> def hoge
+        prompt>   3
+        prompt> end
+        => :hoge
+        prompt>
+      EOC
+    end
+
     private def write_inputrc(content)
       File.open(@inputrc_file, 'w') do |f|
         f.write content
-- 
cgit v0.10.2


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

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