reline 0.5.7 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,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
- private_class_method def self.getconsolemode
162
+ private def getconsolemode
155
163
  mode = "\000\000\000\000"
156
- @@GetConsoleMode.call(@@hConsoleHandle, mode)
164
+ @GetConsoleMode.call(@hConsoleHandle, mode)
157
165
  mode.unpack1('L')
158
166
  end
159
167
 
160
- private_class_method def self.setconsolemode(mode)
161
- @@SetConsoleMode.call(@@hConsoleHandle, mode)
168
+ private def setconsolemode(mode)
169
+ @SetConsoleMode.call(@hConsoleHandle, mode)
162
170
  end
163
171
 
164
- @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
165
- #if @@legacy_console
172
+ #if @legacy_console
166
173
  # setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
167
- # @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
174
+ # @legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
168
175
  #end
169
176
 
170
- @@input_buf = []
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 @@GetFileType.call(io) != FILE_TYPE_PIPE
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 = @@GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
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
- @@hsg = nil
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
- @@hsg = char_code
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 @@hsg
232
- char_code = 0x10000 + (@@hsg - 0xD800) * 0x400 + char_code - 0xDC00
233
- @@hsg = nil
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
- @@hsg = nil
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
- @@output_buf.concat(match.last)
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
- @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
254
+ @output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
255
255
 
256
- @@output_buf.concat(key.char.bytes)
256
+ @output_buf.concat(key.char.bytes)
257
257
  end
258
258
 
259
- def self.check_input_event
259
+ def check_input_event
260
260
  num_of_events = 0.chr * 8
261
- while @@output_buf.empty?
261
+ while @output_buf.empty?
262
262
  Reline.core.line_editor.handle_signal
263
- if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
263
+ if @WaitForSingleObject.(@hConsoleInputHandle, 100) != 0 # max 0.1 sec
264
264
  # prevent for background consolemode change
265
- @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
265
+ @legacy_console = getconsolemode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0
266
266
  next
267
267
  end
268
- next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
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 @@ReadConsoleInputW.(@@hConsoleInputHandle, input_records, 80, read_event) != 0
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
- @@winch_handler.()
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 self.with_raw_input
296
+ def with_raw_input
297
297
  yield
298
298
  end
299
299
 
300
- def self.getc(_timeout_second)
300
+ def getc(_timeout_second)
301
301
  check_input_event
302
- @@output_buf.shift
302
+ @output_buf.shift
303
303
  end
304
304
 
305
- def self.ungetc(c)
306
- @@output_buf.unshift(c)
305
+ def ungetc(c)
306
+ @output_buf.unshift(c)
307
307
  end
308
308
 
309
- def self.in_pasting?
310
- not self.empty_buffer?
309
+ def in_pasting?
310
+ not empty_buffer?
311
311
  end
312
312
 
313
- def self.empty_buffer?
314
- if not @@output_buf.empty?
313
+ def empty_buffer?
314
+ if not @output_buf.empty?
315
315
  false
316
- elsif @@kbhit.call == 0
316
+ elsif @kbhit.call == 0
317
317
  true
318
318
  else
319
319
  false
320
320
  end
321
321
  end
322
322
 
323
- def self.get_console_screen_buffer_info
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 @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
337
+ return if @GetConsoleScreenBufferInfo.call(@hConsoleHandle, csbi) == 0
338
338
  csbi
339
339
  end
340
340
 
341
- def self.get_screen_size
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 self.cursor_pos
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 self.move_cursor_column(val)
358
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, cursor_pos.y * 65536 + val)
357
+ def move_cursor_column(val)
358
+ @SetConsoleCursorPosition.call(@hConsoleHandle, cursor_pos.y * 65536 + val)
359
359
  end
360
360
 
361
- def self.move_cursor_up(val)
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
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, y * 65536 + cursor_pos.x)
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 self.move_cursor_down(val)
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
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y + val) * 65536 + cursor_pos.x)
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 self.erase_after_cursor
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
- @@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)
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 self.scroll_down(val)
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 @@legacy_console || window_left != 0
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
- @@ScrollConsoleScreenBuffer.call(@@hConsoleHandle, scroll_rectangle, nil, destination_origin, fill)
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
- @@output.write [
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 self.clear_screen
420
- if @@legacy_console
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
- @@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)
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
- @@output.write "\e[2J" "\e[H"
430
+ @output.write "\e[2J" "\e[H"
431
431
  end
432
432
  end
433
433
 
434
- def self.set_screen_size(rows, columns)
434
+ def set_screen_size(rows, columns)
435
435
  raise NotImplementedError
436
436
  end
437
437
 
438
- def self.hide_cursor
438
+ def hide_cursor
439
439
  size = 100
440
440
  visible = 0 # 0 means false
441
441
  cursor_info = [size, visible].pack('Li')
442
- @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
442
+ @SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
443
443
  end
444
444
 
445
- def self.show_cursor
445
+ def show_cursor
446
446
  size = 100
447
447
  visible = 1 # 1 means true
448
448
  cursor_info = [size, visible].pack('Li')
449
- @@SetConsoleCursorInfo.call(@@hConsoleHandle, cursor_info)
449
+ @SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
450
450
  end
451
451
 
452
- def self.set_winch_handler(&handler)
453
- @@winch_handler = handler
452
+ def set_winch_handler(&handler)
453
+ @winch_handler = handler
454
454
  end
455
455
 
456
- def self.prep
456
+ def prep
457
457
  # do nothing
458
458
  nil
459
459
  end
460
460
 
461
- def self.deprep(otio)
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
- 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
@@ -319,7 +319,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
319
319
  # 158 M-^^
320
320
  :ed_unassigned,
321
321
  # 159 M-^_
322
- :ed_unassigned,
322
+ :redo,
323
323
  # 160 M-SPACE
324
324
  :em_set_mark,
325
325
  # 161 M-!
@@ -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'