reline 0.5.8 → 0.5.10

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.
@@ -1,21 +1,49 @@
1
1
  require 'fiddle/import'
2
2
 
3
- class Reline::Windows
4
- RESET_COLOR = "\e[0m"
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 self.encoding
34
+ def encoding
7
35
  Encoding::UTF_8
8
36
  end
9
37
 
10
- def self.win?
38
+ def win?
11
39
  true
12
40
  end
13
41
 
14
- def self.win_legacy_console?
15
- @@legacy_console
42
+ def win_legacy_console?
43
+ @legacy_console
16
44
  end
17
45
 
18
- def self.set_default_key_bindings(config)
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,42 @@ 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
- private_class_method def self.getconsolemode
162
+ # Calling Win32API with console handle is reported to fail after executing some external command.
163
+ # We need to refresh console handle and retry the call again.
164
+ private def call_with_console_handle(win32func, *args)
165
+ val = win32func.call(@hConsoleHandle, *args)
166
+ return val if val != 0
167
+
168
+ @hConsoleHandle = @GetStdHandle.call(STD_OUTPUT_HANDLE)
169
+ win32func.call(@hConsoleHandle, *args)
170
+ end
171
+
172
+ private def getconsolemode
155
173
  mode = "\000\000\000\000"
156
- @@GetConsoleMode.call(@@hConsoleHandle, mode)
174
+ call_with_console_handle(@GetConsoleMode, mode)
157
175
  mode.unpack1('L')
158
176
  end
159
177
 
160
- private_class_method def self.setconsolemode(mode)
161
- @@SetConsoleMode.call(@@hConsoleHandle, mode)
178
+ private def setconsolemode(mode)
179
+ call_with_console_handle(@SetConsoleMode, mode)
162
180
  end
163
181
 
164
- @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
165
- #if @@legacy_console
182
+ #if @legacy_console
166
183
  # setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
167
- # @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
184
+ # @legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
168
185
  #end
169
186
 
170
- @@input_buf = []
171
- @@output_buf = []
172
-
173
- @@output = STDOUT
174
-
175
- def self.msys_tty?(io = @@hConsoleInputHandle)
187
+ def msys_tty?(io = @hConsoleInputHandle)
176
188
  # check if fd is a pipe
177
- if @@GetFileType.call(io) != FILE_TYPE_PIPE
189
+ if @GetFileType.call(io) != FILE_TYPE_PIPE
178
190
  return false
179
191
  end
180
192
 
181
193
  bufsize = 1024
182
194
  p_buffer = "\0" * bufsize
183
- res = @@GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
195
+ res = @GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
184
196
  return false if res == 0
185
197
 
186
198
  # get pipe name: p_buffer layout is:
@@ -217,65 +229,63 @@ class Reline::Windows
217
229
  [ { control_keys: :SHIFT, virtual_key_code: VK_TAB }, [27, 91, 90] ],
218
230
  ]
219
231
 
220
- @@hsg = nil
221
-
222
- def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
232
+ def process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
223
233
 
224
234
  # high-surrogate
225
235
  if 0xD800 <= char_code and char_code <= 0xDBFF
226
- @@hsg = char_code
236
+ @hsg = char_code
227
237
  return
228
238
  end
229
239
  # low-surrogate
230
240
  if 0xDC00 <= char_code and char_code <= 0xDFFF
231
- if @@hsg
232
- char_code = 0x10000 + (@@hsg - 0xD800) * 0x400 + char_code - 0xDC00
233
- @@hsg = nil
241
+ if @hsg
242
+ char_code = 0x10000 + (@hsg - 0xD800) * 0x400 + char_code - 0xDC00
243
+ @hsg = nil
234
244
  else
235
245
  # no high-surrogate. ignored.
236
246
  return
237
247
  end
238
248
  else
239
249
  # ignore high-surrogate without low-surrogate if there
240
- @@hsg = nil
250
+ @hsg = nil
241
251
  end
242
252
 
243
253
  key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
244
254
 
