reline 0.3.5 → 0.6.2

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,7 +1,7 @@
1
- class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
2
- MAPPING = [
1
+ module Reline::KeyActor
2
+ VI_INSERT_MAPPING = [
3
3
  # 0 ^@
4
- :ed_unassigned,
4
+ nil,
5
5
  # 1 ^A
6
6
  :ed_insert,
7
7
  # 2 ^B
@@ -19,7 +19,7 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
19
19
  # 8 ^H
20
20
  :vi_delete_prev_char,
21
21
  # 9 ^I
22
- :ed_insert,
22
+ :complete,
23
23
  # 10 ^J
24
24
  :ed_newline,
25
25
  # 11 ^K
@@ -29,11 +29,11 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
29
29
  # 13 ^M
30
30
  :ed_newline,
31
31
  # 14 ^N
32
- :ed_insert,
32
+ :menu_complete,
33
33
  # 15 ^O
34
34
  :ed_insert,
35
35
  # 16 ^P
36
- :ed_insert,
36
+ :menu_complete_backward,
37
37
  # 17 ^Q
38
38
  :ed_ignore,
39
39
  # 18 ^R
@@ -41,7 +41,7 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
41
41
  # 19 ^S
42
42
  :vi_search_next,
43
43
  # 20 ^T
44
- :ed_insert,
44
+ :ed_transpose_chars,
45
45
  # 21 ^U
46
46
  :vi_kill_line_prev,
47
47
  # 22 ^V
@@ -51,7 +51,7 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
51
51
  # 24 ^X
52
52
  :ed_insert,
53
53
  # 25 ^Y
54
- :ed_insert,
54
+ :em_yank,
55
55
  # 26 ^Z
56
56
  :ed_insert,
57
57
  # 27 ^[
@@ -97,25 +97,25 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
97
97
  # 47 /
98
98
  :ed_insert,
99
99
  # 48 0
100
- :ed_insert,
100
+ :ed_digit,
101
101
  # 49 1
102
- :ed_insert,
102
+ :ed_digit,
103
103
  # 50 2
104
- :ed_insert,
104
+ :ed_digit,
105
105
  # 51 3
106
- :ed_insert,
106
+ :ed_digit,
107
107
  # 52 4
108
- :ed_insert,
108
+ :ed_digit,
109
109
  # 53 5
110
- :ed_insert,
110
+ :ed_digit,
111
111
  # 54 6
112
- :ed_insert,
112
+ :ed_digit,
113
113
  # 55 7
114
- :ed_insert,
114
+ :ed_digit,
115
115
  # 56 8
116
- :ed_insert,
116
+ :ed_digit,
117
117
  # 57 9
118
- :ed_insert,
118
+ :ed_digit,
119
119
  # 58 :
120
120
  :ed_insert,
121
121
  # 59 ;
@@ -257,261 +257,261 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
257
257
  # 127 ^?
258
258
  :vi_delete_prev_char,
259
259
  # 128 M-^@
260
- :ed_unassigned,
260
+ nil,
261
261
  # 129 M-^A
262
- :ed_unassigned,
262
+ nil,
263
263
  # 130 M-^B
264
- :ed_unassigned,
264
+ nil,
265
265
  # 131 M-^C
266
- :ed_unassigned,
266
+ nil,
267
267
  # 132 M-^D
268
- :ed_unassigned,
268
+ nil,
269
269
  # 133 M-^E
270
- :ed_unassigned,
270
+ nil,
271
271
  # 134 M-^F
272
- :ed_unassigned,
272
+ nil,
273
273
  # 135 M-^G
274
- :ed_unassigned,
274
+ nil,
275
275
  # 136 M-^H
276
- :ed_unassigned,
276
+ nil,
277
277
  # 137 M-^I
278
- :ed_unassigned,
278
+ nil,
279
279
  # 138 M-^J
280
280
  :key_newline,
281
281
  # 139 M-^K
282
- :ed_unassigned,
282
+ nil,
283
283
  # 140 M-^L
284
- :ed_unassigned,
284
+ nil,
285
285
  # 141 M-^M
286
286
  :key_newline,
287
287
  # 142 M-^N
288
- :ed_unassigned,
288
+ nil,
289
289
  # 143 M-^O
290
- :ed_unassigned,
290
+ nil,
291
291
  # 144 M-^P
292
- :ed_unassigned,
292
+ nil,
293
293
  # 145 M-^Q
294
- :ed_unassigned,
294
+ nil,
295
295
  # 146 M-^R
296
- :ed_unassigned,
296
+ nil,
297
297
  # 147 M-^S
298
- :ed_unassigned,
298
+ nil,
299
299
  # 148 M-^T
300
- :ed_unassigned,
300
+ nil,
301
301
  # 149 M-^U
302
- :ed_unassigned,
302
+ nil,
303
303
  # 150 M-^V
304
- :ed_unassigned,
304
+ nil,
305
305
  # 151 M-^W
306
- :ed_unassigned,
306
+ nil,
307
307
  # 152 M-^X
308
- :ed_unassigned,
308
+ nil,
309
309
  # 153 M-^Y
310
- :ed_unassigned,
310
+ nil,
311
311
  # 154 M-^Z
312
- :ed_unassigned,
312
+ nil,
313
313
  # 155 M-^[
314
- :ed_unassigned,
314
+ nil,
315
315
  # 156 M-^\
316
- :ed_unassigned,
316
+ nil,
317
317
  # 157 M-^]
318
- :ed_unassigned,
318
+ nil,
319
319
  # 158 M-^^
320
- :ed_unassigned,
320
+ nil,
321
321
  # 159 M-^_
322
- :ed_unassigned,
322
+ nil,
323
323
  # 160 M-SPACE
324
- :ed_unassigned,
324
+ nil,
325
325
  # 161 M-!
326
- :ed_unassigned,
326
+ nil,
327
327
  # 162 M-"
328
- :ed_unassigned,
328
+ nil,
329
329
  # 163 M-#
330
- :ed_unassigned,
330
+ nil,
331
331
  # 164 M-$
332
- :ed_unassigned,
332
+ nil,
333
333
  # 165 M-%
334
- :ed_unassigned,
334
+ nil,
335
335
  # 166 M-&
336
- :ed_unassigned,
336
+ nil,
337
337
  # 167 M-'
338
- :ed_unassigned,
338
+ nil,
339
339
  # 168 M-(
340
- :ed_unassigned,
340
+ nil,
341
341
  # 169 M-)
342
- :ed_unassigned,
342
+ nil,
343
343
  # 170 M-*
344
- :ed_unassigned,
344
+ nil,
345
345
  # 171 M-+
346
- :ed_unassigned,
346
+ nil,
347
347
  # 172 M-,
348
- :ed_unassigned,
348
+ nil,
349
349
  # 173 M--
350
- :ed_unassigned,
350
+ nil,
351
351
  # 174 M-.
352
- :ed_unassigned,
352
+ nil,
353
353
  # 175 M-/
354
- :ed_unassigned,
354
+ nil,
355
355
  # 176 M-0
356
- :ed_unassigned,
356
+ nil,
357
357
  # 177 M-1
358
- :ed_unassigned,
358
+ nil,
359
359
  # 178 M-2
360
- :ed_unassigned,
360
+ nil,
361
361
  # 179 M-3
362
- :ed_unassigned,
362
+ nil,
363
363
  # 180 M-4
364
- :ed_unassigned,
364
+ nil,
365
365
  # 181 M-5
366
- :ed_unassigned,
366
+ nil,
367
367
  # 182 M-6
368
- :ed_unassigned,
368
+ nil,
369
369
  # 183 M-7
370
- :ed_unassigned,
370
+ nil,
371
371
  # 184 M-8
372
- :ed_unassigned,
372
+ nil,
373
373
  # 185 M-9
374
- :ed_unassigned,
374
+ nil,
375
375
  # 186 M-:
376
- :ed_unassigned,
376
+ nil,
377
377
  # 187 M-;
378
- :ed_unassigned,
378
+ nil,
379
379
  # 188 M-<
380
- :ed_unassigned,
380
+ nil,
381
381
  # 189 M-=
382
- :ed_unassigned,
382
+ nil,
383
383
  # 190 M->
384
- :ed_unassigned,
384
+ nil,
385
385
  # 191 M-?
386
- :ed_unassigned,
386
+ nil,
387
387
  # 192 M-@
388
- :ed_unassigned,
388
+ nil,
389
389
  # 193 M-A
390
- :ed_unassigned,
390
+ nil,
391
391
  # 194 M-B
392
- :ed_unassigned,
392
+ nil,
393
393
  # 195 M-C
394
- :ed_unassigned,
394
+ nil,
395
395
  # 196 M-D
396
- :ed_unassigned,
396
+ nil,
397
397
  # 197 M-E
398
- :ed_unassigned,
398
+ nil,
399
399
  # 198 M-F
400
- :ed_unassigned,
400
+ nil,
401
401
  # 199 M-G
402
- :ed_unassigned,
402
+ nil,
403
403
  # 200 M-H
404
- :ed_unassigned,
404
+ nil,
405
405
  # 201 M-I
406
- :ed_unassigned,
406
+ nil,
407
407
  # 202 M-J
408
- :ed_unassigned,
408
+ nil,
409
409
  # 203 M-K
410
- :ed_unassigned,
410
+ nil,
411
411
  # 204 M-L
412
- :ed_unassigned,
412
+ nil,
413
413
  # 205 M-M
414
- :ed_unassigned,
414
+ nil,
415
415
  # 206 M-N
416
- :ed_unassigned,
416
+ nil,
417
417
  # 207 M-O
418
- :ed_unassigned,
418
+ nil,
419
419
  # 208 M-P
420
- :ed_unassigned,
420
+ nil,
421
421
  # 209 M-Q
422
- :ed_unassigned,
422
+ nil,
423
423
  # 210 M-R
424
- :ed_unassigned,
424
+ nil,
425
425
  # 211 M-S
426
- :ed_unassigned,
426
+ nil,
427
427
  # 212 M-T
428
- :ed_unassigned,
428
+ nil,
429
429
  # 213 M-U
430
- :ed_unassigned,
430
+ nil,
431
431
  # 214 M-V
432
- :ed_unassigned,
432
+ nil,
433
433
  # 215 M-W
434
- :ed_unassigned,
434
+ nil,
435
435
  # 216 M-X
436
- :ed_unassigned,
436
+ nil,
437
437
  # 217 M-Y
438
- :ed_unassigned,
438
+ nil,
439
439
  # 218 M-Z
440
- :ed_unassigned,
440
+ nil,
441
441
  # 219 M-[
442
- :ed_unassigned,
442
+ nil,
443
443
  # 220 M-\
444
- :ed_unassigned,
444
+ nil,
445
445
  # 221 M-]
446
- :ed_unassigned,
446
+ nil,
447
447
  # 222 M-^
448
- :ed_unassigned,
448
+ nil,
449
449
  # 223 M-_
450
- :ed_unassigned,
450
+ nil,
451
451
  # 224 M-`
452
- :ed_unassigned,
452
+ nil,
453
453
  # 225 M-a
454
- :ed_unassigned,
454
+ nil,
455
455
  # 226 M-b
456
- :ed_unassigned,
456
+ nil,
457
457
  # 227 M-c
458
- :ed_unassigned,
458
+ nil,
459
459
  # 228 M-d
460
- :ed_unassigned,
460
+ nil,
461
461
  # 229 M-e
462
- :ed_unassigned,
462
+ nil,
463
463
  # 230 M-f
464
- :ed_unassigned,
464
+ nil,
465
465
  # 231 M-g
466
- :ed_unassigned,
466
+ nil,
467
467
  # 232 M-h
468
- :ed_unassigned,
468
+ nil,
469
469
  # 233 M-i
470
- :ed_unassigned,
470
+ nil,
471
471
  # 234 M-j
472
- :ed_unassigned,
472
+ nil,
473
473
  # 235 M-k
474
- :ed_unassigned,
474
+ nil,
475
475
  # 236 M-l
476
- :ed_unassigned,
476
+ nil,
477
477
  # 237 M-m
478
- :ed_unassigned,
478
+ nil,
479
479
  # 238 M-n
480
- :ed_unassigned,
480
+ nil,
481
481
  # 239 M-o
482
- :ed_unassigned,
482
+ nil,
483
483
  # 240 M-p
484
- :ed_unassigned,
484
+ nil,
485
485
  # 241 M-q
486
- :ed_unassigned,
486
+ nil,
487
487
  # 242 M-r
488
- :ed_unassigned,
488
+ nil,
489
489
  # 243 M-s
490
- :ed_unassigned,
490
+ nil,
491
491
  # 244 M-t
492
- :ed_unassigned,
492
+ nil,
493
493
  # 245 M-u
494
- :ed_unassigned,
494
+ nil,
495
495
  # 246 M-v
496
- :ed_unassigned,
496
+ nil,
497
497
  # 247 M-w
498
- :ed_unassigned,
498
+ nil,
499
499
  # 248 M-x
500
- :ed_unassigned,
500
+ nil,
501
501
  # 249 M-y
502
- :ed_unassigned,
502
+ nil,
503
503
  # 250 M-z
504
- :ed_unassigned,
504
+ nil,
505
505
  # 251 M-{
506
- :ed_unassigned,
506
+ nil,
507
507
  # 252 M-|
508
- :ed_unassigned,
508
+ nil,
509
509
  # 253 M-}
510
- :ed_unassigned,
510
+ nil,
511
511
  # 254 M-~
512
- :ed_unassigned,
512
+ nil,
513
513
  # 255 M-^?
514
- :ed_unassigned
514
+ nil
515
515
  # EOF
516
516
  ]
517
517
  end
@@ -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'
@@ -1,103 +1,117 @@
1
1
  class Reline::KeyStroke
2
- def initialize(config)
2
+ ESC_BYTE = 27
3
+ CSI_PARAMETER_BYTES_RANGE = 0x30..0x3f
4
+ CSI_INTERMEDIATE_BYTES_RANGE = (0x20..0x2f)
5
+
6
+ attr_accessor :encoding
7
+
8
+ def initialize(config, encoding)
3
9
  @config = config
10
+ @encoding = encoding
4
11
  end
5
12
 
6
- def compress_meta_key(ary)
7
- return ary unless @config.convert_meta
8
- ary.inject([]) { |result, key|
9
- if result.size > 0 and result.last == "\e".ord
10
- result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
13
+ # Input exactly matches to a key sequence
14
+ MATCHING = :matching
15
+ # Input partially matches to a key sequence
16
+ MATCHED = :matched
17
+ # Input matches to a key sequence and the key sequence is a prefix of another key sequence
18
+ MATCHING_MATCHED = :matching_matched
19
+ # Input does not match to any key sequence
20
+ UNMATCHED = :unmatched
21
+
22
+ def match_status(input)
23
+ matching = key_mapping.matching?(input)
24
+ matched = key_mapping.get(input)
25
+ if matching && matched
26
+ MATCHING_MATCHED
27
+ elsif matching
28
+ MATCHING
29
+ elsif matched
30
+ MATCHED
31
+ elsif input[0] == ESC_BYTE
32
+ match_unknown_escape_sequence(input, vi_mode: @config.editing_mode_is?(:vi_insert, :vi_command))
33
+ else
34
+ s = input.pack('c*').force_encoding(@encoding)
35
+ if s.valid_encoding?
36
+ s.size == 1 ? MATCHED : UNMATCHED
11
37
  else
12
- result << key
38
+ # Invalid string is MATCHING (part of valid string) or MATCHED (invalid bytes to be ignored)
39
+ MATCHING_MATCHED
13
40
  end
14
- result
15
- }
41
+ end
16
42
  end
17
43
 
18
- def start_with?(me, other)
19
- compressed_me = compress_meta_key(me)
20
- compressed_other = compress_meta_key(other)
21
- i = 0
22
- loop do
23
- my_c = compressed_me[i]
24
- other_c = compressed_other[i]
25
- other_is_last = (i + 1) == compressed_other.size
26
- me_is_last = (i + 1) == compressed_me.size
27
- if my_c != other_c
28
- if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
29
- return true
30
- else
31
- return false
32
- end
33
- elsif other_is_last
34
- return true
35
- elsif me_is_last
36
- return false
37
- end
38
- i += 1
44
+ def expand(input)
45
+ matched_bytes = nil
46
+ (1..input.size).each do |i|
47
+ bytes = input.take(i)
48
+ status = match_status(bytes)
49
+ matched_bytes = bytes if status == MATCHED || status == MATCHING_MATCHED
50
+ break if status == MATCHED || status == UNMATCHED
39
51
  end
40
- end
52
+ return [[], []] unless matched_bytes
41
53
 
42
- def equal?(me, other)
43
- case me
44
- when Array
45
- compressed_me = compress_meta_key(me)
46
- compressed_other = compress_meta_key(other)
47
- compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
48
- when Integer
49
- if other.is_a?(Reline::Key)
50
- if other.combined_char == "\e".ord
51
- false
52
- else
53
- other.combined_char == me
54
- end
55
- else
56
- me == other
54
+ func = key_mapping.get(matched_bytes)
55
+ s = matched_bytes.pack('c*').force_encoding(@encoding)
56
+ if func.is_a?(Array)
57
+ # Perform simple macro expansion for single byte key bindings.
58
+ # Multibyte key bindings and recursive macro expansion are not supported yet.
59
+ macro = func.pack('c*').force_encoding(@encoding)
60
+ keys = macro.chars.map do |c|
61
+ f = key_mapping.get(c.bytes)
62
+ Reline::Key.new(c, f.is_a?(Symbol) ? f : :ed_insert, false)
57
63
  end
58
- when Reline::Key
59
- if other.is_a?(Integer)
60
- me.combined_char == other
64
+ elsif func
65
+ keys = [Reline::Key.new(s, func, false)]
66
+ else
67
+ if s.valid_encoding? && s.size == 1
68
+ keys = [Reline::Key.new(s, :ed_insert, false)]
61
69
  else
62
- me == other
70
+ keys = []
63
71
  end
64
72
  end
65
- end
66
73
 
67
- def match_status(input)
68
- key_mapping.keys.select { |lhs|
69
- start_with?(lhs, input)
70
- }.tap { |it|
71
- return :matched if it.size == 1 && equal?(it[0], input)
72
- return :matching if it.size == 1 && !equal?(it[0], input)
73
- return :matched if it.max_by(&:size)&.size&.< input.size
74
- return :matching if it.size > 1
75
- }
76
- key_mapping.keys.select { |lhs|
77
- start_with?(input, lhs)
78
- }.tap { |it|
79
- return it.size > 0 ? :matched : :unmatched
80
- }
74
+ [keys, input.drop(matched_bytes.size)]
81
75
  end
82
76
 
83
- def expand(input)
84
- input = compress_meta_key(input)
85
- lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
86
- return input unless lhs
87
- rhs = key_mapping[lhs]
77
+ private
88
78
 
89
- case rhs
90
- when String
91
- rhs_bytes = rhs.bytes
92
- expand(expand(rhs_bytes) + expand(input.drop(lhs.size)))
93
- when Symbol
94
- [rhs] + expand(input.drop(lhs.size))
95
- when Array
96
- rhs
79
+ # returns match status of CSI/SS3 sequence and matched length
80
+ def match_unknown_escape_sequence(input, vi_mode: false)
81
+ idx = 0
82
+ return UNMATCHED unless input[idx] == ESC_BYTE
83
+ idx += 1
84
+ idx += 1 if input[idx] == ESC_BYTE
85
+
86
+ case input[idx]
87
+ when nil
88
+ if idx == 1 # `ESC`
89
+ return MATCHING_MATCHED
90
+ else # `ESC ESC`
91
+ return MATCHING
92
+ end
93
+ when 91 # == '['.ord
94
+ # CSI sequence `ESC [ ... char`
95
+ idx += 1
96
+ idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
97
+ idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
98
+ when 79 # == 'O'.ord
99
+ # SS3 sequence `ESC O char`
100
+ idx += 1
101
+ else
102
+ # `ESC char` or `ESC ESC char`
103
+ return UNMATCHED if vi_mode
97
104
  end
98
- end
99
105
 
100
- private
106
+ case input.size
107
+ when idx
108
+ MATCHING
109
+ when idx + 1
110
+ MATCHED
111
+ else
112
+ UNMATCHED
113
+ end
114
+ end
101
115
 
102
116
  def key_mapping
103
117
  @config.key_bindings
@@ -14,7 +14,7 @@ class Reline::KillRing
14
14
  end
15
15
 
16
16
  def ==(other)
17
- object_id == other.object_id
17
+ equal?(other)
18
18
  end
19
19
  end
20
20
 
@@ -68,7 +68,7 @@ class Reline::KillRing
68
68
  def append(string, before_p = false)
69
69
  case @state
70
70
  when State::FRESH, State::YANK
71
- @ring << RingPoint.new(string)
71
+ @ring << RingPoint.new(+string)
72
72
  @state = State::CONTINUED
73
73
  when State::CONTINUED, State::PROCESSED
74
74
  if before_p