reline 0.3.0 → 0.3.6
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 +25 -1
- data/lib/reline/ansi.rb +11 -4
- data/lib/reline/config.rb +17 -11
- data/lib/reline/general_io.rb +10 -0
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +50 -7
- data/lib/reline/line_editor.rb +235 -282
- data/lib/reline/terminfo.rb +44 -18
- data/lib/reline/unicode/east_asian_width.rb +88 -56
- data/lib/reline/unicode.rb +30 -53
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +7 -3
- data/lib/reline.rb +115 -80
- metadata +4 -5
- data/lib/reline/sibori.rb +0 -170
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3075f4003cf263e4652fc0dec716c71b55b597e6cbdc8cdb5297181b72780b57
|
4
|
+
data.tar.gz: 78eb2e13f17bc0c7ae34b425effe29bf40a30b355af7d0efd271823c2cdde521
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fd55d135c7b1aaffaff575f930bdb6365c202a1d15b5943d3dd9f678f416ba312b21c836ef8b78d11ee9942c4e0f0ac50d395633196bd649bd23a2fa6096456
|
7
|
+
data.tar.gz: 43fe692b243560a81da41a48f4cb5cdf05514f85788bbc6b54bba72aef4d5e7258e73c2a84622c80e51adf36345cd9e7595455f8301e09c1f299f7b2ec147ff2
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
[](https://badge.fury.io/rb/reline)
|
2
|
+
[](https://github.com/ruby/reline/actions/workflows/reline.yml)
|
2
3
|
|
3
4
|
This is a screen capture of *IRB improved by Reline*.
|
4
5
|
|
@@ -54,6 +55,29 @@ end
|
|
54
55
|
|
55
56
|
See also: [test/reline/yamatanooroti/multiline_repl](https://github.com/ruby/reline/blob/master/test/reline/yamatanooroti/multiline_repl)
|
56
57
|
|
58
|
+
## Contributing
|
59
|
+
|
60
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/reline.
|
61
|
+
|
62
|
+
### Run tests
|
63
|
+
|
64
|
+
> **Note**
|
65
|
+
> Please make sure you have `libvterm` installed for `yamatanooroti` tests (integration tests).
|
66
|
+
|
67
|
+
If you use Homebrew, you can install it by running `brew install libvterm`.
|
68
|
+
|
69
|
+
```bash
|
70
|
+
WITH_VTERM=1 bundle install
|
71
|
+
WITH_VTERM=1 bundle exec rake test test_yamatanooroti
|
72
|
+
```
|
73
|
+
|
74
|
+
## Releasing
|
75
|
+
|
76
|
+
```bash
|
77
|
+
rake release
|
78
|
+
gh release create vX.Y.Z --generate-notes
|
79
|
+
```
|
80
|
+
|
57
81
|
## License
|
58
82
|
|
59
83
|
The gem is available as open source under the terms of the [Ruby License](https://www.ruby-lang.org/en/about/license.txt).
|
data/lib/reline/ansi.rb
CHANGED
@@ -7,6 +7,9 @@ class Reline::ANSI
|
|
7
7
|
CAPNAME_KEY_BINDINGS = {
|
8
8
|
'khome' => :ed_move_to_beg,
|
9
9
|
'kend' => :ed_move_to_end,
|
10
|
+
'kdch1' => :key_delete,
|
11
|
+
'kpp' => :ed_search_prev_history,
|
12
|
+
'knp' => :ed_search_next_history,
|
10
13
|
'kcuu1' => :ed_prev_history,
|
11
14
|
'kcud1' => :ed_next_history,
|
12
15
|
'kcuf1' => :ed_next_char,
|
@@ -29,8 +32,8 @@ class Reline::ANSI
|
|
29
32
|
false
|
30
33
|
end
|
31
34
|
|
32
|
-
def self.set_default_key_bindings(config)
|
33
|
-
if Reline::Terminfo.enabled?
|
35
|
+
def self.set_default_key_bindings(config, allow_terminfo: true)
|
36
|
+
if allow_terminfo && Reline::Terminfo.enabled?
|
34
37
|
set_default_key_bindings_terminfo(config)
|
35
38
|
else
|
36
39
|
set_default_key_bindings_comprehensive_list(config)
|
@@ -142,6 +145,10 @@ class Reline::ANSI
|
|
142
145
|
@@output = val
|
143
146
|
end
|
144
147
|
|
148
|
+
def self.with_raw_input
|
149
|
+
@@input.raw { yield }
|
150
|
+
end
|
151
|
+
|
145
152
|
@@buf = []
|
146
153
|
def self.inner_getc
|
147
154
|
unless @@buf.empty?
|
@@ -150,7 +157,7 @@ class Reline::ANSI
|
|
150
157
|
until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
|
151
158
|
Reline.core.line_editor.resize
|
152
159
|
end
|
153
|
-
(c == 0x16 && @@input.raw(min: 0,
|
160
|
+
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
154
161
|
rescue Errno::EIO
|
155
162
|
# Maybe the I/O has been closed.
|
156
163
|
nil
|
@@ -199,7 +206,7 @@ class Reline::ANSI
|
|
199
206
|
end
|
200
207
|
|
201
208
|
def self.in_pasting?
|
202
|
-
@@in_bracketed_paste_mode or (not
|
209
|
+
@@in_bracketed_paste_mode or (not empty_buffer?)
|
203
210
|
end
|
204
211
|
|
205
212
|
def self.empty_buffer?
|
data/lib/reline/config.rb
CHANGED
@@ -45,6 +45,8 @@ class Reline::Config
|
|
45
45
|
attr_accessor v
|
46
46
|
end
|
47
47
|
|
48
|
+
attr_accessor :autocompletion
|
49
|
+
|
48
50
|
def initialize
|
49
51
|
@additional_key_bindings = {} # from inputrc
|
50
52
|
@additional_key_bindings[:emacs] = {}
|
@@ -55,6 +57,7 @@ class Reline::Config
|
|
55
57
|
@if_stack = nil
|
56
58
|
@editing_mode_label = :emacs
|
57
59
|
@keymap_label = :emacs
|
60
|
+
@keymap_prefix = []
|
58
61
|
@key_actors = {}
|
59
62
|
@key_actors[:emacs] = Reline::KeyActor::Emacs.new
|
60
63
|
@key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
|
@@ -90,15 +93,7 @@ class Reline::Config
|
|
90
93
|
end
|
91
94
|
|
92
95
|
def editing_mode_is?(*val)
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
def autocompletion=(val)
|
97
|
-
@autocompletion = val
|
98
|
-
end
|
99
|
-
|
100
|
-
def autocompletion
|
101
|
-
@autocompletion
|
96
|
+
val.any?(@editing_mode_label)
|
102
97
|
end
|
103
98
|
|
104
99
|
def keymap
|
@@ -221,7 +216,7 @@ class Reline::Config
|
|
221
216
|
key, func_name = $1, $2
|
222
217
|
keystroke, func = bind_key(key, func_name)
|
223
218
|
next unless keystroke
|
224
|
-
@additional_key_bindings[@keymap_label][keystroke] = func
|
219
|
+
@additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
|
225
220
|
end
|
226
221
|
end
|
227
222
|
unless @if_stack.empty?
|
@@ -292,18 +287,29 @@ class Reline::Config
|
|
292
287
|
when 'emacs'
|
293
288
|
@editing_mode_label = :emacs
|
294
289
|
@keymap_label = :emacs
|
290
|
+
@keymap_prefix = []
|
295
291
|
when 'vi'
|
296
292
|
@editing_mode_label = :vi_insert
|
297
293
|
@keymap_label = :vi_insert
|
294
|
+
@keymap_prefix = []
|
298
295
|
end
|
299
296
|
when 'keymap'
|
300
297
|
case value
|
301
|
-
when 'emacs', 'emacs-standard'
|
298
|
+
when 'emacs', 'emacs-standard'
|
299
|
+
@keymap_label = :emacs
|
300
|
+
@keymap_prefix = []
|
301
|
+
when 'emacs-ctlx'
|
302
|
+
@keymap_label = :emacs
|
303
|
+
@keymap_prefix = [?\C-x.ord]
|
304
|
+
when 'emacs-meta'
|
302
305
|
@keymap_label = :emacs
|
306
|
+
@keymap_prefix = [?\e.ord]
|
303
307
|
when 'vi', 'vi-move', 'vi-command'
|
304
308
|
@keymap_label = :vi_command
|
309
|
+
@keymap_prefix = []
|
305
310
|
when 'vi-insert'
|
306
311
|
@keymap_label = :vi_insert
|
312
|
+
@keymap_prefix = []
|
307
313
|
end
|
308
314
|
when 'keyseq-timeout'
|
309
315
|
@keyseq_timeout = value.to_i
|
data/lib/reline/general_io.rb
CHANGED
@@ -31,6 +31,10 @@ class Reline::GeneralIO
|
|
31
31
|
@@input = val
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.with_raw_input
|
35
|
+
yield
|
36
|
+
end
|
37
|
+
|
34
38
|
def self.getc
|
35
39
|
unless @@buf.empty?
|
36
40
|
return @@buf.shift
|
@@ -57,6 +61,12 @@ class Reline::GeneralIO
|
|
57
61
|
Reline::CursorPos.new(1, 1)
|
58
62
|
end
|
59
63
|
|
64
|
+
def self.hide_cursor
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.show_cursor
|
68
|
+
end
|
69
|
+
|
60
70
|
def self.move_cursor_column(val)
|
61
71
|
end
|
62
72
|
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
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
|
@@ -73,17 +77,26 @@ class Reline::KeyStroke
|
|
73
77
|
return :matched if it.max_by(&:size)&.size&.< input.size
|
74
78
|
return :matching if it.size > 1
|
75
79
|
}
|
76
|
-
key_mapping.keys.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
if key_mapping.keys.any? { |lhs| start_with?(input, lhs) }
|
81
|
+
:matched
|
82
|
+
else
|
83
|
+
match_unknown_escape_sequence(input).first
|
84
|
+
end
|
81
85
|
end
|
82
86
|
|
83
87
|
def expand(input)
|
84
|
-
input = compress_meta_key(input)
|
85
88
|
lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
|
86
|
-
|
89
|
+
unless lhs
|
90
|
+
status, size = match_unknown_escape_sequence(input)
|
91
|
+
case status
|
92
|
+
when :matched
|
93
|
+
return [:ed_unassigned] + expand(input.drop(size))
|
94
|
+
when :matching
|
95
|
+
return [:ed_unassigned]
|
96
|
+
else
|
97
|
+
return input
|
98
|
+
end
|
99
|
+
end
|
87
100
|
rhs = key_mapping[lhs]
|
88
101
|
|
89
102
|
case rhs
|
@@ -99,6 +112,36 @@ class Reline::KeyStroke
|
|
99
112
|
|
100
113
|
private
|
101
114
|
|
115
|
+
# returns match status of CSI/SS3 sequence and matched length
|
116
|
+
def match_unknown_escape_sequence(input)
|
117
|
+
idx = 0
|
118
|
+
return [:unmatched, nil] unless input[idx] == ESC_BYTE
|
119
|
+
idx += 1
|
120
|
+
idx += 1 if input[idx] == ESC_BYTE
|
121
|
+
|
122
|
+
case input[idx]
|
123
|
+
when nil
|
124
|
+
return [:matching, nil]
|
125
|
+
when 91 # == '['.ord
|
126
|
+
# CSI sequence
|
127
|
+
idx += 1
|
128
|
+
idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
|
129
|
+
idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
|
130
|
+
input[idx] ? [:matched, idx + 1] : [:matching, nil]
|
131
|
+
when 79 # == 'O'.ord
|
132
|
+
# SS3 sequence
|
133
|
+
input[idx + 1] ? [:matched, idx + 2] : [:matching, nil]
|
134
|
+
else
|
135
|
+
if idx == 1
|
136
|
+
# `ESC char`, make it :unmatched so that it will be handled correctly in `read_2nd_character_of_key_sequence`
|
137
|
+
[:unmatched, nil]
|
138
|
+
else
|
139
|
+
# `ESC ESC char`
|
140
|
+
[:matched, idx + 1]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
102
145
|
def key_mapping
|
103
146
|
@config.key_bindings
|
104
147
|
end
|