reline 0.3.0 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/reline.svg)](https://badge.fury.io/rb/reline)
|
2
|
+
[![CI](https://github.com/ruby/reline/actions/workflows/reline.yml/badge.svg)](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
|