245
255
  match = KEY_MAP.find { |args,| key.matches?(**args) }
246
256
  unless match.nil?
247
- @@output_buf.concat(match.last)
257
+ @output_buf.concat(match.last)
248
258
  return
249
259
  end
250
260
 
251
261
  # no char, only control keys
252
262
  return if key.char_code == 0 and key.control_keys.any?
253
263
 
254
- @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
264
+ @output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
255
265
 
256
- @@output_buf.concat(key.char.bytes)
266
+ @output_buf.concat(key.char.bytes)
257
267
  end
258
268
 
259
- def self.check_input_event
269
+ def check_input_event
260
270
  num_of_events = 0.chr * 8
261
- while @@output_buf.empty?
271
+ while @output_buf.empty?
262
272
  Reline.core.line_editor.handle_signal
263
- if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
273
+ if @WaitForSingleObject.(@hConsoleInputHandle, 100) != 0 # max 0.1 sec
264
274
  # prevent for background consolemode change
265
- @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
275
+ @legacy_console = getconsolemode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0
266
276
  next
267
277
  end
268
- next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
278
+ next if @GetNumberOfConsoleInputEvents.(@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
269
279
  input_records = 0.chr * 20 * 80
270
280
  read_event = 0.chr * 4
271
- if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_records, 80, read_event) != 0
281
+ if @ReadConsoleInputW.(@hConsoleInputHandle, input_records, 80, read_event) != 0
272
282
  read_events = read_event.unpack1('L')
273
283
  0.upto(read_events) do |idx|
274
284
  input_record = input_records[idx * 20, 20]
275
285
  event = input_record[0, 2].unpack1('s*')
276
286
  case event
277
287
  when WINDOW_BUFFER_SIZE_EVENT
278
- @@winch_handler.()
288
+ @winch_handler.()
279
289
  when KEY_EVENT
280
290
  key_down = input_record[4, 4].unpack1('l*')
281
291
  repeat_count = input_record[8, 2].unpack1('s*')
@@ -293,34 +303,34 @@ class Reline::Windows
293
303
  end
294
304
  end
295
305
 
296
- def self.with_raw_input
306
+ def with_raw_input
297
307
  yield
298
308
  end
299
309
 
300
- def self.getc(_timeout_second)
310
+ def getc(_timeout_second)
301
311
  check_input_event
302
- @@output_buf.shift
312
+ @output_buf.shift
303
313
  end
304
314
 
305
- def self.ungetc(c)
306
- @@output_buf.unshift(c)
315
+ def ungetc(c)
316
+ @output_buf.unshift(c)
307
317
  end
308
318
 
309
- def self.in_pasting?
310
- not self.empty_buffer?
319
+ def in_pasting?
320
+ not empty_buffer?
311
321
  end
312
322
 
313
- def self.empty_buffer?
314
- if not @@output_buf.empty?
323
+ def empty_buffer?
324
+ if not @output_buf.empty?
315
325
  false
316
- elsif @@kbhit.call == 0
326
+ elsif @kbhit.call == 0
317
327
  true
318
328
  else
319
329
  false
320
330
  end
321
331
  end
322
332
 
323
- def self.get_console_screen_buffer_info
333
+ def get_console_screen_buffer_info
324
334
  # CONSOLE_SCREEN_BUFFER_INFO
325
335
  # [ 0,2] dwSize.X
326
336
  # [ 2,2] dwSize.Y
@@ -334,18 +344,18 @@ class Reline::Windows
334
344
  # [18,2] dwMaximumWindowSize.X
335
345
  # [20,2] dwMaximumWindowSize.Y
336
346
  csbi = 0.chr * 22
337
- return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
347
+ return if call_with_console_handle(@GetConsoleScreenBufferInfo, csbi) == 0
338
348
  csbi
339
349
  end
340
350
 
341
- def self.get_screen_size
351
+ def get_screen_size
342
352
  unless csbi = get_console_screen_buffer_info
343
353
  return [1, 1]
344
354
  end
