From c2bd5b84d06f5e74afce72e4e4af06d7176453b2 Mon Sep 17 00:00:00 2001 From: aycabta Date: Thu, 26 Nov 2020 19:13:34 +0900 Subject: [ruby/reline] Support bracketed paste mode https://github.com/ruby/reline/commit/d1a6869322 --- lib/reline.rb | 14 ++++++++++++-- lib/reline/ansi.rb | 45 +++++++++++++++++++++++++++++++++++++++++++-- lib/reline/config.rb | 1 + 3 files changed, 56 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/reline.rb b/lib/reline.rb index 2862f5bc64..6a5f9b2390 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -44,6 +44,7 @@ module Reline self.output = STDOUT yield self @completion_quote_character = nil + @bracketed_paste_finished = false end def encoding @@ -243,6 +244,10 @@ module Reline 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 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 f11dbb80f4..0b1a7e1745 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -1,4 +1,5 @@ require 'io/console' +require 'timeout' class Reline::ANSI def self.encoding @@ -67,7 +68,7 @@ class Reline::ANSI end @@buf = [] - def self.getc + def self.inner_getc unless @@buf.empty? return @@buf.shift end @@ -80,8 +81,48 @@ class Reline::ANSI 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 370d100414..c66810d30e 100644 --- a/lib/reline/config.rb +++ b/lib/reline/config.rb @@ -37,6 +37,7 @@ class Reline::Config 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| -- cgit v1.2.3