[ruby/reline] Support bracketed paste mode
https://github.com/ruby/reline/commit/d1a6869322
This commit is contained in:
parent
7624f52757
commit
c2bd5b84d0
@ -44,6 +44,7 @@ module Reline
|
|||||||
self.output = STDOUT
|
self.output = STDOUT
|
||||||
yield self
|
yield self
|
||||||
@completion_quote_character = nil
|
@completion_quote_character = nil
|
||||||
|
@bracketed_paste_finished = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def encoding
|
def encoding
|
||||||
@ -243,6 +244,10 @@ module Reline
|
|||||||
line_editor.input_key(c)
|
line_editor.input_key(c)
|
||||||
line_editor.rerender
|
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?
|
if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
|
||||||
prev_pasting_state = false
|
prev_pasting_state = false
|
||||||
@ -275,8 +280,13 @@ module Reline
|
|||||||
buffer = []
|
buffer = []
|
||||||
loop do
|
loop do
|
||||||
c = Reline::IOGate.getc
|
c = Reline::IOGate.getc
|
||||||
|
if c == -1
|
||||||
|
result = :unmatched
|
||||||
|
@bracketed_paste_finished = true
|
||||||
|
else
|
||||||
buffer << c
|
buffer << c
|
||||||
result = key_stroke.match_status(buffer)
|
result = key_stroke.match_status(buffer)
|
||||||
|
end
|
||||||
case result
|
case result
|
||||||
when :matched
|
when :matched
|
||||||
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
require 'io/console'
|
require 'io/console'
|
||||||
|
require 'timeout'
|
||||||
|
|
||||||
class Reline::ANSI
|
class Reline::ANSI
|
||||||
def self.encoding
|
def self.encoding
|
||||||
@ -67,7 +68,7 @@ class Reline::ANSI
|
|||||||
end
|
end
|
||||||
|
|
||||||
@@buf = []
|
@@buf = []
|
||||||
def self.getc
|
def self.inner_getc
|
||||||
unless @@buf.empty?
|
unless @@buf.empty?
|
||||||
return @@buf.shift
|
return @@buf.shift
|
||||||
end
|
end
|
||||||
@ -80,8 +81,48 @@ class Reline::ANSI
|
|||||||
nil
|
nil
|
||||||
end
|
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?
|
def self.in_pasting?
|
||||||
not Reline::IOGate.empty_buffer?
|
@@in_bracketed_paste_mode or (not Reline::IOGate.empty_buffer?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.empty_buffer?
|
def self.empty_buffer?
|
||||||
|
@ -37,6 +37,7 @@ class Reline::Config
|
|||||||
vi-cmd-mode-icon
|
vi-cmd-mode-icon
|
||||||
vi-ins-mode-icon
|
vi-ins-mode-icon
|
||||||
emacs-mode-string
|
emacs-mode-string
|
||||||
|
enable-bracketed-paste
|
||||||
}
|
}
|
||||||
VARIABLE_NAME_SYMBOLS = VARIABLE_NAMES.map { |v| :"#{v.tr(?-, ?_)}" }
|
VARIABLE_NAME_SYMBOLS = VARIABLE_NAMES.map { |v| :"#{v.tr(?-, ?_)}" }
|
||||||
VARIABLE_NAME_SYMBOLS.each do |v|
|
VARIABLE_NAME_SYMBOLS.each do |v|
|
||||||
|
@ -423,6 +423,24 @@ begin
|
|||||||
EOC
|
EOC
|
||||||
end
|
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)
|
private def write_inputrc(content)
|
||||||
File.open(@inputrc_file, 'w') do |f|
|
File.open(@inputrc_file, 'w') do |f|
|
||||||
f.write content
|
f.write content
|
||||||
|
Loading…
x
Reference in New Issue
Block a user