345
355
  csbi[0, 4].unpack('SS').reverse
346
356
  end
347
357
 
348
- def self.cursor_pos
358
+ def cursor_pos
349
359
  unless csbi = get_console_screen_buffer_info
350
360
  return Reline::CursorPos.new(0, 0)
351
361
  end
@@ -354,49 +364,49 @@ class Reline::Windows
354
364
  Reline::CursorPos.new(x, y)
355
365
  end
356
366
 
357
- def self.move_cursor_column(val)
358
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, cursor_pos.y * 65536 + val)
367
+ def move_cursor_column(val)
368
+ call_with_console_handle(@SetConsoleCursorPosition, cursor_pos.y * 65536 + val)
359
369
  end
360
370
 
361
- def self.move_cursor_up(val)
371
+ def move_cursor_up(val)
362
372
  if val > 0
363
373
  y = cursor_pos.y - val
364
374
  y = 0 if y < 0
365
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, y * 65536 + cursor_pos.x)
375
+ call_with_console_handle(@SetConsoleCursorPosition, y * 65536 + cursor_pos.x)
366
376
  elsif val < 0
367
377
  move_cursor_down(-val)
368
378
  end
369
379
  end
370
380
 
371
- def self.move_cursor_down(val)
381
+ def move_cursor_down(val)
372
382
  if val > 0
373
383
  return unless csbi = get_console_screen_buffer_info
374
384
  screen_height = get_screen_size.first
375
385
  y = cursor_pos.y + val
376
386
  y = screen_height - 1 if y > (screen_height - 1)
377
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
387
+ call_with_console_handle(@SetConsoleCursorPosition, (cursor_pos.y + val) * 65536 + cursor_pos.x)
378
388
  elsif val < 0
379
389
  move_cursor_up(-val)
380
390
  end
381
391
  end
382
392
 
383
- def self.erase_after_cursor
393
+ def erase_after_cursor
384
394
  return unless csbi = get_console_screen_buffer_info
385
395
  attributes = csbi[8, 2].unpack1('S')
386
396
  cursor = csbi[4, 4].unpack1('L')
