reline 0.2.8.pre.9 → 0.2.8.pre.10
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 +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
|