reline 0.3.2 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -17,7 +17,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
17
17
  # 7 ^G
18
18
  :ed_unassigned,
19
19
  # 8 ^H
20
- :ed_unassigned,
20
+ :ed_prev_char,
21
21
  # 9 ^I
22
22
  :ed_unassigned,
23
23
  # 10 ^J
@@ -41,7 +41,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
41
41
  # 19 ^S
42
42
  :ed_ignore,
43
43
  # 20 ^T
44
- :ed_unassigned,
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::ViCommand < Reline::KeyActor::Base
51
51
  # 24 ^X
52
52
  :ed_unassigned,
53
53
  # 25 ^Y
54
- :ed_unassigned,
54
+ :em_yank,
55
55
  # 26 ^Z
56
56
  :ed_unassigned,
57
57
  # 27 ^[
@@ -75,7 +75,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
75
75
  # 36 $
76
76
  :ed_move_to_end,
77
77
  # 37 %
78
- :vi_match,
78
+ :ed_unassigned,
79
79
  # 38 &
80
80
  :ed_unassigned,
81
81
  # 39 '
@@ -89,11 +89,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
89
89
  # 43 +
90
90
  :ed_next_history,
91
91
  # 44 ,
92
- :vi_repeat_prev_char,
92
+ :ed_unassigned,
93
93
  # 45 -
94
94
  :ed_prev_history,
95
95
  # 46 .
96
- :vi_redo,
96
+ :ed_unassigned,
97
97
  # 47 /
98
98
  :vi_search_prev,
99
99
  # 48 0
@@ -117,9 +117,9 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
117
117
  # 57 9
118
118
  :ed_argument_digit,
119
119
  # 58 :
120
- :ed_command,
120
+ :ed_unassigned,
121
121
  # 59 ;
122
- :vi_repeat_next_char,
122
+ :ed_unassigned,
123
123
  # 60 <
124
124
  :ed_unassigned,
125
125
  # 61 =
@@ -157,21 +157,21 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
157
157
  # 77 M
158
158
  :ed_unassigned,
159
159
  # 78 N
160
- :vi_repeat_search_prev,
160
+ :ed_unassigned,
161
161
  # 79 O
162
- :ed_sequence_lead_in,
162
+ :ed_unassigned,
163
163
  # 80 P
164
164
  :vi_paste_prev,
165
165
  # 81 Q
166
166
  :ed_unassigned,
167
167
  # 82 R
168
- :vi_replace_mode,
168
+ :ed_unassigned,
169
169
  # 83 S
170
- :vi_substitute_line,
170
+ :ed_unassigned,
171
171
  # 84 T
172
172
  :vi_to_prev_char,
173
173
  # 85 U
174
- :vi_undo_line,
174
+ :ed_unassigned,
175
175
  # 86 V
176
176
  :ed_unassigned,
177
177
  # 87 W
@@ -179,11 +179,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
179
179
  # 88 X
180
180
  :ed_delete_prev_char,
181
181
  # 89 Y
182
- :vi_yank_end,
182
+ :ed_unassigned,
183
183
  # 90 Z
184
184
  :ed_unassigned,
185
185
  # 91 [
186
- :ed_sequence_lead_in,
186
+ :ed_unassigned,
187
187
  # 92 \
188
188
  :ed_unassigned,
189
189
  # 93 ]
@@ -191,7 +191,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
191
191
  # 94 ^
192
192
  :vi_first_print,
193
193
  # 95 _
194
- :vi_history_word,
194
+ :ed_unassigned,
195
195
  # 96 `
196
196
  :ed_unassigned,
197
197
  # 97 a
@@ -221,7 +221,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
221
221
  # 109 m
222
222
  :ed_unassigned,
223
223
  # 110 n
224
- :vi_repeat_search_next,
224
+ :ed_unassigned,
225
225
  # 111 o
226
226
  :ed_unassigned,
227
227
  # 112 p
@@ -231,11 +231,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
231
231
  # 114 r
232
232
  :vi_replace_char,
233
233
  # 115 s
234
- :vi_substitute_char,
234
+ :ed_unassigned,
235
235
  # 116 t
236
236
  :vi_to_next_char,
237
237
  # 117 u
238
- :vi_undo,
238
+ :ed_unassigned,
239
239
  # 118 v
240
240
  :vi_histedit,
241
241
  # 119 w
@@ -253,9 +253,9 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
253
253
  # 125 }
254
254
  :ed_unassigned,
255
255
  # 126 ~
256
- :vi_change_case,
257
- # 127 ^?
258
256
  :ed_unassigned,
257
+ # 127 ^?
258
+ :em_delete_prev_char,
259
259
  # 128 M-^@
260
260
  :ed_unassigned,
261
261
  # 129 M-^A
@@ -415,7 +415,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
415
415
  # 206 M-N
416
416
  :ed_unassigned,
417
417
  # 207 M-O
