reline 0.2.8.pre.9 → 0.2.8.pre.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/reline/ansi.rb +8 -3
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +59 -62
- data/lib/reline/line_editor.rb +131 -60
- data/lib/reline/terminfo.rb +1 -1
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +15 -14
- data/lib/reline.rb +12 -15
- 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: cdcb3b1edc046520bc5be9cbddb21a4ba498fd1111319c90b05f76b066155eaa
|
4
|
+
data.tar.gz: f5a5af7fb221dc0fb21aac67baa20af7c159f22ee792b5f9264badb1ff8b6ba4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a40a42eb7fe33b39dbf8d56eae76708caee116462bbe35b537e36b39e0edb8263cd5854f48b8c7ef440b686c5dabb7e34c72ec844c2ab79661797c23a28a9f0f
|
7
|
+
data.tar.gz: 9937033c4b7509a3ef39522bc82e574cd6049cfa6204463625bf89ad427ff7c21e36ca3e0a94b11e3b36dfb1cacb2b3a357a3a115e80b13e94eb9512697aea1e
|
data/lib/reline/ansi.rb
CHANGED
@@ -33,11 +33,16 @@ class Reline::ANSI
|
|
33
33
|
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
34
34
|
config.add_default_key_binding_by_keymap(:vi_command, key, func)
|
35
35
|
end
|
36
|
+
{
|
37
|
+
[27, 91, 90] => :completion_journey_up, # S-Tab
|
38
|
+
}.each_pair do |key, func|
|
39
|
+
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
40
|
+
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
41
|
+
end
|
36
42
|
{
|
37
43
|
# default bindings
|
38
44
|
[27, 32] => :em_set_mark, # M-<space>
|
39
45
|
[24, 24] => :em_exchange_mark, # C-x C-x
|
40
|
-
[27, 91, 90] => :completion_journey_up, # S-Tab
|
41
46
|
}.each_pair do |key, func|
|
42
47
|
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
43
48
|
end
|
@@ -126,8 +131,8 @@ class Reline::ANSI
|
|
126
131
|
unless @@buf.empty?
|
127
132
|
return @@buf.shift
|
128
133
|
end
|
129
|
-
until c = @@input.raw(intr: true,
|
130
|
-
|
134
|
+
until c = @@input.raw(intr: true) { select([@@input], [], [], 0.1) && @@input.getbyte }
|
135
|
+
Reline.core.line_editor.resize
|
131
136
|
end
|
132
137
|
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
|
133
138
|
rescue Errno::EIO
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -1,90 +1,87 @@
|
|
1
1
|
class Reline::KeyStroke
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
def initialize(config)
|
3
|
+
@config = config
|
4
|
+
end
|
5
|
+
|
6
|
+
def compress_meta_key(ary)
|
7
|
+
ary.inject([]) { |result, key|
|
8
|
+
if result.size > 0 and result.last == "\e".ord
|
9
|
+
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
10
|
+
else
|
11
|
+
result << key
|
12
|
+
end
|
13
|
+
result
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_with?(me, other)
|
18
|
+
compressed_me = compress_meta_key(me)
|
19
|
+
compressed_other = compress_meta_key(other)
|
20
|
+
i = 0
|
21
|
+
loop do
|
22
|
+
my_c = compressed_me[i]
|
23
|
+
other_c = compressed_other[i]
|
24
|
+
other_is_last = (i + 1) == compressed_other.size
|
25
|
+
me_is_last = (i + 1) == compressed_me.size
|
26
|
+
if my_c != other_c
|
27
|
+
if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
|
28
|
+
return true
|
11
29
|
else
|
12
|
-
|
30
|
+
return false
|
13
31
|
end
|
32
|
+
elsif other_is_last
|
33
|
+
return true
|
34
|
+
elsif me_is_last
|
35
|
+
return false
|
14
36
|
end
|
37
|
+
i += 1
|
15
38
|
end
|
39
|
+
end
|
16
40
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
41
|
+
def equal?(me, other)
|
42
|
+
case me
|
43
|
+
when Array
|
44
|
+
compressed_me = compress_meta_key(me)
|
45
|
+
compressed_other = compress_meta_key(other)
|
46
|
+
compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
|
47
|
+
when Integer
|
48
|
+
if other.is_a?(Reline::Key)
|
49
|
+
if other.combined_char == "\e".ord
|
50
|
+
false
|
51
|
+
else
|
52
|
+
other.combined_char == me
|
39
53
|
end
|
54
|
+
else
|
55
|
+
me == other
|
40
56
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def bytes
|
60
|
-
self
|
57
|
+
when Reline::Key
|
58
|
+
if other.is_a?(Integer)
|
59
|
+
me.combined_char == other
|
60
|
+
else
|
61
|
+
me == other
|
61
62
|
end
|
62
63
|
end
|
63
|
-
}
|
64
|
-
|
65
|
-
def initialize(config)
|
66
|
-
@config = config
|
67
64
|
end
|
68
65
|
|
69
66
|
def match_status(input)
|
70
67
|
key_mapping.keys.select { |lhs|
|
71
|
-
|
68
|
+
start_with?(lhs, input)
|
72
69
|
}.tap { |it|
|
73
|
-
return :matched if it.size == 1 && (it[0]
|
74
|
-
return :matching if it.size == 1 && (it[0]
|
70
|
+
return :matched if it.size == 1 && equal?(it[0], input)
|
71
|
+
return :matching if it.size == 1 && !equal?(it[0], input)
|
75
72
|
return :matched if it.max_by(&:size)&.size&.< input.size
|
76
73
|
return :matching if it.size > 1
|
77
74
|
}
|
78
75
|
key_mapping.keys.select { |lhs|
|
79
|
-
|
76
|
+
start_with?(input, lhs)
|
80
77
|
}.tap { |it|
|
81
78
|
return it.size > 0 ? :matched : :unmatched
|
82
79
|
}
|
83
80
|
end
|
84
81
|
|
85
82
|
def expand(input)
|
86
|
-
input = input
|
87
|
-
lhs = key_mapping.keys.select { |item|
|
83
|
+
input = compress_meta_key(input)
|
84
|
+
lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
|
88
85
|
return input unless lhs
|
89
86
|
rhs = key_mapping[lhs]
|
90
87
|
|
data/lib/reline/line_editor.rb
CHANGED
@@ -5,6 +5,7 @@ require 'tempfile'
|
|
5
5
|
|
6
6
|
class Reline::LineEditor
|
7
7
|
# TODO: undo
|
8
|
+
# TODO: Use "private alias_method" idiom after drop Ruby 2.5.
|
8
9
|
attr_reader :line
|
9
10
|
attr_reader :byte_pointer
|
10
11
|
attr_accessor :confirm_multiline_termination_proc
|
@@ -178,43 +179,49 @@ class Reline::LineEditor
|
|
178
179
|
rescue ArgumentError
|
179
180
|
end
|
180
181
|
Reline::IOGate.set_winch_handler do
|
181
|
-
@
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
182
|
+
@resized = true
|
183
|
+
end
|
184
|
+
@block_elem_width = Reline::Unicode.calculate_width('█')
|
185
|
+
end
|
186
|
+
|
187
|
+
def resize
|
188
|
+
return unless @resized
|
189
|
+
@resized = false
|
190
|
+
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
|
191
|
+
old_screen_size = @screen_size
|
192
|
+
@screen_size = Reline::IOGate.get_screen_size
|
193
|
+
@screen_height = @screen_size.first
|
194
|
+
if old_screen_size.last < @screen_size.last # columns increase
|
195
|
+
@rerender_all = true
|
196
|
+
rerender
|
197
|
+
else
|
198
|
+
back = 0
|
199
|
+
new_buffer = whole_lines
|
200
|
+
prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
|
201
|
+
new_buffer.each_with_index do |line, index|
|
202
|
+
prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
|
203
|
+
width = prompt_width + calculate_width(line)
|
204
|
+
height = calculate_height_by_width(width)
|
205
|
+
back += height
|
206
|
+
end
|
207
|
+
@highest_in_all = back
|
208
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
209
|
+
@first_line_started_from =
|
210
|
+
if @line_index.zero?
|
211
|
+
0
|
212
|
+
else
|
213
|
+
calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
|
209
214
|
end
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
214
|
-
@rerender_all = true
|
215
|
+
if @prompt_proc
|
216
|
+
prompt = prompt_list[@line_index]
|
217
|
+
prompt_width = calculate_width(prompt, true)
|
215
218
|
end
|
219
|
+
calculate_nearest_cursor
|
220
|
+
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
221
|
+
Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
|
222
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
223
|
+
@rerender_all = true
|
216
224
|
end
|
217
|
-
@block_elem_width = Reline::Unicode.calculate_width('█')
|
218
225
|
end
|
219
226
|
|
220
227
|
def finalize
|
@@ -264,6 +271,7 @@ class Reline::LineEditor
|
|
264
271
|
@auto_indent_proc = nil
|
265
272
|
@dialogs = []
|
266
273
|
@last_key = nil
|
274
|
+
@resized = false
|
267
275
|
reset_line
|
268
276
|
end
|
269
277
|
|
@@ -560,7 +568,7 @@ class Reline::LineEditor
|
|
560
568
|
|
561
569
|
class Dialog
|
562
570
|
attr_reader :name, :contents, :width
|
563
|
-
attr_accessor :scroll_top, :scrollbar_pos, :column, :vertical_offset, :lines_backup, :trap_key
|
571
|
+
attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key
|
564
572
|
|
565
573
|
def initialize(name, config, proc_scope)
|
566
574
|
@name = name
|
@@ -568,6 +576,7 @@ class Reline::LineEditor
|
|
568
576
|
@proc_scope = proc_scope
|
569
577
|
@width = nil
|
570
578
|
@scroll_top = 0
|
579
|
+
@trap_key = nil
|
571
580
|
end
|
572
581
|
|
573
582
|
def set_cursor_pos(col, row)
|
@@ -643,7 +652,7 @@ class Reline::LineEditor
|
|
643
652
|
end
|
644
653
|
old_dialog = dialog.clone
|
645
654
|
dialog.contents = dialog_render_info.contents
|
646
|
-
pointer =
|
655
|
+
pointer = dialog.pointer
|
647
656
|
if dialog_render_info.width
|
648
657
|
dialog.width = dialog_render_info.width
|
649
658
|
else
|
@@ -652,15 +661,15 @@ class Reline::LineEditor
|
|
652
661
|
height = dialog_render_info.height || DIALOG_HEIGHT
|
653
662
|
height = dialog.contents.size if dialog.contents.size < height
|
654
663
|
if dialog.contents.size > height
|
655
|
-
if
|
656
|
-
if
|
664
|
+
if dialog.pointer
|
665
|
+
if dialog.pointer < 0
|
657
666
|
dialog.scroll_top = 0
|
658
|
-
elsif (
|
659
|
-
dialog.scroll_top =
|
660
|
-
elsif (
|
661
|
-
dialog.scroll_top =
|
667
|
+
elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
|
668
|
+
dialog.scroll_top = dialog.pointer - (height - 1)
|
669
|
+
elsif (dialog.pointer - dialog.scroll_top) < 0
|
670
|
+
dialog.scroll_top = dialog.pointer
|
662
671
|
end
|
663
|
-
pointer =
|
672
|
+
pointer = dialog.pointer - dialog.scroll_top
|
664
673
|
end
|
665
674
|
dialog.contents = dialog.contents[dialog.scroll_top, height]
|
666
675
|
end
|
@@ -711,19 +720,18 @@ class Reline::LineEditor
|
|
711
720
|
@output.write "\e[#{bg_color}m#{str}"
|
712
721
|
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
|
713
722
|
@output.write "\e[37m"
|
714
|
-
if dialog.scrollbar_pos <= (i * 2) and (i * 2 +
|
723
|
+
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
|
715
724
|
@output.write '█'
|
716
725
|
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
717
726
|
@output.write '▀'
|
718
727
|
str += ''
|
719
|
-
elsif dialog.scrollbar_pos <= (i * 2 +
|
728
|
+
elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
720
729
|
@output.write '▄'
|
721
730
|
else
|
722
731
|
@output.write ' ' * @block_elem_width
|
723
732
|
end
|
724
|
-
@output.write "\e[39m"
|
725
733
|
end
|
726
|
-
@output.write "\e[
|
734
|
+
@output.write "\e[0m"
|
727
735
|
Reline::IOGate.move_cursor_column(dialog.column)
|
728
736
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
729
737
|
end
|
@@ -769,7 +777,7 @@ class Reline::LineEditor
|
|
769
777
|
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
770
778
|
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
771
779
|
end
|
772
|
-
@output.write "\e[
|
780
|
+
@output.write "\e[0m#{s}\e[0m"
|
773
781
|
move_cursor_down(1) if i < (line_num - 1)
|
774
782
|
end
|
775
783
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -787,7 +795,7 @@ class Reline::LineEditor
|
|
787
795
|
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
788
796
|
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
789
797
|
end
|
790
|
-
@output.write "\e[
|
798
|
+
@output.write "\e[0m#{s}\e[0m"
|
791
799
|
move_cursor_down(1) if i < (line_num - 1)
|
792
800
|
end
|
793
801
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
|
@@ -806,7 +814,7 @@ class Reline::LineEditor
|
|
806
814
|
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
|
807
815
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
808
816
|
end
|
809
|
-
@output.write "\e[
|
817
|
+
@output.write "\e[0m#{s}\e[0m"
|
810
818
|
move_cursor_down(1) if i < (line_num - 1)
|
811
819
|
end
|
812
820
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -826,7 +834,7 @@ class Reline::LineEditor
|
|
826
834
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
827
835
|
end
|
828
836
|
Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
|
829
|
-
@output.write "\e[
|
837
|
+
@output.write "\e[0m#{s}\e[0m"
|
830
838
|
move_cursor_down(1) if i < (line_num - 1)
|
831
839
|
end
|
832
840
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
|
@@ -866,10 +874,10 @@ class Reline::LineEditor
|
|
866
874
|
Reline::IOGate.move_cursor_column(dialog.column)
|
867
875
|
str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
|
868
876
|
str = padding_space_with_escape_sequences(str, dialog.width)
|
869
|
-
@output.write "\e[
|
877
|
+
@output.write "\e[0m#{str}\e[0m"
|
870
878
|
else
|
871
879
|
Reline::IOGate.move_cursor_column(dialog.column)
|
872
|
-
@output.write "\e[
|
880
|
+
@output.write "\e[0m#{' ' * dialog.width}\e[0m"
|
873
881
|
end
|
874
882
|
move_cursor_down(1) if i < (dialog_vertical_size - 1)
|
875
883
|
end
|
@@ -1402,7 +1410,10 @@ class Reline::LineEditor
|
|
1402
1410
|
end
|
1403
1411
|
@waiting_operator_proc = nil
|
1404
1412
|
@waiting_operator_vi_arg = nil
|
1405
|
-
@vi_arg
|
1413
|
+
if @vi_arg
|
1414
|
+
@rerender_all = true
|
1415
|
+
@vi_arg = nil
|
1416
|
+
end
|
1406
1417
|
else
|
1407
1418
|
block.(false)
|
1408
1419
|
end
|
@@ -1453,7 +1464,10 @@ class Reline::LineEditor
|
|
1453
1464
|
wrap_method_call(method_symbol, method_obj, key) if method_obj
|
1454
1465
|
end
|
1455
1466
|
@kill_ring.process
|
1456
|
-
@vi_arg
|
1467
|
+
if @vi_arg
|
1468
|
+
@rerender_al = true
|
1469
|
+
@vi_arg = nil
|
1470
|
+
end
|
1457
1471
|
elsif @vi_arg
|
1458
1472
|
if key.chr =~ /[0-9]/
|
1459
1473
|
ed_argument_digit(key)
|
@@ -1470,7 +1484,10 @@ class Reline::LineEditor
|
|
1470
1484
|
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
|
1471
1485
|
end
|
1472
1486
|
@kill_ring.process
|
1473
|
-
@vi_arg
|
1487
|
+
if @vi_arg
|
1488
|
+
@rerender_all = true
|
1489
|
+
@vi_arg = nil
|
1490
|
+
end
|
1474
1491
|
end
|
1475
1492
|
elsif @waiting_proc
|
1476
1493
|
@waiting_proc.(key)
|
@@ -1909,6 +1926,8 @@ class Reline::LineEditor
|
|
1909
1926
|
end
|
1910
1927
|
end
|
1911
1928
|
|
1929
|
+
# Editline:: +ed-unassigned+ This editor command always results in an error.
|
1930
|
+
# GNU Readline:: There is no corresponding macro.
|
1912
1931
|
private def ed_unassigned(key) end # do nothing
|
1913
1932
|
|
1914
1933
|
private def process_insert(force: false)
|
@@ -1926,6 +1945,19 @@ class Reline::LineEditor
|
|
1926
1945
|
@continuous_insertion_buffer.clear
|
1927
1946
|
end
|
1928
1947
|
|
1948
|
+
# Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters)
|
1949
|
+
# In insert mode, insert the input character left of the cursor
|
1950
|
+
# position. In replace mode, overwrite the character at the
|
1951
|
+
# cursor and move the cursor to the right by one character
|
1952
|
+
# position. Accept an argument to do this repeatedly. It is an
|
1953
|
+
# error if the input character is the NUL character (+Ctrl-@+).
|
1954
|
+
# Failure to enlarge the edit buffer also results in an error.
|
1955
|
+
# Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append
|
1956
|
+
# the input digit to the argument being read. Otherwise, call
|
1957
|
+
# +ed-insert+. It is an error if the input character is not a
|
1958
|
+
# digit or if the existing argument is already greater than a
|
1959
|
+
# million.
|
1960
|
+
# GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
|
1929
1961
|
private def ed_insert(key)
|
1930
1962
|
str = nil
|
1931
1963
|
width = nil
|
@@ -1976,6 +2008,8 @@ class Reline::LineEditor
|
|
1976
2008
|
arg.times do
|
1977
2009
|
if key == "\C-j".ord or key == "\C-m".ord
|
1978
2010
|
key_newline(key)
|
2011
|
+
elsif key == 0
|
2012
|
+
# Ignore NUL.
|
1979
2013
|
else
|
1980
2014
|
ed_insert(key)
|
1981
2015
|
end
|
@@ -2410,6 +2444,7 @@ class Reline::LineEditor
|
|
2410
2444
|
arg -= 1
|
2411
2445
|
ed_prev_history(key, arg: arg) if arg > 0
|
2412
2446
|
end
|
2447
|
+
alias_method :previous_history, :ed_prev_history
|
2413
2448
|
|
2414
2449
|
private def ed_next_history(key, arg: 1)
|
2415
2450
|
if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
|
@@ -2457,6 +2492,7 @@ class Reline::LineEditor
|
|
2457
2492
|
arg -= 1
|
2458
2493
|
ed_next_history(key, arg: arg) if arg > 0
|
2459
2494
|
end
|
2495
|
+
alias_method :next_history, :ed_next_history
|
2460
2496
|
|
2461
2497
|
private def ed_newline(key)
|
2462
2498
|
process_insert(force: true)
|
@@ -2491,7 +2527,7 @@ class Reline::LineEditor
|
|
2491
2527
|
end
|
2492
2528
|
end
|
2493
2529
|
|
2494
|
-
private def em_delete_prev_char(key)
|
2530
|
+
private def em_delete_prev_char(key, arg: 1)
|
2495
2531
|
if @is_multiline and @cursor == 0 and @line_index > 0
|
2496
2532
|
@buffer_of_lines[@line_index] = @line
|
2497
2533
|
@cursor = calculate_width(@buffer_of_lines[@line_index - 1])
|
@@ -2509,9 +2545,16 @@ class Reline::LineEditor
|
|
2509
2545
|
@cursor -= width
|
2510
2546
|
@cursor_max -= width
|
2511
2547
|
end
|
2548
|
+
arg -= 1
|
2549
|
+
em_delete_prev_char(key, arg: arg) if arg > 0
|
2512
2550
|
end
|
2513
2551
|
alias_method :backward_delete_char, :em_delete_prev_char
|
2514
2552
|
|
2553
|
+
# Editline:: +ed-kill-line+ (vi command: +D+, +Ctrl-K+; emacs: +Ctrl-K+,
|
2554
|
+
# +Ctrl-U+) + Kill from the cursor to the end of the line.
|
2555
|
+
# GNU Readline:: +kill-line+ (+C-k+) Kill the text from point to the end of
|
2556
|
+
# the line. With a negative numeric argument, kill backward
|
2557
|
+
# from the cursor to the beginning of the current line.
|
2515
2558
|
private def ed_kill_line(key)
|
2516
2559
|
if @line.bytesize > @byte_pointer
|
2517
2560
|
@line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer)
|
@@ -2528,8 +2571,14 @@ class Reline::LineEditor
|
|
2528
2571
|
@rest_height += 1
|
2529
2572
|
end
|
2530
2573
|
end
|
2574
|
+
alias_method :kill_line, :ed_kill_line
|
2531
2575
|
|
2532
|
-
|
2576
|
+
# Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the
|
2577
|
+
# beginning of the edit buffer to the cursor and save it to the
|
2578
|
+
# cut buffer.
|
2579
|
+
# GNU Readline:: +unix-line-discard+ (+C-u+) Kill backward from the cursor
|
2580
|
+
# to the beginning of the current line.
|
2581
|
+
private def vi_kill_line_prev(key)
|
2533
2582
|
if @byte_pointer > 0
|
2534
2583
|
@line, deleted = byteslice!(@line, 0, @byte_pointer)
|
2535
2584
|
@byte_pointer = 0
|
@@ -2538,7 +2587,22 @@ class Reline::LineEditor
|
|
2538
2587
|
@cursor = 0
|
2539
2588
|
end
|
2540
2589
|
end
|
2541
|
-
alias_method :
|
2590
|
+
alias_method :unix_line_discard, :vi_kill_line_prev
|
2591
|
+
|
2592
|
+
# Editline:: +em-kill-line+ (not bound) Delete the entire contents of the
|
2593
|
+
# edit buffer and save it to the cut buffer. +vi-kill-line-prev+
|
2594
|
+
# GNU Readline:: +kill-whole-line+ (not bound) Kill all characters on the
|
2595
|
+
# current line, no matter where point is.
|
2596
|
+
private def em_kill_line(key)
|
2597
|
+
if @line.size > 0
|
2598
|
+
@kill_ring.append(@line.dup, true)
|
2599
|
+
@line.clear
|
2600
|
+
@byte_pointer = 0
|
2601
|
+
@cursor_max = 0
|
2602
|
+
@cursor = 0
|
2603
|
+
end
|
2604
|
+
end
|
2605
|
+
alias_method :kill_whole_line, :em_kill_line
|
2542
2606
|
|
2543
2607
|
private def em_delete(key)
|
2544
2608
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
@@ -3043,7 +3107,14 @@ class Reline::LineEditor
|
|
3043
3107
|
|
3044
3108
|
private def ed_argument_digit(key)
|
3045
3109
|
if @vi_arg.nil?
|
3046
|
-
|
3110
|
+
if key.chr.to_i.zero?
|
3111
|
+
if key.anybits?(0b10000000)
|
3112
|
+
unescaped_key = key ^ 0b10000000
|
3113
|
+
unless unescaped_key.chr.to_i.zero?
|
3114
|
+
@vi_arg = unescaped_key.chr.to_i
|
3115
|
+
end
|
3116
|
+
end
|
3117
|
+
else
|
3047
3118
|
@vi_arg = key.chr.to_i
|
3048
3119
|
end
|
3049
3120
|
else
|
data/lib/reline/terminfo.rb
CHANGED
@@ -71,7 +71,7 @@ module Reline::Terminfo
|
|
71
71
|
def self.setupterm(term, fildes)
|
72
72
|
errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
|
73
73
|
ret = @setupterm.(term, fildes, errret_int)
|
74
|
-
errret = errret_int.
|
74
|
+
errret = errret_int.unpack1('i')
|
75
75
|
case ret
|
76
76
|
when 0 # OK
|
77
77
|
0
|
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -184,7 +184,7 @@ class Reline::Windows
|
|
184
184
|
# DWORD FileNameLength;
|
185
185
|
# WCHAR FileName[1];
|
186
186
|
# } FILE_NAME_INFO
|
187
|
-
len = p_buffer[0, 4].
|
187
|
+
len = p_buffer[0, 4].unpack1("L")
|
188
188
|
name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
|
189
189
|
|
190
190
|
# Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
|
@@ -234,22 +234,23 @@ class Reline::Windows
|
|
234
234
|
def self.check_input_event
|
235
235
|
num_of_events = 0.chr * 8
|
236
236
|
while @@output_buf.empty? #or true
|
237
|
+
Reline.core.line_editor.resize
|
237
238
|
next if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
|
238
|
-
next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.
|
239
|
+
next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
|
239
240
|
input_record = 0.chr * 18
|
240
241
|
read_event = 0.chr * 4
|
241
242
|
if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
|
242
|
-
event = input_record[0, 2].
|
243
|
+
event = input_record[0, 2].unpack1('s*')
|
243
244
|
case event
|
244
245
|
when WINDOW_BUFFER_SIZE_EVENT
|
245
246
|
@@winch_handler.()
|
246
247
|
when KEY_EVENT
|
247
|
-
key_down = input_record[4, 4].
|
248
|
-
repeat_count = input_record[8, 2].
|
249
|
-
virtual_key_code = input_record[10, 2].
|
250
|
-
virtual_scan_code = input_record[12, 2].
|
251
|
-
char_code = input_record[14, 2].
|
252
|
-
control_key_state = input_record[16, 2].
|
248
|
+
key_down = input_record[4, 4].unpack1('l*')
|
249
|
+
repeat_count = input_record[8, 2].unpack1('s*')
|
250
|
+
virtual_key_code = input_record[10, 2].unpack1('s*')
|
251
|
+
virtual_scan_code = input_record[12, 2].unpack1('s*')
|
252
|
+
char_code = input_record[14, 2].unpack1('S*')
|
253
|
+
control_key_state = input_record[16, 2].unpack1('S*')
|
253
254
|
is_key_down = key_down.zero? ? false : true
|
254
255
|
if is_key_down
|
255
256
|
process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
@@ -291,8 +292,8 @@ class Reline::Windows
|
|
291
292
|
def self.cursor_pos
|
292
293
|
csbi = 0.chr * 22
|
293
294
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
294
|
-
x = csbi[4, 2].
|
295
|
-
y = csbi[6, 2].
|
295
|
+
x = csbi[4, 2].unpack1('s*')
|
296
|
+
y = csbi[6, 2].unpack1('s*')
|
296
297
|
Reline::CursorPos.new(x, y)
|
297
298
|
end
|
298
299
|
|
@@ -324,7 +325,7 @@ class Reline::Windows
|
|
324
325
|
def self.erase_after_cursor
|
325
326
|
csbi = 0.chr * 24
|
326
327
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
327
|
-
cursor = csbi[4, 4].
|
328
|
+
cursor = csbi[4, 4].unpack1('L')
|
328
329
|
written = 0.chr * 4
|
329
330
|
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
|
330
331
|
@@FillConsoleOutputAttribute.call(@@hConsoleHandle, 0, get_screen_size.last - cursor_pos.x, cursor, written)
|
@@ -343,8 +344,8 @@ class Reline::Windows
|
|
343
344
|
def self.clear_screen
|
344
345
|
csbi = 0.chr * 22
|
345
346
|
return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
|
346
|
-
buffer_width = csbi[0, 2].
|
347
|
-
attributes = csbi[8, 2].
|
347
|
+
buffer_width = csbi[0, 2].unpack1('S')
|
348
|
+
attributes = csbi[8, 2].unpack1('S')
|
348
349
|
_window_left, window_top, _window_right, window_bottom = *csbi[10,8].unpack('S*')
|
349
350
|
fill_length = buffer_width * (window_bottom - window_top + 1)
|
350
351
|
screen_topleft = window_top * 65536
|
data/lib/reline.rb
CHANGED
@@ -17,19 +17,15 @@ module Reline
|
|
17
17
|
class ConfigEncodingConversionError < StandardError; end
|
18
18
|
|
19
19
|
Key = Struct.new('Key', :char, :combined_char, :with_meta) do
|
20
|
-
def match?(
|
21
|
-
|
22
|
-
|
23
|
-
(
|
24
|
-
(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
true
|
30
|
-
else
|
31
|
-
false
|
32
|
-
end
|
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)
|
33
29
|
else
|
34
30
|
false
|
35
31
|
end
|
@@ -37,7 +33,7 @@ module Reline
|
|
37
33
|
alias_method :==, :match?
|
38
34
|
end
|
39
35
|
CursorPos = Struct.new(:x, :y)
|
40
|
-
DialogRenderInfo = Struct.new(:pos, :contents, :
|
36
|
+
DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)
|
41
37
|
|
42
38
|
class Core
|
43
39
|
ATTR_READER_NAMES = %i(
|
@@ -241,7 +237,8 @@ module Reline
|
|
241
237
|
context.clear
|
242
238
|
context.push(cursor_pos_to_render, result, pointer, dialog)
|
243
239
|
end
|
244
|
-
|
240
|
+
dialog.pointer = pointer
|
241
|
+
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15)
|
245
242
|
}
|
246
243
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
247
244
|
|
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.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|