387
397
  written = 0.chr * 4
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)
398
+ call_with_console_handle(@FillConsoleOutputCharacter, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
399
+ call_with_console_handle(@FillConsoleOutputAttribute, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
390
400
  end
391
401
 
392
- def self.scroll_down(val)
402
+ def scroll_down(val)
393
403
  return if val < 0
394
404
  return unless csbi = get_console_screen_buffer_info
395
405
  buffer_width, buffer_lines, x, y, attributes, window_left, window_top, window_bottom = csbi.unpack('ssssSssx2s')
396
406
  screen_height = window_bottom - window_top + 1
397
407
  val = screen_height if val > screen_height
398
408
 
399
- if @@legacy_console || window_left != 0
409
+ if @legacy_console || window_left != 0
400
410
  # unless ENABLE_VIRTUAL_TERMINAL,
401
411
  # if srWindow.Left != 0 then it's conhost.exe hosted console
402
412
  # and puts "\n" causes horizontal scroll. its glitch.
@@ -404,11 +414,11 @@ class Reline::Windows
404
414
  scroll_rectangle = [0, val, buffer_width, buffer_lines - val].pack('s4')
405
415
  destination_origin = 0 # y * 65536 + x
406
416
  fill = [' '.ord, attributes].pack('SS')
407
- @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
417
+ call_with_console_handle(@ScrollConsoleScreenBuffer, scroll_rectangle, nil, destination_origin, fill)
408
418
  else
409
419
  origin_x = x + 1
410
420
  origin_y = y - window_top + 1
411
- @@output.write [
421
+ @output.write [
412
422
  (origin_y != screen_height) ? "\e[#{screen_height};H" : nil,
413
423
  "\n" * val,
414
424
  (origin_y != screen_height or !x.zero?) ? "\e[#{origin_y};#{origin_x}H" : nil
@@ -416,49 +426,49 @@ class Reline::Windows
416
426
  end
417
427
  end
418
428
 
419
- def self.clear_screen
420
- if @@legacy_console
429
+ def clear_screen
430
+ if @legacy_console
421
431
  return unless csbi = get_console_screen_buffer_info
422
432
  buffer_width, _buffer_lines, attributes, window_top, window_bottom = csbi.unpack('ss@8S@12sx2s')
423
433
  fill_length = buffer_width * (window_bottom - window_top + 1)
424
434
  screen_topleft = window_top * 65536
425
435
  written = 0.chr * 4
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)
436
+ call_with_console_handle(@FillConsoleOutputCharacter, 0x20, fill_length, screen_topleft, written)
437
+ call_with_console_handle(@FillConsoleOutputAttribute, attributes, fill_length, screen_topleft, written)
438
+ call_with_console_handle(@SetConsoleCursorPosition, screen_topleft)
429
439
  else
430
- @@output.write "\e[2J" "\e[H"
440
+ @output.write "\e[2J" "\e[H"
431
441
  end
432
442
  end
433
443
 
434
- def self.set_screen_size(rows, columns)
444
+ def set_screen_size(rows, columns)
435
445
  raise NotImplementedError
436
446
  end
437
447
 
438
- def self.hide_cursor
448
+ def hide_cursor
439
449
  size = 100
440
450
  visible = 0 # 0 means false
441
451
  cursor_info = [size, visible].pack('Li')
442
- @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
452
+ call_with_console_handle(@SetConsoleCursorInfo, cursor_info)
443
453
  end
444
454
 
445
- def self.show_cursor
455
+ def show_cursor
446
456
  size = 100
447
457
  visible = 1 # 1 means true
448
458
  cursor_info = [size, visible].pack('Li')
449
- @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
459
+ call_with_console_handle(@SetConsoleCursorInfo, cursor_info)
450
460
  end
451
461
 
452
- def self.set_winch_handler(&handler)
453
- @@winch_handler = handler
462
+ def set_winch_handler(&handler)
463
+ @winch_handler = handler
454
464
  end
455
465
 
456
- def self.prep
466
+ def prep
457
467
  # do nothing
458
468
  nil
459
469
  end
460
470
 
461
- def self.deprep(otio)
471
+ def deprep(otio)
462
472
  # do nothing
463
473
  end
464
474
 
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
- MAPPING = Array.new(256)
2
+ def initialize(mapping = [])
3
+ @mapping = mapping
4
+ @matching_bytes = {}
5
+ @key_bindings = {}
6
+ end
3
7
 
4
8
  def get_method(key)
5
- self.class::MAPPING[key]
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 initialize
9
- @default_key_bindings = {}
23
+ def get(key)
24
+ @key_bindings[key]
10
25
  end
11
26
 
12
- def default_key_bindings
13
- @default_key_bindings
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
- class Reline::KeyActor::Emacs < Reline::KeyActor::Base
2
- MAPPING = [
1
+ module Reline::KeyActor
2
+ EMACS_MAPPING = [
3
3
  # 0 ^@
4
4
  :em_set_mark,
5
5
  # 1 ^A
@@ -1,5 +1,5 @@
1
- class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
2
- MAPPING = [
1
+ module Reline::KeyActor
2
+ VI_COMMAND_MAPPING = [
3
3
  # 0 ^@
4
4
  :ed_unassigned,
5
5
  # 1 ^A
@@ -1,5 +1,5 @@
1
- class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
2
- MAPPING = [
1
+ module Reline::KeyActor
2
+ VI_INSERT_MAPPING = [
3
3
  # 0 ^@
4
4
  :ed_unassigned,
5
5
  # 1 ^A
@@ -2,6 +2,7 @@ module Reline::KeyActor
2
2
  end
3
3
 
4
4
  require 'reline/key_actor/base'
5
+ require 'reline/key_actor/composite'
5
6
  require 'reline/key_actor/emacs'
6
7
  require 'reline/key_actor/vi_command'
7
8
  require 'reline/key_actor/vi_insert'