reline 0.5.7 → 0.5.9
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 +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-!
|