reline 0.5.7 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/reline/config.rb +30 -27
- data/lib/reline/{ansi.rb → io/ansi.rb} +88 -86
- data/lib/reline/io/dumb.rb +106 -0
- data/lib/reline/{windows.rb → io/windows.rb} +102 -102
- data/lib/reline/io.rb +41 -0
- data/lib/reline/key_actor/base.rb +22 -6
- data/lib/reline/key_actor/composite.rb +17 -0
- data/lib/reline/key_actor/emacs.rb +3 -3
- data/lib/reline/key_actor/vi_command.rb +2 -2
- data/lib/reline/key_actor/vi_insert.rb +2 -2
- data/lib/reline/key_actor.rb +1 -0
- data/lib/reline/key_stroke.rb +65 -104
- data/lib/reline/line_editor.rb +61 -45
- data/lib/reline/terminfo.rb +5 -0
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +35 -123
- metadata +7 -5
- data/lib/reline/general_io.rb +0 -111
@@ -1,21 +1,49 @@
|
|
1
1
|
require 'fiddle/import'
|
2
2
|
|
3
|
-
class Reline::Windows
|
4
|
-
|
3
|
+
class Reline::Windows < Reline::IO
|
4
|
+
def initialize
|
5
|
+
@input_buf = []
|
6
|
+
@output_buf = []
|
7
|
+
|
8
|
+
@output = STDOUT
|
9
|
+
@hsg = nil
|
10
|
+
@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
|
11
|
+
@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
|
12
|
+
@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
|
13
|
+
@GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
|
14
|
+
@SetConsoleCursorPosition = Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
|
15
|
+
@GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
|
16
|
+
@FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
|
17
|
+
@ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
|
18
|
+
@hConsoleHandle = @GetStdHandle.call(STD_OUTPUT_HANDLE)
|
19
|
+
@hConsoleInputHandle = @GetStdHandle.call(STD_INPUT_HANDLE)
|
20
|
+
@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
|
21
|
+
@ReadConsoleInputW = Win32API.new('kernel32', 'ReadConsoleInputW', ['L', 'P', 'L', 'P'], 'L')
|
22
|
+
@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
|
23
|
+
@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
|
24
|
+
@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L')
|
25
|
+
@SetConsoleCursorInfo = Win32API.new('kernel32', 'SetConsoleCursorInfo', ['L', 'P'], 'L')
|
26
|
+
|
27
|
+
@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
|
28
|
+
@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')
|
29
|
+
@WaitForSingleObject = Win32API.new('kernel32', 'WaitForSingleObject', ['L', 'L'], 'L')
|
30
|
+
|
31
|
+
@legacy_console = getconsolemode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0
|
32
|
+
end
|
5
33
|
|
6
|
-
def
|
34
|
+
def encoding
|
7
35
|
Encoding::UTF_8
|
8
36
|
end
|
9
37
|
|
10
|
-
def
|
38
|
+
def win?
|
11
39
|
true
|
12
40
|
end
|
13
41
|
|
14
|
-
def
|
15
|
-
|
42
|
+
def win_legacy_console?
|
43
|
+
@legacy_console
|
16
44
|
end
|
17
45
|
|
18
|
-
def
|
46
|
+
def set_default_key_bindings(config)
|
19
47
|
{
|
20
48
|
[224, 72] => :ed_prev_history, # ↑
|
21
49
|
[224, 80] => :ed_next_history, # ↓
|
@@ -129,58 +157,32 @@ class Reline::Windows
|
|
129
157
|
STD_OUTPUT_HANDLE = -11
|
130
158
|
FILE_TYPE_PIPE = 0x0003
|
131
159
|
FILE_NAME_INFO = 2
|
132
|
-
@@getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
|
133
|
-
@@kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
|
134
|
-
@@GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
|
135
|
-
@@GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
|
136
|
-
@@SetConsoleCursorPosition = Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
|
137
|
-
@@GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
|
138
|
-
@@FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
|
139
|
-
@@ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
|
140
|
-
@@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE)
|
141
|
-
@@hConsoleInputHandle = @@GetStdHandle.call(STD_INPUT_HANDLE)
|
142
|
-
@@GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['L', 'P'], 'L')
|
143
|
-
@@ReadConsoleInputW = Win32API.new('kernel32', 'ReadConsoleInputW', ['L', 'P', 'L', 'P'], 'L')
|
144
|
-
@@GetFileType = Win32API.new('kernel32', 'GetFileType', ['L'], 'L')
|
145
|
-
@@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
|
146
|
-
@@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L')
|
147
|
-
@@SetConsoleCursorInfo = Win32API.new('kernel32', 'SetConsoleCursorInfo', ['L', 'P'], 'L')
|
148
|
-
|
149
|
-
@@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
|
150
|
-
@@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')
|
151
|
-
@@WaitForSingleObject = Win32API.new('kernel32', 'WaitForSingleObject', ['L', 'L'], 'L')
|
152
160
|
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
|
153
161
|
|
154
|
-
|
162
|
+
private def getconsolemode
|
155
163
|
mode = "\000\000\000\000"
|
156
|
-
|
164
|
+
@GetConsoleMode.call(@hConsoleHandle, mode)
|
157
165
|
mode.unpack1('L')
|
158
166
|
end
|
159
167
|
|
160
|
-
|
161
|
-
|
168
|
+
private def setconsolemode(mode)
|
169
|
+
@SetConsoleMode.call(@hConsoleHandle, mode)
|
162
170
|
end
|
163
171
|
|
164
|
-
|
165
|
-
#if @@legacy_console
|
172
|
+
#if @legacy_console
|
166
173
|
# setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
167
|
-
#
|
174
|
+
# @legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
|
168
175
|
#end
|
169
176
|
|
170
|
-
|
171
|
-
@@output_buf = []
|
172
|
-
|
173
|
-
@@output = STDOUT
|
174
|
-
|
175
|
-
def self.msys_tty?(io = @@hConsoleInputHandle)
|
177
|
+
def msys_tty?(io = @hConsoleInputHandle)
|
176
178
|
# check if fd is a pipe
|
177
|
-
if
|
179
|
+
if @GetFileType.call(io) != FILE_TYPE_PIPE
|
178
180
|
return false
|
179
181
|
end
|
180
182
|
|
181
183
|
bufsize = 1024
|
182
184
|
p_buffer = "\0" * bufsize
|
183
|
-
res =
|
185
|
+
res = @GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
|
184
186
|
return false if res == 0
|
185
187
|
|
186
188
|
# get pipe name: p_buffer layout is:
|
@@ -217,65 +219,63 @@ class Reline::Windows
|
|
217
219
|
[ { control_keys: :SHIFT, virtual_key_code: VK_TAB }, [27, 91, 90] ],
|
218
220
|
]
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
-
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
222
|
+
def process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
223
223
|
|
224
224
|
# high-surrogate
|
225
225
|
if 0xD800 <= char_code and char_code <= 0xDBFF
|
226
|
-
|
226
|
+
@hsg = char_code
|
227
227
|
return
|
228
228
|
end
|
229
229
|
# low-surrogate
|
230
230
|
if 0xDC00 <= char_code and char_code <= 0xDFFF
|
231
|
-
if
|
232
|
-
char_code = 0x10000 + (
|
233
|
-
|
231
|
+
if @hsg
|
232
|
+
char_code = 0x10000 + (@hsg - 0xD800) * 0x400 + char_code - 0xDC00
|
233
|
+
@hsg = nil
|
234
234
|
else
|
235
235
|
# no high-surrogate. ignored.
|
236
236
|
return
|
237
237
|
end
|
238
238
|
else
|
239
239
|
# ignore high-surrogate without low-surrogate if there
|
240
|
-
|
240
|
+
@hsg = nil
|
241
241
|
end
|
242
242
|
|
243
243
|
key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
|
244
244
|
|
245
245
|
match = KEY_MAP.find { |args,| key.matches?(**args) }
|
246
246
|
unless match.nil?
|
247
|
-
|
247
|
+
@output_buf.concat(match.last)
|
248
248
|
return
|
249
249
|
end
|
250
250
|
|
251
251
|
# no char, only control keys
|
252
252
|
return if key.char_code == 0 and key.control_keys.any?
|
253
253
|
|
254
|
-
|
254
|
+
@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
|
255
255
|
|
256
|
-
|
256
|
+
@output_buf.concat(key.char.bytes)
|
257
257
|
end
|
258
258
|
|
259
|
-
def
|
259
|
+
def check_input_event
|
260
260
|
num_of_events = 0.chr * 8
|
261
|
-
while
|
261
|
+
while @output_buf.empty?
|
262
262
|
Reline.core.line_editor.handle_signal
|
263
|
-
if
|
263
|
+
if @WaitForSingleObject.(@hConsoleInputHandle, 100) != 0 # max 0.1 sec
|
264
264
|
# prevent for background consolemode change
|
265
|
-
|
265
|
+
@legacy_console = getconsolemode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0
|
266
266
|
next
|
267
267
|
end
|
268
|
-
next if
|
268
|
+
next if @GetNumberOfConsoleInputEvents.(@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
|
269
269
|
input_records = 0.chr * 20 * 80
|
270
270
|
read_event = 0.chr * 4
|
271
|
-
if
|
271
|
+
if @ReadConsoleInputW.(@hConsoleInputHandle, input_records, 80, read_event) != 0
|
272
272
|
read_events = read_event.unpack1('L')
|
273
273
|
0.upto(read_events) do |idx|
|
274
274
|
input_record = input_records[idx * 20, 20]
|
275
275
|
event = input_record[0, 2].unpack1('s*')
|
276
276
|
case event
|
277
277
|
when WINDOW_BUFFER_SIZE_EVENT
|
278
|
-
|
278
|
+
@winch_handler.()
|
279
279
|
when KEY_EVENT
|
280
280
|
key_down = input_record[4, 4].unpack1('l*')
|
281
281
|
repeat_count = input_record[8, 2].unpack1('s*')
|
@@ -293,34 +293,34 @@ class Reline::Windows
|
|
293
293
|
end
|
294
294
|
end
|
295
295
|
|
296
|
-
def
|
296
|
+
def with_raw_input
|
297
297
|
yield
|
298
298
|
end
|
299
299
|
|
300
|
-
def
|
300
|
+
def getc(_timeout_second)
|
301
301
|
check_input_event
|
302
|
-
|
302
|
+
@output_buf.shift
|
303
303
|
end
|
304
304
|
|
305
|
-
def
|
306
|
-
|
305
|
+
def ungetc(c)
|
306
|
+
@output_buf.unshift(c)
|
307
307
|
end
|
308
308
|
|
309
|
-
def
|
310
|
-
not
|
309
|
+
def in_pasting?
|
310
|
+
not empty_buffer?
|
311
311
|
end
|
312
312
|
|
313
|
-
def
|
314
|
-
if not
|
313
|
+
def empty_buffer?
|
314
|
+
if not @output_buf.empty?
|
315
315
|
false
|
316
|
-
elsif
|
316
|
+
elsif @kbhit.call == 0
|
317
317
|
true
|
318
318
|
else
|
319
319
|
false
|
320
320
|
end
|
321
321
|
end
|
322
322
|
|
323
|
-
def
|
323
|
+
def get_console_screen_buffer_info
|
324
324
|
# CONSOLE_SCREEN_BUFFER_INFO
|
325
325
|
# [ 0,2] dwSize.X
|
326
326
|
# [ 2,2] dwSize.Y
|
@@ -334,18 +334,18 @@ class Reline::Windows
|
|
334
334
|
# [18,2] dwMaximumWindowSize.X
|
335
335
|
# [20,2] dwMaximumWindowSize.Y
|
336
336
|
csbi = 0.chr * 22
|
337
|
-
return if
|
337
|
+
return if @GetConsoleScreenBufferInfo.call(@hConsoleHandle, csbi) == 0
|
338
338
|
csbi
|
339
339
|
end
|
340
340
|
|
341
|
-
def
|
341
|
+
def get_screen_size
|
342
342
|
unless csbi = get_console_screen_buffer_info
|
343
343
|
return [1, 1]
|
344
344
|
end
|
345
345
|
csbi[0, 4].unpack('SS').reverse
|
346
346
|
end
|
347
347
|
|
348
|
-
def
|
348
|
+
def cursor_pos
|
349
349
|
unless csbi = get_console_screen_buffer_info
|
350
350
|
return Reline::CursorPos.new(0, 0)
|
351
351
|
end
|
@@ -354,49 +354,49 @@ class Reline::Windows
|
|
354
354
|
Reline::CursorPos.new(x, y)
|
355
355
|
end
|
356
356
|
|
357
|
-
def
|
358
|
-
|
357
|
+
def move_cursor_column(val)
|
358
|
+
@SetConsoleCursorPosition.call(@hConsoleHandle, cursor_pos.y * 65536 + val)
|
359
359
|
end
|
360
360
|
|
361
|
-
def
|
361
|
+
def move_cursor_up(val)
|
362
362
|
if val > 0
|
363
363
|
y = cursor_pos.y - val
|
364
364
|
y = 0 if y < 0
|
365
|
-
|
365
|
+
@SetConsoleCursorPosition.call(@hConsoleHandle, y * 65536 + cursor_pos.x)
|
366
366
|
elsif val < 0
|
367
367
|
move_cursor_down(-val)
|
368
368
|
end
|
369
369
|
end
|
370
370
|
|
371
|
-
def
|
371
|
+
def move_cursor_down(val)
|
372
372
|
if val > 0
|
373
373
|
return unless csbi = get_console_screen_buffer_info
|
374
374
|
screen_height = get_screen_size.first
|
375
375
|
y = cursor_pos.y + val
|
376
376
|
y = screen_height - 1 if y > (screen_height - 1)
|
377
|
-
|
377
|
+
@SetConsoleCursorPosition.call(@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
|
378
378
|
elsif val < 0
|
379
379
|
move_cursor_up(-val)
|
380
380
|
end
|
381
381
|
end
|
382
382
|
|
383
|
-
def
|
383
|
+
def erase_after_cursor
|
384
384
|
return unless csbi = get_console_screen_buffer_info
|
385
385
|
attributes = csbi[8, 2].unpack1('S')
|
386
386
|
cursor = csbi[4, 4].unpack1('L')
|
387
387
|
written = 0.chr * 4
|
388
|
-
|
389
|
-
|
388
|
+
@FillConsoleOutputCharacter.call(@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
|
389
|
+
@FillConsoleOutputAttribute.call(@hConsoleHandle, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
|
390
390
|
end
|
391
391
|
|
392
|
-
def
|
392
|
+
def scroll_down(val)
|
393
393
|
return if val < 0
|
394
394
|
return unless csbi = get_console_screen_buffer_info
|
395
395
|
buffer_width, buffer_lines, x, y, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s')
|
396
396
|
screen_height = window_bottom - window_top + 1
|
397
397
|
val = screen_height if val > screen_height
|
398
398
|
|
399
|
-
if
|
399
|
+
if @legacy_console || window_left != 0
|
400
400
|
# unless ENABLE_VIRTUAL_TERMINAL,
|
401
401
|
# if srWindow.Left != 0 then it's conhost.exe hosted console
|
402
402
|
# and puts "\n" causes horizontal scroll. its glitch.
|
@@ -404,11 +404,11 @@ class Reline::Windows
|
|
404
404
|
scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4')
|
405
405
|
destination_origin = 0 # y * 65536 + x
|
406
406
|
fill = [' '.ord, attributes].pack('SS')
|
407
|
-
|
407
|
+
@ScrollConsoleScreenBuffer.call(@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
|
408
408
|
else
|
409
409
|
origin_x = x + 1
|
410
410
|
origin_y = y - window_top + 1
|
411
|
-
|
411
|
+
@output.write [
|
412
412
|
(origin_y != screen_height) ? "\e[#{screen_height};H" : nil,
|
413
413
|
"\n" * val,
|
414
414
|
(origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil
|
@@ -416,49 +416,49 @@ class Reline::Windows
|
|
416
416
|
end
|
417
417
|
end
|
418
418
|
|
419
|
-
def
|
420
|
-
if
|
419
|
+
def clear_screen
|
420
|
+
if @legacy_console
|
421
421
|
return unless csbi = get_console_screen_buffer_info
|
422
422
|
buffer_width, _buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s')
|
423
423
|
fill_length = buffer_width * (window_bottom - window_top + 1)
|
424
424
|
screen_topleft = window_top * 65536
|
425
425
|
written = 0.chr * 4
|
426
|
-
|
427
|
-
|
428
|
-
|
426
|
+
@FillConsoleOutputCharacter.call(@hConsoleHandle, 0x20, fill_length, screen_topleft, written)
|
427
|
+
@FillConsoleOutputAttribute.call(@hConsoleHandle, attributes, fill_length, screen_topleft, written)
|
428
|
+
@SetConsoleCursorPosition.call(@hConsoleHandle, screen_topleft)
|
429
429
|
else
|
430
|
-
|
430
|
+
@output.write "\e[2J" "\e[H"
|
431
431
|
end
|
432
432
|
end
|
433
433
|
|
434
|
-
def
|
434
|
+
def set_screen_size(rows, columns)
|
435
435
|
raise NotImplementedError
|
436
436
|
end
|
437
437
|
|
438
|
-
def
|
438
|
+
def hide_cursor
|
439
439
|
size = 100
|
440
440
|
visible = 0 # 0 means false
|
441
441
|
cursor_info = [size, visible].pack('Li')
|
442
|
-
|
442
|
+
@SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
|
443
443
|
end
|
444
444
|
|
445
|
-
def
|
445
|
+
def show_cursor
|
446
446
|
size = 100
|
447
447
|
visible = 1 # 1 means true
|
448
448
|
cursor_info = [size, visible].pack('Li')
|
449
|
-
|
449
|
+
@SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
|
450
450
|
end
|
451
451
|
|
452
|
-
def
|
453
|
-
|
452
|
+
def set_winch_handler(&handler)
|
453
|
+
@winch_handler = handler
|
454
454
|
end
|
455
455
|
|
456
|
-
def
|
456
|
+
def prep
|
457
457
|
# do nothing
|
458
458
|
nil
|
459
459
|
end
|
460
460
|
|
461
|
-
def
|
461
|
+
def deprep(otio)
|
462
462
|
# do nothing
|
463
463
|
end
|
464
464
|
|
data/lib/reline/io.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module Reline
|
3
|
+
class IO
|
4
|
+
RESET_COLOR = "\e[0m"
|
5
|
+
|
6
|
+
def self.decide_io_gate
|
7
|
+
if ENV['TERM'] == 'dumb'
|
8
|
+
Reline::Dumb.new
|
9
|
+
else
|
10
|
+
require 'reline/io/ansi'
|
11
|
+
|
12
|
+
case RbConfig::CONFIG['host_os']
|
13
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
14
|
+
require 'reline/io/windows'
|
15
|
+
io = Reline::Windows.new
|
16
|
+
if io.msys_tty?
|
17
|
+
Reline::ANSI.new
|
18
|
+
else
|
19
|
+
io
|
20
|
+
end
|
21
|
+
else
|
22
|
+
Reline::ANSI.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def dumb?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def win?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset_color_sequence
|
36
|
+
self.class::RESET_COLOR
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
require 'reline/io/dumb'
|
@@ -1,15 +1,31 @@
|
|
1
1
|
class Reline::KeyActor::Base
|
2
|
-
|
2
|
+
def initialize(mapping = [])
|
3
|
+
@mapping = mapping
|
4
|
+
@matching_bytes = {}
|
5
|
+
@key_bindings = {}
|
6
|
+
end
|
3
7
|
|
4
8
|
def get_method(key)
|
5
|
-
|
9
|
+
@mapping[key]
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(key, func)
|
13
|
+
(1...key.size).each do |size|
|
14
|
+
@matching_bytes[key.take(size)] = true
|
15
|
+
end
|
16
|
+
@key_bindings[key] = func
|
17
|
+
end
|
18
|
+
|
19
|
+
def matching?(key)
|
20
|
+
@matching_bytes[key]
|
6
21
|
end
|
7
22
|
|
8
|
-
def
|
9
|
-
@
|
23
|
+
def get(key)
|
24
|
+
@key_bindings[key]
|
10
25
|
end
|
11
26
|
|
12
|
-
def
|
13
|
-
@
|
27
|
+
def clear
|
28
|
+
@matching_bytes.clear
|
29
|
+
@key_bindings.clear
|
14
30
|
end
|
15
31
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Reline::KeyActor::Composite
|
2
|
+
def initialize(key_actors)
|
3
|
+
@key_actors = key_actors
|
4
|
+
end
|
5
|
+
|
6
|
+
def matching?(key)
|
7
|
+
@key_actors.any? { |key_actor| key_actor.matching?(key) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(key)
|
11
|
+
@key_actors.each do |key_actor|
|
12
|
+
func = key_actor.get(key)
|
13
|
+
return func if func
|
14
|
+
end
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Reline::KeyActor
|
2
|
+
EMACS_MAPPING = [
|
3
3
|
# 0 ^@
|
4
4
|
:em_set_mark,
|
5
5
|
# 1 ^A
|
@@ -319,7 +319,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
319
319
|
# 158 M-^^
|
320
320
|
:ed_unassigned,
|
321
321
|
# 159 M-^_
|
322
|
-
:
|
322
|
+
:redo,
|
323
323
|
# 160 M-SPACE
|
324
324
|
:em_set_mark,
|
325
325
|
# 161 M-!
|