summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/reline.rb77
-rw-r--r--lib/reline/key_stroke.rb77
2 files changed, 77 insertions, 77 deletions
diff --git a/lib/reline.rb b/lib/reline.rb
index cafaf578a0..49e99d2d65 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -22,6 +22,7 @@ module Reline
CursorPos = Struct.new(:x, :y)
@@config = Reline::Config.new
+ @@key_stroke = Reline::KeyStroke.new(@@config)
@@line_editor = Reline::LineEditor.new(@@config)
@@ambiguous_width = nil
@@ -331,10 +332,9 @@ module Reline
end
end
- key_stroke = Reline::KeyStroke.new(@@config)
begin
loop do
- key_stroke.read_io(@@config.keyseq_timeout) { |inputs|
+ read_io(@@config.keyseq_timeout) { |inputs|
inputs.each { |c|
@@line_editor.input_key(c)
@@line_editor.rerender
@@ -353,6 +353,79 @@ module Reline
Reline::IOGate.deprep(otio)
end
+ # Keystrokes of GNU Readline will timeout it with the specification of
+ # "keyseq-timeout" when waiting for the 2nd character after the 1st one.
+ # If the 2nd character comes after 1st ESC without timeout it has a
+ # meta-property of meta-key to discriminate modified key with meta-key
+ # from multibyte characters that come with 8th bit on.
+ #
+ # GNU Readline will wait for the 2nd character with "keyseq-timeout"
+ # milli-seconds but wait forever after 3rd characters.
+ def read_io(keyseq_timeout, &block)
+ buffer = []
+ loop do
+ c = Reline::IOGate.getc
+ buffer << c
+ result = @@key_stroke.match_status(buffer)
+ case result
+ when :matched
+ block.(@@key_stroke.expand(buffer).map{ |c| Reline::Key.new(c, c, false) })
+ break
+ when :matching
+ if buffer.size == 1
+ begin
+ succ_c = nil
+ Timeout.timeout(keyseq_timeout / 1000.0) {
+ succ_c = Reline::IOGate.getc
+ }
+ rescue Timeout::Error # cancel matching only when first byte
+ block.([Reline::Key.new(c, c, false)])
+ break
+ else
+ if @@key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
+ if c == "\e".ord
+ block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
+ else
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
+ end
+ break
+ else
+ Reline::IOGate.ungetc(succ_c)
+ end
+ end
+ end
+ when :unmatched
+ if buffer.size == 1 and c == "\e".ord
+ read_escaped_key(keyseq_timeout, buffer, block)
+ else
+ block.(buffer.map{ |c| Reline::Key.new(c, c, false) })
+ end
+ break
+ end
+ end
+ end
+
+ def read_escaped_key(keyseq_timeout, buffer, block)
+ begin
+ escaped_c = nil
+ Timeout.timeout(keyseq_timeout / 1000.0) {
+ escaped_c = Reline::IOGate.getc
+ }
+ rescue Timeout::Error # independent ESC
+ block.([Reline::Key.new(c, c, false)])
+ else
+ if escaped_c.nil?
+ block.([Reline::Key.new(c, c, false)])
+ elsif escaped_c >= 128 # maybe, first byte of multi byte
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
+ elsif escaped_c == "\e".ord # escape twice
+ block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
+ else
+ block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
+ end
+ end
+ end
+
def may_req_ambiguous_char_width
@@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
return if @@ambiguous_width
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb
index 08c00625ba..2f5415ef7e 100644
--- a/lib/reline/key_stroke.rb
+++ b/lib/reline/key_stroke.rb
@@ -15,79 +15,6 @@ class Reline::KeyStroke
@config = config
end
- # Keystrokes of GNU Readline will timeout it with the specification of
- # "keyseq-timeout" when waiting for the 2nd character after the 1st one.
- # If the 2nd character comes after 1st ESC without timeout it has a
- # meta-property of meta-key to discriminate modified key with meta-key
- # from multibyte characters that come with 8th bit on.
- #
- # GNU Readline will wait for the 2nd character with "keyseq-timeout"
- # milli-seconds but wait forever after 3rd characters.
- def read_io(keyseq_timeout, &block)
- buffer = []
- loop do
- c = Reline::IOGate.getc
- buffer << c
- result = match_status(buffer)
- case result
- when :matched
- block.(expand(buffer).map{ |c| Reline::Key.new(c, c, false) })
- break
- when :matching
- if buffer.size == 1
- begin
- succ_c = nil
- Timeout.timeout(keyseq_timeout / 1000.0) {
- succ_c = Reline::IOGate.getc
- }
- rescue Timeout::Error # cancel matching only when first byte
- block.([Reline::Key.new(c, c, false)])
- break
- else
- if match_status(buffer.dup.push(succ_c)) == :unmatched
- if c == "\e".ord
- block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
- else
- block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
- end
- break
- else
- Reline::IOGate.ungetc(succ_c)
- end
- end
- end
- when :unmatched
- if buffer.size == 1 and c == "\e".ord
- read_escaped_key(keyseq_timeout, buffer, block)
- else
- block.(buffer.map{ |c| Reline::Key.new(c, c, false) })
- end
- break
- end
- end
- end
-
- def read_escaped_key(keyseq_timeout, buffer, block)
- begin
- escaped_c = nil
- Timeout.timeout(keyseq_timeout / 1000.0) {
- escaped_c = Reline::IOGate.getc
- }
- rescue Timeout::Error # independent ESC
- block.([Reline::Key.new(c, c, false)])
- else
- if escaped_c.nil?
- block.([Reline::Key.new(c, c, false)])
- elsif escaped_c >= 128 # maybe, first byte of multi byte
- block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
- elsif escaped_c == "\e".ord # escape twice
- block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
- else
- block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
- end
- end
- end
-
def match_status(input)
key_mapping.keys.select { |lhs|
lhs.start_with? input
@@ -104,8 +31,6 @@ class Reline::KeyStroke
}
end
- private
-
def expand(input)
lhs = key_mapping.keys.select { |lhs| input.start_with? lhs }.sort_by(&:size).reverse.first
return input unless lhs
@@ -120,6 +45,8 @@ class Reline::KeyStroke
end
end
+ private
+
def key_mapping
@config.key_bindings
end