reline 0.5.2 → 0.5.8
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 +1 -1
- data/lib/reline/ansi.rb +24 -33
- data/lib/reline/config.rb +35 -56
- data/lib/reline/key_actor/base.rb +0 -4
- data/lib/reline/key_actor/emacs.rb +3 -3
- data/lib/reline/key_actor/vi_insert.rb +3 -3
- data/lib/reline/line_editor.rb +322 -409
- data/lib/reline/unicode.rb +66 -12
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +21 -12
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bcccc644594f9c2e4b9ae0eb743c2ae293ef084e96a8d9bd032b76825111c01b
|
4
|
+
data.tar.gz: b5ab239a3d20925d4fbd8fb827908fa3e4fa70298a172e32e9b2b4de59dc767e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bce894711da0253bf9b3f0eb192ff64947d591edd00f9094430431eb470fade4d02f3f8b529d364cdd7124d7f5a5203ea755be41dbfda890e37654aca430706
|
7
|
+
data.tar.gz: eed500ad148a1f83e3de03e6d7daaf5d250ba3ea25d47d24070e749dfd44a7d900b83474dd0b427faee74bad883dab97b7af1984a7fb7209e1819fd416d4381b
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Reline is compatible with the API of Ruby's stdlib 'readline', GNU Readline and
|
|
15
15
|
|
16
16
|
It's compatible with the readline standard library.
|
17
17
|
|
18
|
-
See [the document of readline stdlib](https://ruby-doc.org/stdlib/
|
18
|
+
See [the document of readline stdlib](https://ruby-doc.org/stdlib/exts/readline/Readline.html) or [bin/example](https://github.com/ruby/reline/blob/master/bin/example).
|
19
19
|
|
20
20
|
### Multi-line editing mode
|
21
21
|
|
data/lib/reline/ansi.rb
CHANGED
@@ -45,6 +45,7 @@ class Reline::ANSI
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.set_default_key_bindings(config, allow_terminfo: true)
|
48
|
+
set_bracketed_paste_key_bindings(config)
|
48
49
|
set_default_key_bindings_ansi_cursor(config)
|
49
50
|
if allow_terminfo && Reline::Terminfo.enabled?
|
50
51
|
set_default_key_bindings_terminfo(config)
|
@@ -66,6 +67,12 @@ class Reline::ANSI
|
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
70
|
+
def self.set_bracketed_paste_key_bindings(config)
|
71
|
+
[:emacs, :vi_insert, :vi_command].each do |keymap|
|
72
|
+
config.add_default_key_binding_by_keymap(keymap, START_BRACKETED_PASTE.bytes, :bracketed_paste_start)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
69
76
|
def self.set_default_key_bindings_ansi_cursor(config)
|
70
77
|
ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
|
71
78
|
bindings = [["\e[#{char}", default_func]] # CSI + char
|
@@ -178,46 +185,26 @@ class Reline::ANSI
|
|
178
185
|
nil
|
179
186
|
end
|
180
187
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
def self.getc_with_bracketed_paste(timeout_second)
|
188
|
+
START_BRACKETED_PASTE = String.new("\e[200~", encoding: Encoding::ASCII_8BIT)
|
189
|
+
END_BRACKETED_PASTE = String.new("\e[201~", encoding: Encoding::ASCII_8BIT)
|
190
|
+
def self.read_bracketed_paste
|
185
191
|
buffer = String.new(encoding: Encoding::ASCII_8BIT)
|
186
|
-
buffer
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
return inner_getc(timeout_second)
|
191
|
-
elsif END_BRACKETED_PASTE == buffer
|
192
|
-
@@in_bracketed_paste_mode = false
|
193
|
-
ungetc(-1)
|
194
|
-
return inner_getc(timeout_second)
|
195
|
-
end
|
196
|
-
succ_c = inner_getc(Reline.core.config.keyseq_timeout)
|
197
|
-
|
198
|
-
if succ_c
|
199
|
-
buffer << succ_c
|
200
|
-
else
|
201
|
-
break
|
202
|
-
end
|
192
|
+
until buffer.end_with?(END_BRACKETED_PASTE)
|
193
|
+
c = inner_getc(Float::INFINITY)
|
194
|
+
break unless c
|
195
|
+
buffer << c
|
203
196
|
end
|
204
|
-
buffer.
|
205
|
-
|
206
|
-
end
|
207
|
-
inner_getc(timeout_second)
|
197
|
+
string = buffer.delete_suffix(END_BRACKETED_PASTE).force_encoding(encoding)
|
198
|
+
string.valid_encoding? ? string : ''
|
208
199
|
end
|
209
200
|
|
210
201
|
# if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second
|
211
202
|
def self.getc(timeout_second)
|
212
|
-
|
213
|
-
getc_with_bracketed_paste(timeout_second)
|
214
|
-
else
|
215
|
-
inner_getc(timeout_second)
|
216
|
-
end
|
203
|
+
inner_getc(timeout_second)
|
217
204
|
end
|
218
205
|
|
219
206
|
def self.in_pasting?
|
220
|
-
|
207
|
+
not empty_buffer?
|
221
208
|
end
|
222
209
|
|
223
210
|
def self.empty_buffer?
|
@@ -248,7 +235,7 @@ class Reline::ANSI
|
|
248
235
|
s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
|
249
236
|
return s if s[0] > 0 && s[1] > 0
|
250
237
|
[24, 80]
|
251
|
-
rescue Errno::ENOTTY
|
238
|
+
rescue Errno::ENOTTY, Errno::ENODEV
|
252
239
|
[24, 80]
|
253
240
|
end
|
254
241
|
|
@@ -284,7 +271,7 @@ class Reline::ANSI
|
|
284
271
|
buf = @@output.pread(@@output.pos, 0)
|
285
272
|
row = buf.count("\n")
|
286
273
|
column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
|
287
|
-
rescue Errno::ESPIPE
|
274
|
+
rescue Errno::ESPIPE, IOError
|
288
275
|
# Just returns column 1 for ambiguous width because this I/O is not
|
289
276
|
# tty and can't seek.
|
290
277
|
row = 0
|
@@ -361,11 +348,15 @@ class Reline::ANSI
|
|
361
348
|
end
|
362
349
|
|
363
350
|
def self.prep
|
351
|
+
# Enable bracketed paste
|
352
|
+
@@output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste
|
364
353
|
retrieve_keybuffer
|
365
354
|
nil
|
366
355
|
end
|
367
356
|
|
368
357
|
def self.deprep(otio)
|
358
|
+
# Disable bracketed paste
|
359
|
+
@@output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste
|
369
360
|
Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
|
370
361
|
end
|
371
362
|
end
|
data/lib/reline/config.rb
CHANGED
@@ -8,31 +8,12 @@ class Reline::Config
|
|
8
8
|
end
|
9
9
|
|
10
10
|
VARIABLE_NAMES = %w{
|
11
|
-
bind-tty-special-chars
|
12
|
-
blink-matching-paren
|
13
|
-
byte-oriented
|
14
11
|
completion-ignore-case
|
15
12
|
convert-meta
|
16
13
|
disable-completion
|
17
|
-
enable-keypad
|
18
|
-
expand-tilde
|
19
|
-
history-preserve-point
|
20
14
|
history-size
|
21
|
-
horizontal-scroll-mode
|
22
|
-
input-meta
|
23
15
|
keyseq-timeout
|
24
|
-
mark-directories
|
25
|
-
mark-modified-lines
|
26
|
-
mark-symlinked-directories
|
27
|
-
match-hidden-files
|
28
|
-
meta-flag
|
29
|
-
output-meta
|
30
|
-
page-completions
|
31
|
-
prefer-visible-bell
|
32
|
-
print-completions-horizontally
|
33
16
|
show-all-if-ambiguous
|
34
|
-
show-all-if-unmodified
|
35
|
-
visible-stats
|
36
17
|
show-mode-in-prompt
|
37
18
|
vi-cmd-mode-string
|
38
19
|
vi-ins-mode-string
|
@@ -53,8 +34,6 @@ class Reline::Config
|
|
53
34
|
@additional_key_bindings[:vi_insert] = {}
|
54
35
|
@additional_key_bindings[:vi_command] = {}
|
55
36
|
@oneshot_key_bindings = {}
|
56
|
-
@skip_section = nil
|
57
|
-
@if_stack = nil
|
58
37
|
@editing_mode_label = :emacs
|
59
38
|
@keymap_label = :emacs
|
60
39
|
@keymap_prefix = []
|
@@ -71,17 +50,15 @@ class Reline::Config
|
|
71
50
|
@test_mode = false
|
72
51
|
@autocompletion = false
|
73
52
|
@convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
|
53
|
+
@loaded = false
|
54
|
+
@enable_bracketed_paste = true
|
74
55
|
end
|
75
56
|
|
76
57
|
def reset
|
77
58
|
if editing_mode_is?(:vi_command)
|
78
59
|
@editing_mode_label = :vi_insert
|
79
60
|
end
|
80
|
-
@additional_key_bindings.keys.each do |key|
|
81
|
-
@additional_key_bindings[key].clear
|
82
|
-
end
|
83
61
|
@oneshot_key_bindings.clear
|
84
|
-
reset_default_key_bindings
|
85
62
|
end
|
86
63
|
|
87
64
|
def editing_mode
|
@@ -100,6 +77,10 @@ class Reline::Config
|
|
100
77
|
@key_actors[@keymap_label]
|
101
78
|
end
|
102
79
|
|
80
|
+
def loaded?
|
81
|
+
@loaded
|
82
|
+
end
|
83
|
+
|
103
84
|
def inputrc_path
|
104
85
|
case ENV['INPUTRC']
|
105
86
|
when nil, ''
|
@@ -131,6 +112,7 @@ class Reline::Config
|
|
131
112
|
end
|
132
113
|
|
133
114
|
def read(file = nil)
|
115
|
+
@loaded = true
|
134
116
|
file ||= default_inputrc_path
|
135
117
|
begin
|
136
118
|
if file.respond_to?(:readlines)
|
@@ -173,12 +155,6 @@ class Reline::Config
|
|
173
155
|
@key_actors[@keymap_label].default_key_bindings[keystroke] = target
|
174
156
|
end
|
175
157
|
|
176
|
-
def reset_default_key_bindings
|
177
|
-
@key_actors.values.each do |ka|
|
178
|
-
ka.reset_default_key_bindings
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
158
|
def read_lines(lines, file = nil)
|
183
159
|
if not lines.empty? and lines.first.encoding != Reline.encoding_system_needs
|
184
160
|
begin
|
@@ -190,9 +166,7 @@ class Reline::Config
|
|
190
166
|
end
|
191
167
|
end
|
192
168
|
end
|
193
|
-
|
194
|
-
@skip_section = nil
|
195
|
-
@if_stack = []
|
169
|
+
if_stack = []
|
196
170
|
|
197
171
|
lines.each_with_index do |line, no|
|
198
172
|
next if line.match(/\A\s*#/)
|
@@ -201,62 +175,67 @@ class Reline::Config
|
|
201
175
|
|
202
176
|
line = line.chomp.lstrip
|
203
177
|
if line.start_with?('$')
|
204
|
-
handle_directive(line[1..-1], file, no)
|
178
|
+
handle_directive(line[1..-1], file, no, if_stack)
|
205
179
|
next
|
206
180
|
end
|
207
181
|
|
208
|
-
next if
|
182
|
+
next if if_stack.any? { |_no, skip| skip }
|
209
183
|
|
210
184
|
case line
|
211
|
-
when /^set +([^ ]+) +(
|
212
|
-
|
213
|
-
|
185
|
+
when /^set +([^ ]+) +(.+)/i
|
186
|
+
# value ignores everything after a space, raw_value does not.
|
187
|
+
var, value, raw_value = $1.downcase, $2.partition(' ').first, $2
|
188
|
+
bind_variable(var, value, raw_value)
|
214
189
|
next
|
215
190
|
when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
|
216
191
|
key, func_name = $1, $2
|
192
|
+
func_name = func_name.split.first
|
217
193
|
keystroke, func = bind_key(key, func_name)
|
218
194
|
next unless keystroke
|
219
195
|
@additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
|
220
196
|
end
|
221
197
|
end
|
222
|
-
unless
|
223
|
-
raise InvalidInputrc, "#{file}:#{
|
198
|
+
unless if_stack.empty?
|
199
|
+
raise InvalidInputrc, "#{file}:#{if_stack.last[0]}: unclosed if"
|
224
200
|
end
|
225
|
-
ensure
|
226
|
-
@skip_section, @if_stack = conditions
|
227
201
|
end
|
228
202
|
|
229
|
-
def handle_directive(directive, file, no)
|
203
|
+
def handle_directive(directive, file, no, if_stack)
|
230
204
|
directive, args = directive.split(' ')
|
231
205
|
case directive
|
232
206
|
when 'if'
|
233
207
|
condition = false
|
234
208
|
case args
|
235
|
-
when
|
209
|
+
when /^mode=(vi|emacs)$/i
|
210
|
+
mode = $1.downcase
|
211
|
+
# NOTE: mode=vi means vi-insert mode
|
212
|
+
mode = 'vi_insert' if mode == 'vi'
|
213
|
+
if @editing_mode_label == mode.to_sym
|
214
|
+
condition = true
|
215
|
+
end
|
236
216
|
when 'term'
|
237
217
|
when 'version'
|
238
218
|
else # application name
|
239
219
|
condition = true if args == 'Ruby'
|
240
220
|
condition = true if args == 'Reline'
|
241
221
|
end
|
242
|
-
|
243
|
-
@skip_section = !condition
|
222
|
+
if_stack << [no, !condition]
|
244
223
|
when 'else'
|
245
|
-
if
|
224
|
+
if if_stack.empty?
|
246
225
|
raise InvalidInputrc, "#{file}:#{no}: unmatched else"
|
247
226
|
end
|
248
|
-
|
227
|
+
if_stack.last[1] = !if_stack.last[1]
|
249
228
|
when 'endif'
|
250
|
-
if
|
229
|
+
if if_stack.empty?
|
251
230
|
raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
|
252
231
|
end
|
253
|
-
|
232
|
+
if_stack.pop
|
254
233
|
when 'include'
|
255
234
|
read(File.expand_path(args))
|
256
235
|
end
|
257
236
|
end
|
258
237
|
|
259
|
-
def bind_variable(name, value)
|
238
|
+
def bind_variable(name, value, raw_value)
|
260
239
|
case name
|
261
240
|
when 'history-size'
|
262
241
|
begin
|
@@ -281,7 +260,7 @@ class Reline::Config
|
|
281
260
|
when 'completion-query-items'
|
282
261
|
@completion_query_items = value.to_i
|
283
262
|
when 'isearch-terminators'
|
284
|
-
@isearch_terminators = retrieve_string(
|
263
|
+
@isearch_terminators = retrieve_string(raw_value)
|
285
264
|
when 'editing-mode'
|
286
265
|
case value
|
287
266
|
when 'emacs'
|
@@ -323,11 +302,11 @@ class Reline::Config
|
|
323
302
|
@show_mode_in_prompt = false
|
324
303
|
end
|
325
304
|
when 'vi-cmd-mode-string'
|
326
|
-
@vi_cmd_mode_string = retrieve_string(
|
305
|
+
@vi_cmd_mode_string = retrieve_string(raw_value)
|
327
306
|
when 'vi-ins-mode-string'
|
328
|
-
@vi_ins_mode_string = retrieve_string(
|
307
|
+
@vi_ins_mode_string = retrieve_string(raw_value)
|
329
308
|
when 'emacs-mode-string'
|
330
|
-
@emacs_mode_string = retrieve_string(
|
309
|
+
@emacs_mode_string = retrieve_string(raw_value)
|
331
310
|
when *VARIABLE_NAMES then
|
332
311
|
variable_name = :"@#{name.tr(?-, ?_)}"
|
333
312
|
instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
|
@@ -19,7 +19,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
19
19
|
# 8 ^H
|
20
20
|
:em_delete_prev_char,
|
21
21
|
# 9 ^I
|
22
|
-
:
|
22
|
+
:complete,
|
23
23
|
# 10 ^J
|
24
24
|
:ed_newline,
|
25
25
|
# 11 ^K
|
@@ -63,7 +63,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
63
63
|
# 30 ^^
|
64
64
|
:ed_unassigned,
|
65
65
|
# 31 ^_
|
66
|
-
:
|
66
|
+
:undo,
|
67
67
|
# 32 SPACE
|
68
68
|
:ed_insert,
|
69
69
|
# 33 !
|
@@ -319,7 +319,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
319
319
|
# 158 M-^^
|
320
320
|
:ed_unassigned,
|
321
321
|
# 159 M-^_
|
322
|
-
:
|
322
|
+
:redo,
|
323
323
|
# 160 M-SPACE
|
324
324
|
:em_set_mark,
|
325
325
|
# 161 M-!
|
@@ -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
|
-
:
|
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
|
-
:
|
32
|
+
:menu_complete,
|
33
33
|
# 15 ^O
|
34
34
|
:ed_insert,
|
35
35
|
# 16 ^P
|
36
|
-
:
|
36
|
+
:menu_complete_backward,
|
37
37
|
# 17 ^Q
|
38
38
|
:ed_ignore,
|
39
39
|
# 18 ^R
|