418
- :ed_sequence_lead_in,
418
+ :ed_unassigned,
419
419
  # 208 M-P
420
420
  :ed_unassigned,
421
421
  # 209 M-Q
@@ -439,7 +439,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
439
439
  # 218 M-Z
440
440
  :ed_unassigned,
441
441
  # 219 M-[
442
- :ed_sequence_lead_in,
442
+ :ed_unassigned,
443
443
  # 220 M-\
444
444
  :ed_unassigned,
445
445
  # 221 M-]
@@ -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
@@ -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 ^[
@@ -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,104 +1,108 @@
1
1
  class Reline::KeyStroke
2
+ ESC_BYTE = 27
3
+ CSI_PARAMETER_BYTES_RANGE = 0x30..0x3f
4
+ CSI_INTERMEDIATE_BYTES_RANGE = (0x20..0x2f)
5
+
2
6
  def initialize(config)
3
7
  @config = config
4
8
  end
5
9
 
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)
11
- else
12
- result << key
13
- end
14
- result
15
- }
16
- end
10
+ # Input exactly matches to a key sequence
11
+ MATCHING = :matching
12
+ # Input partially matches to a key sequence
13
+ MATCHED = :matched
14
+ # Input matches to a key sequence and the key sequence is a prefix of another key sequence
15
+ MATCHING_MATCHED = :matching_matched
16
+ # Input does not match to any key sequence
17
+ UNMATCHED = :unmatched
17
18
 
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
39
- end
40
- end
19
+ def match_status(input)
20
+ matching = key_mapping.matching?(input)
21
+ matched = key_mapping.get(input)
41
22
 
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
57
- end
58
- when Reline::Key
59
- if other.is_a?(Integer)
60
- me.combined_char == other
61
- else
62
- me == other
63
- end
64
- end
65
- end
23
+ # FIXME: Workaround for single byte. remove this after MAPPING is merged into KeyActor.
24
+ matched ||= input.size == 1
25
+ matching ||= input == [ESC_BYTE]
66
26
 
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
- }
27
+ if matching && matched
28
+ MATCHING_MATCHED
29
+ elsif matching
30
+ MATCHING
31
+ elsif matched
32
+ MATCHED
33
+ elsif input[0] == ESC_BYTE
34
+ match_unknown_escape_sequence(input, vi_mode: @config.editing_mode_is?(:vi_insert, :vi_command))
35
+ elsif input.size == 1
36
+ MATCHED
37
+ else
38
+ UNMATCHED
39
+ end
81
40
  end
82
41
 
83
42
  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]
43
+ matched_bytes = nil
44
+ (1..input.size).each do |i|
45
+ bytes = input.take(i)
46
+ status = match_status(bytes)
47
+ matched_bytes = bytes if status == MATCHED || status == MATCHING_MATCHED
48
+ end
49
+ return [[], []] unless matched_bytes
88
50
 
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
51
+ func = key_mapping.get(matched_bytes)
52
+ if func.is_a?(Array)
53
+ keys = func.map { |c| Reline::Key.new(c, c, false) }
54
+ elsif func
55
+ keys = [Reline::Key.new(func, func, false)]
56
+ elsif matched_bytes.size == 1
57
+ keys = [Reline::Key.new(matched_bytes.first, matched_bytes.first, false)]
58
+ elsif matched_bytes.size == 2 && matched_bytes[0] == ESC_BYTE
59
+ keys = [Reline::Key.new(matched_bytes[1], matched_bytes[1] | 0b10000000, true)]
60
+ else
61
+ keys = []
97
62
  end
63
+
64
+ [keys, input.drop(matched_bytes.size)]
98
65
  end
99
66
 
100
67
  private
101
68
 
69
+ # returns match status of CSI/SS3 sequence and matched length
70
+ def match_unknown_escape_sequence(input, vi_mode: false)
71
+ idx = 0
72
+ return UNMATCHED unless input[idx] == ESC_BYTE
73
+ idx += 1
74
+ idx += 1 if input[idx] == ESC_BYTE
75
+
76
+ case input[idx]
77
+ when nil
78
+ if idx == 1 # `ESC`
79
+ return MATCHING_MATCHED
80
+ else # `ESC ESC`
81
+ return MATCHING
82
+ end
83
+ when 91 # == '['.ord
84
+ # CSI sequence `ESC [ ... char`
85
+ idx += 1
86
+ idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
87
+ idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
88
+ when 79 # == 'O'.ord
89
+ # SS3 sequence `ESC O char`
90
+ idx += 1
91
+ else
92
+ # `ESC char` or `ESC ESC char`
93
+ return UNMATCHED if vi_mode
94
+ end
95
+
96
+ case input.size
97
+ when idx
98
+ MATCHING
99
+ when idx + 1
100
+ MATCHED
101
+ else
102
+ UNMATCHED
103
+ end
104
+ end
105
+
102
106
  def key_mapping
103
107
  @config.key_bindings
104
108
  end
@@ -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