reline 0.0.1 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/lib/reline.rb +329 -334
- data/lib/reline/ansi.rb +28 -11
- data/lib/reline/config.rb +4 -5
- data/lib/reline/general_io.rb +4 -1
- data/lib/reline/key_actor/vi_command.rb +1 -1
- data/lib/reline/key_actor/vi_insert.rb +1 -1
- data/lib/reline/key_stroke.rb +1 -1
- data/lib/reline/line_editor.rb +181 -76
- data/lib/reline/unicode/east_asian_width.rb +1 -1
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +109 -65
- metadata +4 -4
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -9,49 +9,65 @@ class Reline::Windows
|
|
9
9
|
[224, 83] => :key_delete, # Del
|
10
10
|
[224, 71] => :ed_move_to_beg, # Home
|
11
11
|
[224, 79] => :ed_move_to_end, # End
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
12
|
+
[ 0, 41] => :ed_unassigned, # input method on/off
|
13
|
+
[ 0, 72] => :ed_prev_history, # ↑
|
14
|
+
[ 0, 80] => :ed_next_history, # ↓
|
15
|
+
[ 0, 77] => :ed_next_char, # →
|
16
|
+
[ 0, 75] => :ed_prev_char, # ←
|
17
|
+
[ 0, 83] => :key_delete, # Del
|
18
|
+
[ 0, 71] => :ed_move_to_beg, # Home
|
19
|
+
[ 0, 79] => :ed_move_to_end # End
|
20
|
+
}
|
21
|
+
|
22
|
+
if defined? JRUBY_VERSION
|
23
|
+
require 'win32api'
|
24
|
+
else
|
25
|
+
class Win32API
|
26
|
+
DLL = {}
|
27
|
+
TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG}
|
28
|
+
POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
|
29
|
+
|
30
|
+
WIN32_TYPES = "VPpNnLlIi"
|
31
|
+
DL_TYPES = "0SSI"
|
32
|
+
|
33
|
+
def initialize(dllname, func, import, export = "0", calltype = :stdcall)
|
34
|
+
@proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
|
35
|
+
import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]}
|
36
|
+
export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
|
37
|
+
calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
|
38
|
+
|
39
|
+
handle = DLL[dllname] ||=
|
40
|
+
begin
|
41
|
+
Fiddle.dlopen(dllname)
|
42
|
+
rescue Fiddle::DLError
|
43
|
+
raise unless File.extname(dllname).empty?
|
44
|
+
Fiddle.dlopen(dllname + ".dll")
|
45
|
+
end
|
46
|
+
|
47
|
+
@func = Fiddle::Function.new(handle[func], import, export, calltype)
|
48
|
+
rescue Fiddle::DLError => e
|
49
|
+
raise LoadError, e.message, e.backtrace
|
50
|
+
end
|
40
51
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
def call(*args)
|
53
|
+
import = @proto.split("")
|
54
|
+
args.each_with_index do |x, i|
|
55
|
+
args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
|
56
|
+
args[i], = [x].pack("I").unpack("i") if import[i] == "I"
|
57
|
+
end
|
58
|
+
ret, = @func.call(*args)
|
59
|
+
return ret || 0
|
46
60
|
end
|
47
|
-
ret, = @func.call(*args)
|
48
|
-
return ret || 0
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
52
64
|
VK_MENU = 0x12
|
65
|
+
VK_LMENU = 0xA4
|
66
|
+
VK_CONTROL = 0x11
|
53
67
|
VK_SHIFT = 0x10
|
68
|
+
STD_INPUT_HANDLE = -10
|
54
69
|
STD_OUTPUT_HANDLE = -11
|
70
|
+
WINDOW_BUFFER_SIZE_EVENT = 0x04
|
55
71
|
@@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
|
56
72
|
@@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
|
57
73
|
@@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
|
@@ -61,77 +77,101 @@ class Reline::Windows
|
|
61
77
|
@@FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
|
62
78
|
@@ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
|
63
79
|
@@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE)
|
64
|
-
@@
|
80
|
+
@@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE)
|
81
|
+
@@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
|
82
|
+
@@ReadConsoleInput = Win32API.new('kernel32', 'ReadConsoleInput', ['L', 'P', 'L', 'P'], 'L')
|
83
|
+
@@input_buf = []
|
84
|
+
@@output_buf = []
|
65
85
|
|
66
86
|
def self.getwch
|
87
|
+
unless @@input_buf.empty?
|
88
|
+
return @@input_buf.shift
|
89
|
+
end
|
67
90
|
while @@kbhit.call == 0
|
68
91
|
sleep(0.001)
|
69
92
|
end
|
70
|
-
result = []
|
71
93
|
until @@kbhit.call == 0
|
72
94
|
ret = @@getwch.call
|
95
|
+
if ret == 0 or ret == 0xE0
|
96
|
+
@@input_buf << ret
|
97
|
+
ret = @@getwch.call
|
98
|
+
@@input_buf << ret
|
99
|
+
return @@input_buf.shift
|
100
|
+
end
|
73
101
|
begin
|
74
|
-
|
102
|
+
bytes = ret.chr(Encoding::UTF_8).encode(Encoding.default_external).bytes
|
103
|
+
@@input_buf.push(*bytes)
|
75
104
|
rescue Encoding::UndefinedConversionError
|
76
|
-
|
77
|
-
|
105
|
+
@@input_buf << ret
|
106
|
+
@@input_buf << @@getwch.call if ret == 224
|
78
107
|
end
|
79
108
|
end
|
80
|
-
|
109
|
+
@@input_buf.shift
|
81
110
|
end
|
82
111
|
|
83
112
|
def self.getc
|
84
|
-
|
85
|
-
|
113
|
+
num_of_events = 0.chr * 8
|
114
|
+
while @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) != 0 and num_of_events.unpack('L').first > 0
|
115
|
+
input_record = 0.chr * 18
|
116
|
+
read_event = 0.chr * 4
|
117
|
+
if @@ReadConsoleInput.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
|
118
|
+
event = input_record[0, 2].unpack('s*').first
|
119
|
+
if event == WINDOW_BUFFER_SIZE_EVENT
|
120
|
+
@@winch_handler.()
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
unless @@output_buf.empty?
|
125
|
+
return @@output_buf.shift
|
86
126
|
end
|
87
127
|
input = getwch
|
88
|
-
|
89
|
-
|
90
|
-
|
128
|
+
meta = (@@GetKeyState.call(VK_LMENU) & 0x80) != 0
|
129
|
+
control = (@@GetKeyState.call(VK_CONTROL) & 0x80) != 0
|
130
|
+
shift = (@@GetKeyState.call(VK_SHIFT) & 0x80) != 0
|
131
|
+
force_enter = !input.instance_of?(Array) && (control or shift) && input == 0x0D
|
132
|
+
if force_enter
|
91
133
|
# It's treated as Meta+Enter on Windows
|
92
|
-
@@
|
93
|
-
@@
|
94
|
-
|
95
|
-
|
96
|
-
else # single byte
|
97
|
-
case input[0]
|
134
|
+
@@output_buf.push("\e".ord)
|
135
|
+
@@output_buf.push(input)
|
136
|
+
else
|
137
|
+
case input
|
98
138
|
when 0x00
|
99
|
-
|
100
|
-
|
139
|
+
meta = false
|
140
|
+
@@output_buf.push(input)
|
101
141
|
input = getwch
|
102
|
-
@@
|
142
|
+
@@output_buf.push(*input)
|
103
143
|
when 0xE0
|
104
|
-
@@
|
144
|
+
@@output_buf.push(input)
|
105
145
|
input = getwch
|
106
|
-
@@
|
146
|
+
@@output_buf.push(*input)
|
107
147
|
when 0x03
|
108
|
-
@@
|
148
|
+
@@output_buf.push(input)
|
109
149
|
else
|
110
|
-
@@
|
150
|
+
@@output_buf.push(input)
|
111
151
|
end
|
112
152
|
end
|
113
|
-
if
|
153
|
+
if meta
|
114
154
|
"\e".ord
|
115
155
|
else
|
116
|
-
@@
|
156
|
+
@@output_buf.shift
|
117
157
|
end
|
118
158
|
end
|
119
159
|
|
120
160
|
def self.ungetc(c)
|
121
|
-
@@
|
161
|
+
@@output_buf.unshift(c)
|
122
162
|
end
|
123
163
|
|
124
164
|
def self.get_screen_size
|
125
|
-
csbi = 0.chr *
|
165
|
+
csbi = 0.chr * 22
|
126
166
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
127
167
|
csbi[0, 4].unpack('SS').reverse
|
128
168
|
end
|
129
169
|
|
130
170
|
def self.cursor_pos
|
131
|
-
csbi = 0.chr *
|
171
|
+
csbi = 0.chr * 22
|
132
172
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
133
173
|
x = csbi[4, 2].unpack('s*').first
|
134
|
-
y = csbi[6,
|
174
|
+
y = csbi[6, 2].unpack('s*').first
|
135
175
|
Reline::CursorPos.new(x, y)
|
136
176
|
end
|
137
177
|
|
@@ -181,6 +221,10 @@ class Reline::Windows
|
|
181
221
|
raise NotImplementedError
|
182
222
|
end
|
183
223
|
|
224
|
+
def self.set_winch_handler(&handler)
|
225
|
+
@@winch_handler = handler
|
226
|
+
end
|
227
|
+
|
184
228
|
def self.prep
|
185
229
|
# do nothing
|
186
230
|
nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
98
|
- !ruby/object:Gem::Version
|
99
99
|
version: '0'
|
100
100
|
requirements: []
|
101
|
-
rubygems_version: 3.0.
|
101
|
+
rubygems_version: 3.0.6
|
102
102
|
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|