reline 0.2.8.pre.7 → 0.2.8.pre.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/lib/reline/config.rb +16 -2
- data/lib/reline/key_stroke.rb +56 -4
- data/lib/reline/line_editor.rb +42 -6
- data/lib/reline/line_editor.rb.orig +49 -6
- data/lib/reline/unicode.rb +3 -3
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +53 -24
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f03d46c602265d3a197f00021df365a9686e4fd0b5d0ef2a037a9ad25143b91
|
4
|
+
data.tar.gz: e97bfb610d3c9498e651b25de97e87380e624b56ea970ab7048b25dca7be9488
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be1a180b58930985ea7ba5d63be81b62c8ffb0b960daf33c5ad984652fa6021151519cc1fa41055c240d7675d628c6749ab69ca67c2c2bfa306a9deab8200c56
|
7
|
+
data.tar.gz: 68be299c9815a350c8afec2c5b27aa02905c8fcc04c6fbba331aded2aded1d0dc160d2e8b01be58a91f308b1ad1dd880209e237de770002422910c6014ddc51a
|
data/lib/reline/config.rb
CHANGED
@@ -50,6 +50,7 @@ class Reline::Config
|
|
50
50
|
@additional_key_bindings[:emacs] = {}
|
51
51
|
@additional_key_bindings[:vi_insert] = {}
|
52
52
|
@additional_key_bindings[:vi_command] = {}
|
53
|
+
@oneshot_key_bindings = {}
|
53
54
|
@skip_section = nil
|
54
55
|
@if_stack = nil
|
55
56
|
@editing_mode_label = :emacs
|
@@ -75,6 +76,7 @@ class Reline::Config
|
|
75
76
|
@additional_key_bindings.keys.each do |key|
|
76
77
|
@additional_key_bindings[key].clear
|
77
78
|
end
|
79
|
+
@oneshot_key_bindings.clear
|
78
80
|
reset_default_key_bindings
|
79
81
|
end
|
80
82
|
|
@@ -128,8 +130,12 @@ class Reline::Config
|
|
128
130
|
return home_rc_path
|
129
131
|
end
|
130
132
|
|
133
|
+
private def default_inputrc_path
|
134
|
+
@default_inputrc_path ||= inputrc_path
|
135
|
+
end
|
136
|
+
|
131
137
|
def read(file = nil)
|
132
|
-
file ||=
|
138
|
+
file ||= default_inputrc_path
|
133
139
|
begin
|
134
140
|
if file.respond_to?(:readlines)
|
135
141
|
lines = file.readlines
|
@@ -149,7 +155,15 @@ class Reline::Config
|
|
149
155
|
|
150
156
|
def key_bindings
|
151
157
|
# override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label]
|
152
|
-
@key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label])
|
158
|
+
@key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label]).merge(@oneshot_key_bindings)
|
159
|
+
end
|
160
|
+
|
161
|
+
def add_oneshot_key_binding(keystroke, target)
|
162
|
+
@oneshot_key_bindings[keystroke] = target
|
163
|
+
end
|
164
|
+
|
165
|
+
def reset_oneshot_key_bindings
|
166
|
+
@oneshot_key_bindings.clear
|
153
167
|
end
|
154
168
|
|
155
169
|
def add_default_key_binding_by_keymap(keymap, keystroke, target)
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -1,8 +1,59 @@
|
|
1
1
|
class Reline::KeyStroke
|
2
2
|
using Module.new {
|
3
|
+
refine Integer do
|
4
|
+
def ==(other)
|
5
|
+
if other.is_a?(Reline::Key)
|
6
|
+
if other.combined_char == "\e".ord
|
7
|
+
false
|
8
|
+
else
|
9
|
+
other.combined_char == self
|
10
|
+
end
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
3
17
|
refine Array do
|
4
18
|
def start_with?(other)
|
5
|
-
|
19
|
+
compressed_me = compress_meta_key
|
20
|
+
compressed_other = other.compress_meta_key
|
21
|
+
i = 0
|
22
|
+
loop do
|
23
|
+
my_c = compressed_me[i]
|
24
|
+
other_c = compressed_other[i]
|
25
|
+
other_is_last = (i + 1) == compressed_other.size
|
26
|
+
me_is_last = (i + 1) == compressed_me.size
|
27
|
+
if my_c != other_c
|
28
|
+
if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
|
29
|
+
return true
|
30
|
+
else
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
elsif other_is_last
|
34
|
+
return true
|
35
|
+
elsif me_is_last
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
i += 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def ==(other)
|
43
|
+
compressed_me = compress_meta_key
|
44
|
+
compressed_other = other.compress_meta_key
|
45
|
+
compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| i[0] == i[1] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def compress_meta_key
|
49
|
+
inject([]) { |result, key|
|
50
|
+
if result.size > 0 and result.last == "\e".ord
|
51
|
+
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
52
|
+
else
|
53
|
+
result << key
|
54
|
+
end
|
55
|
+
result
|
56
|
+
}
|
6
57
|
end
|
7
58
|
|
8
59
|
def bytes
|
@@ -19,8 +70,8 @@ class Reline::KeyStroke
|
|
19
70
|
key_mapping.keys.select { |lhs|
|
20
71
|
lhs.start_with? input
|
21
72
|
}.tap { |it|
|
22
|
-
return :matched if it.size == 1 && (it
|
23
|
-
return :matching if it.size == 1 && (it
|
73
|
+
return :matched if it.size == 1 && (it[0] == input)
|
74
|
+
return :matching if it.size == 1 && (it[0] != input)
|
24
75
|
return :matched if it.max_by(&:size)&.size&.< input.size
|
25
76
|
return :matching if it.size > 1
|
26
77
|
}
|
@@ -32,7 +83,8 @@ class Reline::KeyStroke
|
|
32
83
|
end
|
33
84
|
|
34
85
|
def expand(input)
|
35
|
-
|
86
|
+
input = input.compress_meta_key
|
87
|
+
lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).last
|
36
88
|
return input unless lhs
|
37
89
|
rhs = key_mapping[lhs]
|
38
90
|
|
data/lib/reline/line_editor.rb
CHANGED
@@ -550,8 +550,9 @@ class Reline::LineEditor
|
|
550
550
|
attr_reader :name, :contents, :width
|
551
551
|
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup, :trap_key
|
552
552
|
|
553
|
-
def initialize(name, proc_scope)
|
553
|
+
def initialize(name, config, proc_scope)
|
554
554
|
@name = name
|
555
|
+
@config = config
|
555
556
|
@proc_scope = proc_scope
|
556
557
|
@width = nil
|
557
558
|
@scroll_top = 0
|
@@ -575,13 +576,25 @@ class Reline::LineEditor
|
|
575
576
|
def call(key)
|
576
577
|
@proc_scope.set_dialog(self)
|
577
578
|
@proc_scope.set_key(key)
|
578
|
-
@proc_scope.call
|
579
|
+
dialog_render_info = @proc_scope.call
|
580
|
+
if @trap_key
|
581
|
+
if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap
|
582
|
+
@trap_key.each do |t|
|
583
|
+
@config.add_oneshot_key_binding(t, @name)
|
584
|
+
end
|
585
|
+
elsif @trap_key.is_a?(Array)
|
586
|
+
@config.add_oneshot_key_binding(@trap_key, @name)
|
587
|
+
elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
|
588
|
+
@config.add_oneshot_key_binding([@trap_key], @name)
|
589
|
+
end
|
590
|
+
end
|
591
|
+
dialog_render_info
|
579
592
|
end
|
580
593
|
end
|
581
594
|
|
582
595
|
def add_dialog_proc(name, p, context = nil)
|
583
596
|
return if @dialogs.any? { |d| d.name == name }
|
584
|
-
@dialogs << Dialog.new(name, DialogProcScope.new(self, @config, p, context))
|
597
|
+
@dialogs << Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
|
585
598
|
end
|
586
599
|
|
587
600
|
DIALOG_HEIGHT = 20
|
@@ -661,6 +674,13 @@ class Reline::LineEditor
|
|
661
674
|
reset_dialog(dialog, old_dialog)
|
662
675
|
move_cursor_down(dialog.vertical_offset)
|
663
676
|
Reline::IOGate.move_cursor_column(dialog.column)
|
677
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
678
|
+
bar_max_height = height * 2
|
679
|
+
moving_distance = (dialog_render_info.contents.size - height) * 2
|
680
|
+
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
|
681
|
+
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
|
682
|
+
position = ((bar_max_height - bar_height) * position_ratio).floor.to_i
|
683
|
+
end
|
664
684
|
dialog.contents.each_with_index do |item, i|
|
665
685
|
if i == pointer
|
666
686
|
bg_color = '45'
|
@@ -672,10 +692,26 @@ class Reline::LineEditor
|
|
672
692
|
end
|
673
693
|
end
|
674
694
|
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width)
|
675
|
-
@output.write "\e[#{bg_color}m#{str}
|
695
|
+
@output.write "\e[#{bg_color}m#{str}"
|
696
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
697
|
+
@output.write "\e[37m"
|
698
|
+
if position <= (i * 2) and (i * 2 + 1) < (position + bar_height)
|
699
|
+
@output.write '█'
|
700
|
+
elsif position <= (i * 2) and (i * 2) < (position + bar_height)
|
701
|
+
@output.write '▀'
|
702
|
+
str += ''
|
703
|
+
elsif position <= (i * 2 + 1) and (i * 2) < (position + bar_height)
|
704
|
+
@output.write '▄'
|
705
|
+
else
|
706
|
+
@output.write ' '
|
707
|
+
end
|
708
|
+
@output.write "\e[39m"
|
709
|
+
end
|
710
|
+
@output.write "\e[49m"
|
676
711
|
Reline::IOGate.move_cursor_column(dialog.column)
|
677
712
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
678
713
|
end
|
714
|
+
dialog.width += 1 if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
679
715
|
Reline::IOGate.move_cursor_column(cursor_column)
|
680
716
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
|
681
717
|
Reline::IOGate.show_cursor
|
@@ -1478,9 +1514,9 @@ class Reline::LineEditor
|
|
1478
1514
|
|
1479
1515
|
def input_key(key)
|
1480
1516
|
@last_key = key
|
1517
|
+
@config.reset_oneshot_key_bindings
|
1481
1518
|
@dialogs.each do |dialog|
|
1482
|
-
|
1483
|
-
if dialog.trap_key and dialog.trap_key.match?(key)
|
1519
|
+
if key.char.instance_of?(Symbol) and key.char == dialog.name
|
1484
1520
|
return
|
1485
1521
|
end
|
1486
1522
|
end
|
@@ -251,6 +251,7 @@ class Reline::LineEditor
|
|
251
251
|
@in_pasting = false
|
252
252
|
@auto_indent_proc = nil
|
253
253
|
@dialogs = []
|
254
|
+
@last_key = nil
|
254
255
|
reset_line
|
255
256
|
end
|
256
257
|
|
@@ -512,6 +513,14 @@ class Reline::LineEditor
|
|
512
513
|
@cursor_pos.y = row
|
513
514
|
end
|
514
515
|
|
516
|
+
def set_key(key)
|
517
|
+
@key = key
|
518
|
+
end
|
519
|
+
|
520
|
+
def key
|
521
|
+
@key
|
522
|
+
end
|
523
|
+
|
515
524
|
def cursor_pos
|
516
525
|
@cursor_pos
|
517
526
|
end
|
@@ -539,7 +548,7 @@ class Reline::LineEditor
|
|
539
548
|
|
540
549
|
class Dialog
|
541
550
|
attr_reader :name, :contents, :width
|
542
|
-
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup
|
551
|
+
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup, :trap_key
|
543
552
|
|
544
553
|
def initialize(name, proc_scope)
|
545
554
|
@name = name
|
@@ -563,8 +572,9 @@ class Reline::LineEditor
|
|
563
572
|
end
|
564
573
|
end
|
565
574
|
|
566
|
-
def call
|
575
|
+
def call(key)
|
567
576
|
@proc_scope.set_dialog(self)
|
577
|
+
@proc_scope.set_key(key)
|
568
578
|
@proc_scope.call
|
569
579
|
end
|
570
580
|
end
|
@@ -588,10 +598,11 @@ class Reline::LineEditor
|
|
588
598
|
private def render_each_dialog(dialog, cursor_column)
|
589
599
|
if @in_pasting
|
590
600
|
dialog.contents = nil
|
601
|
+
dialog.trap_key = nil
|
591
602
|
return
|
592
603
|
end
|
593
604
|
dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
|
594
|
-
dialog_render_info = dialog.call
|
605
|
+
dialog_render_info = dialog.call(@last_key)
|
595
606
|
if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
|
596
607
|
dialog.lines_backup = {
|
597
608
|
lines: modify_lines(whole_lines),
|
@@ -602,13 +613,18 @@ class Reline::LineEditor
|
|
602
613
|
}
|
603
614
|
clear_each_dialog(dialog)
|
604
615
|
dialog.contents = nil
|
616
|
+
dialog.trap_key = nil
|
605
617
|
return
|
606
618
|
end
|
607
619
|
old_dialog = dialog.clone
|
608
|
-
dialog.width = dialog_render_info.width if dialog_render_info.width
|
609
|
-
height = dialog_render_info.height || DIALOG_HEIGHT
|
610
|
-
pointer = dialog_render_info.pointer
|
611
620
|
dialog.contents = dialog_render_info.contents
|
621
|
+
pointer = dialog_render_info.pointer
|
622
|
+
if dialog_render_info.width
|
623
|
+
dialog.width = dialog_render_info.width
|
624
|
+
else
|
625
|
+
dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
|
626
|
+
end
|
627
|
+
height = dialog_render_info.height || DIALOG_HEIGHT
|
612
628
|
height = dialog.contents.size if dialog.contents.size < height
|
613
629
|
if dialog.contents.size > height
|
614
630
|
if dialog_render_info.pointer
|
@@ -645,6 +661,13 @@ class Reline::LineEditor
|
|
645
661
|
reset_dialog(dialog, old_dialog)
|
646
662
|
move_cursor_down(dialog.vertical_offset)
|
647
663
|
Reline::IOGate.move_cursor_column(dialog.column)
|
664
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
665
|
+
bar_max_height = height * 2
|
666
|
+
moving_distance = (dialog_render_info.contents.size - height) * 2
|
667
|
+
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
|
668
|
+
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
|
669
|
+
position = ((bar_max_height - bar_height) * position_ratio).floor.to_i
|
670
|
+
end
|
648
671
|
dialog.contents.each_with_index do |item, i|
|
649
672
|
if i == pointer
|
650
673
|
bg_color = '45'
|
@@ -656,10 +679,22 @@ class Reline::LineEditor
|
|
656
679
|
end
|
657
680
|
end
|
658
681
|
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width)
|
682
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
683
|
+
if position <= (i * 2) and (i * 2 + 1) < (position + bar_height)
|
684
|
+
str += '█'
|
685
|
+
elsif position <= (i * 2) and (i * 2) < (position + bar_height)
|
686
|
+
str += '▀'
|
687
|
+
elsif position <= (i * 2 + 1) and (i * 2) < (position + bar_height)
|
688
|
+
str += '▄'
|
689
|
+
else
|
690
|
+
str += ' '
|
691
|
+
end
|
692
|
+
end
|
659
693
|
@output.write "\e[#{bg_color}m#{str}\e[49m"
|
660
694
|
Reline::IOGate.move_cursor_column(dialog.column)
|
661
695
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
662
696
|
end
|
697
|
+
dialog.width += 1 if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
663
698
|
Reline::IOGate.move_cursor_column(cursor_column)
|
664
699
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
|
665
700
|
Reline::IOGate.show_cursor
|
@@ -774,6 +809,7 @@ class Reline::LineEditor
|
|
774
809
|
end
|
775
810
|
|
776
811
|
private def clear_each_dialog(dialog)
|
812
|
+
dialog.trap_key = nil
|
777
813
|
return unless dialog.contents
|
778
814
|
prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
|
779
815
|
visual_lines = []
|
@@ -1460,6 +1496,13 @@ class Reline::LineEditor
|
|
1460
1496
|
end
|
1461
1497
|
|
1462
1498
|
def input_key(key)
|
1499
|
+
@last_key = key
|
1500
|
+
@dialogs.each do |dialog|
|
1501
|
+
# The dialog will intercept the key if trap_key is set.
|
1502
|
+
if dialog.trap_key and dialog.trap_key.match?(key)
|
1503
|
+
return
|
1504
|
+
end
|
1505
|
+
end
|
1463
1506
|
@just_cursor_moving = nil
|
1464
1507
|
if key.char.nil?
|
1465
1508
|
if @first_char
|
data/lib/reline/unicode.rb
CHANGED
@@ -101,9 +101,9 @@ class Reline::Unicode
|
|
101
101
|
|
102
102
|
def self.get_mbchar_width(mbchar)
|
103
103
|
ord = mbchar.ord
|
104
|
-
if (0x00 <= ord and ord <= 0x1F)
|
104
|
+
if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs
|
105
105
|
return 2
|
106
|
-
elsif (0x20 <= ord and ord <= 0x7E)
|
106
|
+
elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars
|
107
107
|
return 1
|
108
108
|
end
|
109
109
|
m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
|
@@ -185,7 +185,7 @@ class Reline::Unicode
|
|
185
185
|
[lines, height]
|
186
186
|
end
|
187
187
|
|
188
|
-
# Take a chunk of a String with escape sequences.
|
188
|
+
# Take a chunk of a String cut by width with escape sequences.
|
189
189
|
def self.take_range(str, start_col, max_width, encoding = str.encoding)
|
190
190
|
chunk = String.new(encoding: encoding)
|
191
191
|
total_width = 0
|
data/lib/reline/version.rb
CHANGED
data/lib/reline.rb
CHANGED
@@ -18,13 +18,26 @@ module Reline
|
|
18
18
|
|
19
19
|
Key = Struct.new('Key', :char, :combined_char, :with_meta) do
|
20
20
|
def match?(key)
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
if key.instance_of?(Reline::Key)
|
22
|
+
(key.char.nil? or char.nil? or char == key.char) and
|
23
|
+
(key.combined_char.nil? or combined_char.nil? or combined_char == key.combined_char) and
|
24
|
+
(key.with_meta.nil? or with_meta.nil? or with_meta == key.with_meta)
|
25
|
+
elsif key.is_a?(Integer) or key.is_a?(Symbol)
|
26
|
+
if not combined_char.nil? and combined_char == key
|
27
|
+
true
|
28
|
+
elsif combined_char.nil? and not char.nil? and char == key
|
29
|
+
true
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
else
|
34
|
+
false
|
35
|
+
end
|
24
36
|
end
|
37
|
+
alias_method :==, :match?
|
25
38
|
end
|
26
39
|
CursorPos = Struct.new(:x, :y)
|
27
|
-
DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, keyword_init: true)
|
40
|
+
DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, :scrollbar, keyword_init: true)
|
28
41
|
|
29
42
|
class Core
|
30
43
|
ATTR_READER_NAMES = %i(
|
@@ -228,7 +241,7 @@ module Reline
|
|
228
241
|
context.clear
|
229
242
|
context.push(cursor_pos_to_render, result, pointer, dialog)
|
230
243
|
end
|
231
|
-
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, height: 15)
|
244
|
+
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, scrollbar: true, height: 15)
|
232
245
|
}
|
233
246
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
234
247
|
|
@@ -368,25 +381,9 @@ module Reline
|
|
368
381
|
break
|
369
382
|
when :matching
|
370
383
|
if buffer.size == 1
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
succ_c = Reline::IOGate.getc
|
375
|
-
}
|
376
|
-
rescue Timeout::Error # cancel matching only when first byte
|
377
|
-
block.([Reline::Key.new(c, c, false)])
|
378
|
-
break
|
379
|
-
else
|
380
|
-
if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
|
381
|
-
if c == "\e".ord
|
382
|
-
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
383
|
-
else
|
384
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
385
|
-
end
|
386
|
-
break
|
387
|
-
else
|
388
|
-
Reline::IOGate.ungetc(succ_c)
|
389
|
-
end
|
384
|
+
case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
385
|
+
when :break then break
|
386
|
+
when :next then next
|
390
387
|
end
|
391
388
|
end
|
392
389
|
when :unmatched
|
@@ -403,6 +400,38 @@ module Reline
|
|
403
400
|
end
|
404
401
|
end
|
405
402
|
|
403
|
+
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
404
|
+
begin
|
405
|
+
succ_c = nil
|
406
|
+
Timeout.timeout(keyseq_timeout / 1000.0) {
|
407
|
+
succ_c = Reline::IOGate.getc
|
408
|
+
}
|
409
|
+
rescue Timeout::Error # cancel matching only when first byte
|
410
|
+
block.([Reline::Key.new(c, c, false)])
|
411
|
+
return :break
|
412
|
+
else
|
413
|
+
case key_stroke.match_status(buffer.dup.push(succ_c))
|
414
|
+
when :unmatched
|
415
|
+
if c == "\e".ord
|
416
|
+
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
417
|
+
else
|
418
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
419
|
+
end
|
420
|
+
return :break
|
421
|
+
when :matching
|
422
|
+
Reline::IOGate.ungetc(succ_c)
|
423
|
+
return :next
|
424
|
+
when :matched
|
425
|
+
buffer << succ_c
|
426
|
+
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
427
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
428
|
+
}
|
429
|
+
block.(expanded)
|
430
|
+
return :break
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
406
435
|
private def read_escaped_key(keyseq_timeout, c, block)
|
407
436
|
begin
|
408
437
|
escaped_c = nil
|
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.2.8.pre.
|
4
|
+
version: 0.2.8.pre.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|