reline 0.2.7 → 0.3.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/lib/reline/ansi.rb +64 -22
- data/lib/reline/config.rb +34 -3
- data/lib/reline/general_io.rb +3 -1
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +64 -14
- data/lib/reline/line_editor.rb +630 -72
- data/lib/reline/terminfo.rb +50 -5
- data/lib/reline/unicode.rb +42 -3
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +151 -49
- data/lib/reline.rb +127 -22
- metadata +3 -3
data/lib/reline.rb
CHANGED
@@ -16,8 +16,24 @@ module Reline
|
|
16
16
|
|
17
17
|
class ConfigEncodingConversionError < StandardError; end
|
18
18
|
|
19
|
-
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
19
|
+
Key = Struct.new('Key', :char, :combined_char, :with_meta) do
|
20
|
+
def match?(other)
|
21
|
+
case other
|
22
|
+
when Reline::Key
|
23
|
+
(other.char.nil? or char.nil? or char == other.char) and
|
24
|
+
(other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
|
25
|
+
(other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
|
26
|
+
when Integer, Symbol
|
27
|
+
(combined_char and combined_char == other) or
|
28
|
+
(combined_char.nil? and char and char == other)
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method :==, :match?
|
34
|
+
end
|
20
35
|
CursorPos = Struct.new(:x, :y)
|
36
|
+
DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)
|
21
37
|
|
22
38
|
class Core
|
23
39
|
ATTR_READER_NAMES = %i(
|
@@ -44,6 +60,7 @@ module Reline
|
|
44
60
|
|
45
61
|
def initialize
|
46
62
|
self.output = STDOUT
|
63
|
+
@dialog_proc_list = {}
|
47
64
|
yield self
|
48
65
|
@completion_quote_character = nil
|
49
66
|
@bracketed_paste_finished = false
|
@@ -106,6 +123,14 @@ module Reline
|
|
106
123
|
@completion_proc = p
|
107
124
|
end
|
108
125
|
|
126
|
+
def autocompletion
|
127
|
+
@config.autocompletion
|
128
|
+
end
|
129
|
+
|
130
|
+
def autocompletion=(val)
|
131
|
+
@config.autocompletion = val
|
132
|
+
end
|
133
|
+
|
109
134
|
def output_modifier_proc=(p)
|
110
135
|
raise ArgumentError unless p.respond_to?(:call) or p.nil?
|
111
136
|
@output_modifier_proc = p
|
@@ -130,6 +155,17 @@ module Reline
|
|
130
155
|
@dig_perfect_match_proc = p
|
131
156
|
end
|
132
157
|
|
158
|
+
DialogProc = Struct.new(:dialog_proc, :context)
|
159
|
+
def add_dialog_proc(name_sym, p, context = nil)
|
160
|
+
raise ArgumentError unless p.respond_to?(:call) or p.nil?
|
161
|
+
raise ArgumentError unless name_sym.instance_of?(Symbol)
|
162
|
+
@dialog_proc_list[name_sym] = DialogProc.new(p, context)
|
163
|
+
end
|
164
|
+
|
165
|
+
def dialog_proc(name_sym)
|
166
|
+
@dialog_proc_list[name_sym]
|
167
|
+
end
|
168
|
+
|
133
169
|
def input=(val)
|
134
170
|
raise TypeError unless val.respond_to?(:getc) or val.nil?
|
135
171
|
if val.respond_to?(:getc)
|
@@ -171,6 +207,46 @@ module Reline
|
|
171
207
|
Reline::IOGate.get_screen_size
|
172
208
|
end
|
173
209
|
|
210
|
+
Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
|
211
|
+
# autocomplete
|
212
|
+
return nil unless config.autocompletion
|
213
|
+
if just_cursor_moving and completion_journey_data.nil?
|
214
|
+
# Auto complete starts only when edited
|
215
|
+
return nil
|
216
|
+
end
|
217
|
+
pre, target, post = retrieve_completion_block(true)
|
218
|
+
if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
|
219
|
+
return nil
|
220
|
+
end
|
221
|
+
if completion_journey_data and completion_journey_data.list
|
222
|
+
result = completion_journey_data.list.dup
|
223
|
+
result.shift
|
224
|
+
pointer = completion_journey_data.pointer - 1
|
225
|
+
else
|
226
|
+
result = call_completion_proc_with_checking_args(pre, target, post)
|
227
|
+
pointer = nil
|
228
|
+
end
|
229
|
+
if result and result.size == 1 and result[0] == target and pointer != 0
|
230
|
+
result = nil
|
231
|
+
end
|
232
|
+
target_width = Reline::Unicode.calculate_width(target)
|
233
|
+
x = cursor_pos.x - target_width
|
234
|
+
if x < 0
|
235
|
+
x = screen_width + x
|
236
|
+
y = -1
|
237
|
+
else
|
238
|
+
y = 0
|
239
|
+
end
|
240
|
+
cursor_pos_to_render = Reline::CursorPos.new(x, y)
|
241
|
+
if context and context.is_a?(Array)
|
242
|
+
context.clear
|
243
|
+
context.push(cursor_pos_to_render, result, pointer, dialog)
|
244
|
+
end
|
245
|
+
dialog.pointer = pointer
|
246
|
+
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15)
|
247
|
+
}
|
248
|
+
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
249
|
+
|
174
250
|
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
175
251
|
unless confirm_multiline_termination
|
176
252
|
raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
|
@@ -230,6 +306,9 @@ module Reline
|
|
230
306
|
line_editor.auto_indent_proc = auto_indent_proc
|
231
307
|
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
|
232
308
|
line_editor.pre_input_hook = pre_input_hook
|
309
|
+
@dialog_proc_list.each_pair do |name_sym, d|
|
310
|
+
line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
|
311
|
+
end
|
233
312
|
|
234
313
|
unless config.test_mode
|
235
314
|
config.read
|
@@ -240,6 +319,7 @@ module Reline
|
|
240
319
|
line_editor.rerender
|
241
320
|
|
242
321
|
begin
|
322
|
+
line_editor.set_signal_handlers
|
243
323
|
prev_pasting_state = false
|
244
324
|
loop do
|
245
325
|
prev_pasting_state = Reline::IOGate.in_pasting?
|
@@ -268,6 +348,11 @@ module Reline
|
|
268
348
|
line_editor.finalize
|
269
349
|
Reline::IOGate.deprep(otio)
|
270
350
|
raise e
|
351
|
+
rescue Exception
|
352
|
+
# Including Interrupt
|
353
|
+
line_editor.finalize
|
354
|
+
Reline::IOGate.deprep(otio)
|
355
|
+
raise
|
271
356
|
end
|
272
357
|
|
273
358
|
line_editor.finalize
|
@@ -303,25 +388,9 @@ module Reline
|
|
303
388
|
break
|
304
389
|
when :matching
|
305
390
|
if buffer.size == 1
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
succ_c = Reline::IOGate.getc
|
310
|
-
}
|
311
|
-
rescue Timeout::Error # cancel matching only when first byte
|
312
|
-
block.([Reline::Key.new(c, c, false)])
|
313
|
-
break
|
314
|
-
else
|
315
|
-
if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
|
316
|
-
if c == "\e".ord
|
317
|
-
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
318
|
-
else
|
319
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
320
|
-
end
|
321
|
-
break
|
322
|
-
else
|
323
|
-
Reline::IOGate.ungetc(succ_c)
|
324
|
-
end
|
391
|
+
case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
392
|
+
when :break then break
|
393
|
+
when :next then next
|
325
394
|
end
|
326
395
|
end
|
327
396
|
when :unmatched
|
@@ -338,6 +407,38 @@ module Reline
|
|
338
407
|
end
|
339
408
|
end
|
340
409
|
|
410
|
+
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
411
|
+
begin
|
412
|
+
succ_c = nil
|
413
|
+
Timeout.timeout(keyseq_timeout / 1000.0) {
|
414
|
+
succ_c = Reline::IOGate.getc
|
415
|
+
}
|
416
|
+
rescue Timeout::Error # cancel matching only when first byte
|
417
|
+
block.([Reline::Key.new(c, c, false)])
|
418
|
+
return :break
|
419
|
+
else
|
420
|
+
case key_stroke.match_status(buffer.dup.push(succ_c))
|
421
|
+
when :unmatched
|
422
|
+
if c == "\e".ord
|
423
|
+
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
424
|
+
else
|
425
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
426
|
+
end
|
427
|
+
return :break
|
428
|
+
when :matching
|
429
|
+
Reline::IOGate.ungetc(succ_c)
|
430
|
+
return :next
|
431
|
+
when :matched
|
432
|
+
buffer << succ_c
|
433
|
+
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
434
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
435
|
+
}
|
436
|
+
block.(expanded)
|
437
|
+
return :break
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
341
442
|
private def read_escaped_key(keyseq_timeout, c, block)
|
342
443
|
begin
|
343
444
|
escaped_c = nil
|
@@ -366,7 +467,7 @@ module Reline
|
|
366
467
|
|
367
468
|
private def may_req_ambiguous_char_width
|
368
469
|
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
|
369
|
-
return if @ambiguous_width
|
470
|
+
return if defined? @ambiguous_width
|
370
471
|
Reline::IOGate.move_cursor_column(0)
|
371
472
|
begin
|
372
473
|
output.write "\u{25bd}"
|
@@ -389,7 +490,7 @@ module Reline
|
|
389
490
|
#--------------------------------------------------------
|
390
491
|
|
391
492
|
(Core::ATTR_READER_NAMES).each { |name|
|
392
|
-
def_single_delegators :core, "#{name}", "#{name}="
|
493
|
+
def_single_delegators :core, :"#{name}", :"#{name}="
|
393
494
|
}
|
394
495
|
def_single_delegators :core, :input=, :output=
|
395
496
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
@@ -424,6 +525,9 @@ module Reline
|
|
424
525
|
def_single_delegators :core, :ambiguous_width
|
425
526
|
def_single_delegators :core, :last_incremental_search
|
426
527
|
def_single_delegators :core, :last_incremental_search=
|
528
|
+
def_single_delegators :core, :add_dialog_proc
|
529
|
+
def_single_delegators :core, :dialog_proc
|
530
|
+
def_single_delegators :core, :autocompletion, :autocompletion=
|
427
531
|
|
428
532
|
def_single_delegators :core, :readmultiline
|
429
533
|
def_instance_delegators self, :readmultiline
|
@@ -445,6 +549,7 @@ module Reline
|
|
445
549
|
core.completer_quote_characters = '"\''
|
446
550
|
core.filename_quote_characters = ""
|
447
551
|
core.special_prefixes = ""
|
552
|
+
core.add_dialog_proc(:autocomplete, Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE, Reline::DEFAULT_DIALOG_CONTEXT)
|
448
553
|
}
|
449
554
|
end
|
450
555
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
75
|
requirements: []
|
76
|
-
rubygems_version: 3.
|
76
|
+
rubygems_version: 3.0.3.1
|
77
77
|
signing_key:
|
78
78
|
specification_version: 4
|
79
79
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|