reline 0.3.9 → 0.6.1
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 +8 -1
- data/lib/reline/config.rb +95 -123
- data/lib/reline/face.rb +199 -0
- data/lib/reline/history.rb +4 -4
- data/lib/reline/io/ansi.rb +318 -0
- data/lib/reline/io/dumb.rb +120 -0
- data/lib/reline/{windows.rb → io/windows.rb} +182 -153
- data/lib/reline/io.rb +55 -0
- data/lib/reline/key_actor/base.rb +27 -9
- data/lib/reline/key_actor/composite.rb +17 -0
- data/lib/reline/key_actor/emacs.rb +103 -103
- data/lib/reline/key_actor/vi_command.rb +188 -188
- data/lib/reline/key_actor/vi_insert.rb +144 -144
- data/lib/reline/key_actor.rb +1 -0
- data/lib/reline/key_stroke.rb +75 -104
- data/lib/reline/kill_ring.rb +2 -2
- data/lib/reline/line_editor.rb +1175 -2121
- data/lib/reline/unicode/east_asian_width.rb +1289 -1192
- data/lib/reline/unicode.rb +218 -445
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +143 -224
- metadata +13 -11
- data/lib/reline/ansi.rb +0 -363
- data/lib/reline/general_io.rb +0 -116
- data/lib/reline/terminfo.rb +0 -160
data/lib/reline/key_stroke.rb
CHANGED
@@ -3,142 +3,113 @@ class Reline::KeyStroke
|
|
3
3
|
CSI_PARAMETER_BYTES_RANGE = 0x30..0x3f
|
4
4
|
CSI_INTERMEDIATE_BYTES_RANGE = (0x20..0x2f)
|
5
5
|
|
6
|
-
|
7
|
-
@config = config
|
8
|
-
end
|
6
|
+
attr_accessor :encoding
|
9
7
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
if result.size > 0 and result.last == "\e".ord
|
14
|
-
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
15
|
-
else
|
16
|
-
result << key
|
17
|
-
end
|
18
|
-
result
|
19
|
-
}
|
8
|
+
def initialize(config, encoding)
|
9
|
+
@config = config
|
10
|
+
@encoding = encoding
|
20
11
|
end
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
me_is_last = (i + 1) == compressed_me.size
|
31
|
-
if my_c != other_c
|
32
|
-
if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
|
33
|
-
return true
|
34
|
-
else
|
35
|
-
return false
|
36
|
-
end
|
37
|
-
elsif other_is_last
|
38
|
-
return true
|
39
|
-
elsif me_is_last
|
40
|
-
return false
|
41
|
-
end
|
42
|
-
i += 1
|
43
|
-
end
|
44
|
-
end
|
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
|
45
21
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
when Reline::Key
|
63
|
-
if other.is_a?(Integer)
|
64
|
-
me.combined_char == other
|
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
|
65
37
|
else
|
66
|
-
|
38
|
+
# Invalid string is MATCHING (part of valid string) or MATCHED (invalid bytes to be ignored)
|
39
|
+
MATCHING_MATCHED
|
67
40
|
end
|
68
41
|
end
|
69
42
|
end
|
70
43
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
return :matching if it.size > 1
|
79
|
-
}
|
80
|
-
if key_mapping.keys.any? { |lhs| start_with?(input, lhs) }
|
81
|
-
:matched
|
82
|
-
else
|
83
|
-
match_unknown_escape_sequence(input).first
|
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
|
84
51
|
end
|
85
|
-
|
52
|
+
return [[], []] unless matched_bytes
|
86
53
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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)
|
63
|
+
end
|
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)]
|
96
69
|
else
|
97
|
-
|
70
|
+
keys = []
|
98
71
|
end
|
99
72
|
end
|
100
|
-
rhs = key_mapping[lhs]
|
101
73
|
|
102
|
-
|
103
|
-
when String
|
104
|
-
rhs_bytes = rhs.bytes
|
105
|
-
expand(expand(rhs_bytes) + expand(input.drop(lhs.size)))
|
106
|
-
when Symbol
|
107
|
-
[rhs] + expand(input.drop(lhs.size))
|
108
|
-
when Array
|
109
|
-
rhs
|
110
|
-
end
|
74
|
+
[keys, input.drop(matched_bytes.size)]
|
111
75
|
end
|
112
76
|
|
113
77
|
private
|
114
78
|
|
115
79
|
# returns match status of CSI/SS3 sequence and matched length
|
116
|
-
def match_unknown_escape_sequence(input)
|
80
|
+
def match_unknown_escape_sequence(input, vi_mode: false)
|
117
81
|
idx = 0
|
118
|
-
return
|
82
|
+
return UNMATCHED unless input[idx] == ESC_BYTE
|
119
83
|
idx += 1
|
120
84
|
idx += 1 if input[idx] == ESC_BYTE
|
121
85
|
|
122
86
|
case input[idx]
|
123
87
|
when nil
|
124
|
-
|
88
|
+
if idx == 1 # `ESC`
|
89
|
+
return MATCHING_MATCHED
|
90
|
+
else # `ESC ESC`
|
91
|
+
return MATCHING
|
92
|
+
end
|
125
93
|
when 91 # == '['.ord
|
126
|
-
# CSI sequence
|
94
|
+
# CSI sequence `ESC [ ... char`
|
127
95
|
idx += 1
|
128
96
|
idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
|
129
97
|
idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
|
130
|
-
input[idx] ? [:matched, idx + 1] : [:matching, nil]
|
131
98
|
when 79 # == 'O'.ord
|
132
|
-
# SS3 sequence
|
133
|
-
|
99
|
+
# SS3 sequence `ESC O char`
|
100
|
+
idx += 1
|
134
101
|
else
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
102
|
+
# `ESC char` or `ESC ESC char`
|
103
|
+
return UNMATCHED if vi_mode
|
104
|
+
end
|
105
|
+
|
106
|
+
case input.size
|
107
|
+
when idx
|
108
|
+
MATCHING
|
109
|
+
when idx + 1
|
110
|
+
MATCHED
|
111
|
+
else
|
112
|
+
UNMATCHED
|
142
113
|
end
|
143
114
|
end
|
144
115
|
|
data/lib/reline/kill_ring.rb
CHANGED
@@ -14,7 +14,7 @@ class Reline::KillRing
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def ==(other)
|
17
|
-
|
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
|