summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2020-11-26 19:13:34 +0900
committeraycabta <aycabta@gmail.com>2020-12-05 02:58:59 +0900
commitc2bd5b84d06f5e74afce72e4e4af06d7176453b2 (patch)
tree1dd5c60a940e3132410b2e01e4f2a4b78d458c11 /lib
parent7624f5275713c3dd2d551058355d9a4544c2ef53 (diff)
[ruby/reline] Support bracketed paste mode
https://github.com/ruby/reline/commit/d1a6869322
Diffstat (limited to 'lib')
-rw-r--r--lib/reline.rb14
-rw-r--r--lib/reline/ansi.rb45
-rw-r--r--lib/reline/config.rb1
3 files changed, 56 insertions, 4 deletions
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|