[ruby/reline] Support bracketed paste mode

https://github.com/ruby/reline/commit/d1a6869322
This commit is contained in:
aycabta 2020-11-26 19:13:34 +09:00
parent 7624f52757
commit c2bd5b84d0
4 changed files with 74 additions and 4 deletions

View File

@ -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|

View File

@ -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?

View File

@ -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|

View File

@ -423,6 +423,24 @@ begin
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