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/