mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[ruby/reline] Fixed Ctrl+Enter key in Windows.
https://github.com/ruby/reline/commit/0c38e39023
This commit is contained in:
parent
46c6da9c37
commit
5b9f3ed326
2 changed files with 110 additions and 39 deletions
|
@ -181,47 +181,38 @@ class Reline::Windows
|
|||
name =~ /(msys-|cygwin-).*-pty/ ? true : false
|
||||
end
|
||||
|
||||
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
||||
char = char_code.chr(Encoding::UTF_8)
|
||||
if char_code == 0x0D and control_key_state.anybits?(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | SHIFT_PRESSED)
|
||||
KEY_MAP = [
|
||||
# It's treated as Meta+Enter on Windows.
|
||||
@@output_buf.push("\e".ord)
|
||||
@@output_buf.push(char_code)
|
||||
elsif char_code == 0x20 and control_key_state.anybits?(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
|
||||
[ { control_keys: :CTRL, virtual_key_code: 0x0D }, "\e\r".bytes ],
|
||||
[ { control_keys: :SHIFT, virtual_key_code: 0x0D }, "\e\r".bytes ],
|
||||
|
||||
# It's treated as Meta+Space on Windows.
|
||||
@@output_buf.push("\e".ord)
|
||||
@@output_buf.push(char_code)
|
||||
elsif control_key_state.anybits?(ENHANCED_KEY)
|
||||
case virtual_key_code # Emulate getwch() key sequences.
|
||||
when VK_END
|
||||
@@output_buf.push(0, 79)
|
||||
when VK_HOME
|
||||
@@output_buf.push(0, 71)
|
||||
when VK_LEFT
|
||||
@@output_buf.push(0, 75)
|
||||
when VK_UP
|
||||
@@output_buf.push(0, 72)
|
||||
when VK_RIGHT
|
||||
@@output_buf.push(0, 77)
|
||||
when VK_DOWN
|
||||
@@output_buf.push(0, 80)
|
||||
when VK_DELETE
|
||||
@@output_buf.push(0, 83)
|
||||
when VK_RETURN
|
||||
@@output_buf.push(char_code) # must be 0x0D
|
||||
when VK_DIVIDE
|
||||
@@output_buf.push(char_code)
|
||||
end
|
||||
elsif char_code == 0 and control_key_state != 0
|
||||
# unknown
|
||||
else
|
||||
case virtual_key_code
|
||||
when VK_RETURN
|
||||
@@output_buf.push("\n".ord)
|
||||
else
|
||||
@@output_buf.concat(char.bytes)
|
||||
end
|
||||
[ { control_keys: :CTRL, char_code: 0x20 }, "\e ".bytes ],
|
||||
|
||||
# Emulate getwch() key sequences.
|
||||
[ { control_keys: [], virtual_key_code: VK_UP }, [0, 72] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_DOWN }, [0, 80] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_RIGHT }, [0, 77] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_LEFT }, [0, 75] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_DELETE }, [0, 83] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_HOME }, [0, 71] ],
|
||||
[ { control_keys: [], virtual_key_code: VK_END }, [0, 79] ],
|
||||
]
|
||||
|
||||
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
||||
|
||||
key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
|
||||
|
||||
match = KEY_MAP.find { |args,| key.matches?(**args) }
|
||||
unless match.nil?
|
||||
@@output_buf.concat(match.last)
|
||||
return
|
||||
end
|
||||
|
||||
# no char, only control keys
|
||||
return if key.char_code == 0 and key.control_keys.any?
|
||||
|
||||
@@output_buf.concat(key.char.bytes)
|
||||
end
|
||||
|
||||
def self.check_input_event
|
||||
|
@ -362,4 +353,43 @@ class Reline::Windows
|
|||
def self.deprep(otio)
|
||||
# do nothing
|
||||
end
|
||||
|
||||
class KeyEventRecord
|
||||
|
||||
attr_reader :virtual_key_code, :char_code, :control_key_state, :control_keys
|
||||
|
||||
def initialize(virtual_key_code, char_code, control_key_state)
|
||||
@virtual_key_code = virtual_key_code
|
||||
@char_code = char_code
|
||||
@control_key_state = control_key_state
|
||||
@enhanced = control_key_state & ENHANCED_KEY != 0
|
||||
|
||||
(@control_keys = []).tap do |control_keys|
|
||||
# symbols must be sorted to make comparison is easier later on
|
||||
control_keys << :ALT if control_key_state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) != 0
|
||||
control_keys << :CTRL if control_key_state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) != 0
|
||||
control_keys << :SHIFT if control_key_state & SHIFT_PRESSED != 0
|
||||
end.freeze
|
||||
end
|
||||
|
||||
def char
|
||||
@char_code.chr(Encoding::UTF_8)
|
||||
end
|
||||
|
||||
def enhanced?
|
||||
@enhanced
|
||||
end
|
||||
|
||||
# Verifies if the arguments match with this key event.
|
||||
# Nil arguments are ignored, but at least one must be passed as non-nil.
|
||||
# To verify that no control keys were pressed, pass an empty array: `control_keys: []`.
|
||||
def matches?(control_keys: nil, virtual_key_code: nil, char_code: nil)
|
||||
raise ArgumentError, 'No argument was passed to match key event' if control_keys.nil? && virtual_key_code.nil? && char_code.nil?
|
||||
|
||||
(control_keys.nil? || [*control_keys].sort == @control_keys) &&
|
||||
(virtual_key_code.nil? || @virtual_key_code == virtual_key_code) &&
|
||||
(char_code.nil? || char_code == @char_code)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
41
test/reline/windows/test_key_event_record.rb
Normal file
41
test/reline/windows/test_key_event_record.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
require_relative '../helper'
|
||||
require 'reline/windows'
|
||||
|
||||
class Reline::Windows
|
||||
class KeyEventRecord::Test < Reline::TestCase
|
||||
|
||||
def setup
|
||||
# Ctrl+A
|
||||
@key = Reline::Windows::KeyEventRecord.new(0x41, 1, Reline::Windows::LEFT_CTRL_PRESSED)
|
||||
end
|
||||
|
||||
def test_matches__with_no_arguments_raises_error
|
||||
assert_raises(ArgumentError) { @key.matches? }
|
||||
end
|
||||
|
||||
def test_matches_char_code
|
||||
assert_true @key.matches?(char_code: 0x1)
|
||||
end
|
||||
|
||||
def test_matches_virtual_key_code
|
||||
assert_true @key.matches?(virtual_key_code: 0x41)
|
||||
end
|
||||
|
||||
def test_matches_control_keys
|
||||
assert_true @key.matches?(control_keys: :CTRL)
|
||||
end
|
||||
|
||||
def test_doesnt_match_alt
|
||||
assert_false @key.matches?(control_keys: :ALT)
|
||||
end
|
||||
|
||||
def test_doesnt_match_empty_control_key
|
||||
assert_false @key.matches?(control_keys: [])
|
||||
end
|
||||
|
||||
def test_matches_control_keys_and_virtual_key_code
|
||||
assert_true @key.matches?(control_keys: :CTRL, virtual_key_code: 0x41)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue