reline 0.2.8.pre.7 → 0.2.8.pre.11
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/config.rb +20 -3
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +63 -14
- data/lib/reline/line_editor.rb +223 -74
- data/lib/reline/terminfo.rb +1 -1
- data/lib/reline/unicode.rb +3 -3
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +18 -16
- data/lib/reline.rb +53 -27
- metadata +3 -4
- data/lib/reline/line_editor.rb.orig +0 -3156
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
|
@@ -150,7 +151,7 @@ class Reline::LineEditor
|
|
150
151
|
@screen_size = Reline::IOGate.get_screen_size
|
151
152
|
@screen_height = @screen_size.first
|
152
153
|
reset_variables(prompt, encoding: encoding)
|
153
|
-
@old_trap = Signal.trap(
|
154
|
+
@old_trap = Signal.trap('INT') {
|
154
155
|
clear_dialog
|
155
156
|
if @scroll_partial_screen
|
156
157
|
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
|
@@ -170,47 +171,85 @@ class Reline::LineEditor
|
|
170
171
|
@old_trap.call
|
171
172
|
end
|
172
173
|
}
|
174
|
+
begin
|
175
|
+
@old_tstp_trap = Signal.trap('TSTP') {
|
176
|
+
Reline::IOGate.ungetc("\C-z".ord)
|
177
|
+
@old_tstp_trap.call if @old_tstp_trap.respond_to?(:call)
|
178
|
+
}
|
179
|
+
rescue ArgumentError
|
180
|
+
end
|
173
181
|
Reline::IOGate.set_winch_handler do
|
174
|
-
@
|
175
|
-
|
176
|
-
|
177
|
-
@
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
182
|
+
@resized = true
|
183
|
+
end
|
184
|
+
if ENV.key?('RELINE_ALT_SCROLLBAR')
|
185
|
+
@full_block = '::'
|
186
|
+
@upper_half_block = "''"
|
187
|
+
@lower_half_block = '..'
|
188
|
+
@block_elem_width = 2
|
189
|
+
elsif Reline::IOGate.win?
|
190
|
+
@full_block = '█'
|
191
|
+
@upper_half_block = '▀'
|
192
|
+
@lower_half_block = '▄'
|
193
|
+
@block_elem_width = 1
|
194
|
+
elsif @encoding == Encoding::UTF_8
|
195
|
+
@full_block = '█'
|
196
|
+
@upper_half_block = '▀'
|
197
|
+
@lower_half_block = '▄'
|
198
|
+
@block_elem_width = Reline::Unicode.calculate_width('█')
|
199
|
+
else
|
200
|
+
@full_block = '::'
|
201
|
+
@upper_half_block = "''"
|
202
|
+
@lower_half_block = '..'
|
203
|
+
@block_elem_width = 2
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def resize
|
208
|
+
return unless @resized
|
209
|
+
@resized = false
|
210
|
+
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
|
211
|
+
old_screen_size = @screen_size
|
212
|
+
@screen_size = Reline::IOGate.get_screen_size
|
213
|
+
@screen_height = @screen_size.first
|
214
|
+
if old_screen_size.last < @screen_size.last # columns increase
|
215
|
+
@rerender_all = true
|
216
|
+
rerender
|
217
|
+
else
|
218
|
+
back = 0
|
219
|
+
new_buffer = whole_lines
|
220
|
+
prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
|
221
|
+
new_buffer.each_with_index do |line, index|
|
222
|
+
prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
|
223
|
+
width = prompt_width + calculate_width(line)
|
224
|
+
height = calculate_height_by_width(width)
|
225
|
+
back += height
|
226
|
+
end
|
227
|
+
@highest_in_all = back
|
228
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
229
|
+
@first_line_started_from =
|
230
|
+
if @line_index.zero?
|
231
|
+
0
|
232
|
+
else
|
233
|
+
calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
|
202
234
|
end
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
207
|
-
@rerender_all = true
|
235
|
+
if @prompt_proc
|
236
|
+
prompt = prompt_list[@line_index]
|
237
|
+
prompt_width = calculate_width(prompt, true)
|
208
238
|
end
|
239
|
+
calculate_nearest_cursor
|
240
|
+
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
241
|
+
Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
|
242
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
243
|
+
@rerender_all = true
|
209
244
|
end
|
210
245
|
end
|
211
246
|
|
212
247
|
def finalize
|
213
|
-
Signal.trap('
|
248
|
+
Signal.trap('INT', @old_trap)
|
249
|
+
begin
|
250
|
+
Signal.trap('TSTP', @old_tstp_trap)
|
251
|
+
rescue ArgumentError
|
252
|
+
end
|
214
253
|
end
|
215
254
|
|
216
255
|
def eof?
|
@@ -252,6 +291,7 @@ class Reline::LineEditor
|
|
252
291
|
@auto_indent_proc = nil
|
253
292
|
@dialogs = []
|
254
293
|
@last_key = nil
|
294
|
+
@resized = false
|
255
295
|
reset_line
|
256
296
|
end
|
257
297
|
|
@@ -548,13 +588,15 @@ class Reline::LineEditor
|
|
548
588
|
|
549
589
|
class Dialog
|
550
590
|
attr_reader :name, :contents, :width
|
551
|
-
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup, :trap_key
|
591
|
+
attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key
|
552
592
|
|
553
|
-
def initialize(name, proc_scope)
|
593
|
+
def initialize(name, config, proc_scope)
|
554
594
|
@name = name
|
595
|
+
@config = config
|
555
596
|
@proc_scope = proc_scope
|
556
597
|
@width = nil
|
557
598
|
@scroll_top = 0
|
599
|
+
@trap_key = nil
|
558
600
|
end
|
559
601
|
|
560
602
|
def set_cursor_pos(col, row)
|
@@ -575,16 +617,28 @@ class Reline::LineEditor
|
|
575
617
|
def call(key)
|
576
618
|
@proc_scope.set_dialog(self)
|
577
619
|
@proc_scope.set_key(key)
|
578
|
-
@proc_scope.call
|
620
|
+
dialog_render_info = @proc_scope.call
|
621
|
+
if @trap_key
|
622
|
+
if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap
|
623
|
+
@trap_key.each do |t|
|
624
|
+
@config.add_oneshot_key_binding(t, @name)
|
625
|
+
end
|
626
|
+
elsif @trap_key.is_a?(Array)
|
627
|
+
@config.add_oneshot_key_binding(@trap_key, @name)
|
628
|
+
elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
|
629
|
+
@config.add_oneshot_key_binding([@trap_key], @name)
|
630
|
+
end
|
631
|
+
end
|
632
|
+
dialog_render_info
|
579
633
|
end
|
580
634
|
end
|
581
635
|
|
582
636
|
def add_dialog_proc(name, p, context = nil)
|
583
637
|
return if @dialogs.any? { |d| d.name == name }
|
584
|
-
@dialogs << Dialog.new(name, DialogProcScope.new(self, @config, p, context))
|
638
|
+
@dialogs << Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
|
585
639
|
end
|
586
640
|
|
587
|
-
|
641
|
+
DIALOG_DEFAULT_HEIGHT = 20
|
588
642
|
private def render_dialog(cursor_column)
|
589
643
|
@dialogs.each do |dialog|
|
590
644
|
render_each_dialog(dialog, cursor_column)
|
@@ -618,31 +672,44 @@ class Reline::LineEditor
|
|
618
672
|
end
|
619
673
|
old_dialog = dialog.clone
|
620
674
|
dialog.contents = dialog_render_info.contents
|
621
|
-
pointer =
|
675
|
+
pointer = dialog.pointer
|
622
676
|
if dialog_render_info.width
|
623
677
|
dialog.width = dialog_render_info.width
|
624
678
|
else
|
625
679
|
dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
|
626
680
|
end
|
627
|
-
height = dialog_render_info.height ||
|
681
|
+
height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
|
628
682
|
height = dialog.contents.size if dialog.contents.size < height
|
629
683
|
if dialog.contents.size > height
|
630
|
-
if
|
631
|
-
if
|
684
|
+
if dialog.pointer
|
685
|
+
if dialog.pointer < 0
|
632
686
|
dialog.scroll_top = 0
|
633
|
-
elsif (
|
634
|
-
dialog.scroll_top =
|
635
|
-
elsif (
|
636
|
-
dialog.scroll_top =
|
687
|
+
elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
|
688
|
+
dialog.scroll_top = dialog.pointer - (height - 1)
|
689
|
+
elsif (dialog.pointer - dialog.scroll_top) < 0
|
690
|
+
dialog.scroll_top = dialog.pointer
|
637
691
|
end
|
638
|
-
pointer =
|
692
|
+
pointer = dialog.pointer - dialog.scroll_top
|
639
693
|
end
|
640
694
|
dialog.contents = dialog.contents[dialog.scroll_top, height]
|
641
695
|
end
|
696
|
+
if dialog.contents and dialog.scroll_top >= dialog.contents.size
|
697
|
+
dialog.scroll_top = dialog.contents.size - height
|
698
|
+
end
|
699
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
700
|
+
bar_max_height = height * 2
|
701
|
+
moving_distance = (dialog_render_info.contents.size - height) * 2
|
702
|
+
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
|
703
|
+
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
|
704
|
+
dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
|
705
|
+
else
|
706
|
+
dialog.scrollbar_pos = nil
|
707
|
+
end
|
642
708
|
upper_space = @first_line_started_from - @started_from
|
643
709
|
lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
|
644
710
|
dialog.column = dialog_render_info.pos.x
|
645
|
-
|
711
|
+
dialog.width += @block_elem_width if dialog.scrollbar_pos
|
712
|
+
diff = (dialog.column + dialog.width) - (@screen_size.last)
|
646
713
|
if diff > 0
|
647
714
|
dialog.column -= diff
|
648
715
|
end
|
@@ -658,6 +725,10 @@ class Reline::LineEditor
|
|
658
725
|
dialog.vertical_offset = dialog_render_info.pos.y + 1
|
659
726
|
end
|
660
727
|
Reline::IOGate.hide_cursor
|
728
|
+
if dialog.column < 0
|
729
|
+
dialog.column = 0
|
730
|
+
dialog.width = @screen_size.last
|
731
|
+
end
|
661
732
|
reset_dialog(dialog, old_dialog)
|
662
733
|
move_cursor_down(dialog.vertical_offset)
|
663
734
|
Reline::IOGate.move_cursor_column(dialog.column)
|
@@ -671,8 +742,23 @@ class Reline::LineEditor
|
|
671
742
|
bg_color = '46'
|
672
743
|
end
|
673
744
|
end
|
674
|
-
|
675
|
-
|
745
|
+
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
|
746
|
+
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
|
747
|
+
@output.write "\e[#{bg_color}m#{str}"
|
748
|
+
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
|
749
|
+
@output.write "\e[37m"
|
750
|
+
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
|
751
|
+
@output.write @full_block
|
752
|
+
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
753
|
+
@output.write @upper_half_block
|
754
|
+
str += ''
|
755
|
+
elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
756
|
+
@output.write @lower_half_block
|
757
|
+
else
|
758
|
+
@output.write ' ' * @block_elem_width
|
759
|
+
end
|
760
|
+
end
|
761
|
+
@output.write "\e[0m"
|
676
762
|
Reline::IOGate.move_cursor_column(dialog.column)
|
677
763
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
678
764
|
end
|
@@ -713,12 +799,12 @@ class Reline::LineEditor
|
|
713
799
|
line_num.times do |i|
|
714
800
|
Reline::IOGate.move_cursor_column(old_dialog.column)
|
715
801
|
if visual_lines[start + i].nil?
|
716
|
-
s = ' ' *
|
802
|
+
s = ' ' * old_dialog.width
|
717
803
|
else
|
718
|
-
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column,
|
719
|
-
s = padding_space_with_escape_sequences(s,
|
804
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
805
|
+
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
720
806
|
end
|
721
|
-
@output.write "\e[
|
807
|
+
@output.write "\e[0m#{s}\e[0m"
|
722
808
|
move_cursor_down(1) if i < (line_num - 1)
|
723
809
|
end
|
724
810
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -731,12 +817,12 @@ class Reline::LineEditor
|
|
731
817
|
line_num.times do |i|
|
732
818
|
Reline::IOGate.move_cursor_column(old_dialog.column)
|
733
819
|
if visual_lines[start + i].nil?
|
734
|
-
s = ' ' *
|
820
|
+
s = ' ' * old_dialog.width
|
735
821
|
else
|
736
|
-
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column,
|
737
|
-
s = padding_space_with_escape_sequences(s,
|
822
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
823
|
+
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
738
824
|
end
|
739
|
-
@output.write "\e[
|
825
|
+
@output.write "\e[0m#{s}\e[0m"
|
740
826
|
move_cursor_down(1) if i < (line_num - 1)
|
741
827
|
end
|
742
828
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
|
@@ -755,7 +841,7 @@ class Reline::LineEditor
|
|
755
841
|
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
|
756
842
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
757
843
|
end
|
758
|
-
@output.write "\e[
|
844
|
+
@output.write "\e[0m#{s}\e[0m"
|
759
845
|
move_cursor_down(1) if i < (line_num - 1)
|
760
846
|
end
|
761
847
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -775,7 +861,7 @@ class Reline::LineEditor
|
|
775
861
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
776
862
|
end
|
777
863
|
Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
|
778
|
-
@output.write "\e[
|
864
|
+
@output.write "\e[0m#{s}\e[0m"
|
779
865
|
move_cursor_down(1) if i < (line_num - 1)
|
780
866
|
end
|
781
867
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
|
@@ -815,10 +901,10 @@ class Reline::LineEditor
|
|
815
901
|
Reline::IOGate.move_cursor_column(dialog.column)
|
816
902
|
str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
|
817
903
|
str = padding_space_with_escape_sequences(str, dialog.width)
|
818
|
-
@output.write "\e[
|
904
|
+
@output.write "\e[0m#{str}\e[0m"
|
819
905
|
else
|
820
906
|
Reline::IOGate.move_cursor_column(dialog.column)
|
821
|
-
@output.write "\e[
|
907
|
+
@output.write "\e[0m#{' ' * dialog.width}\e[0m"
|
822
908
|
end
|
823
909
|
move_cursor_down(1) if i < (dialog_vertical_size - 1)
|
824
910
|
end
|
@@ -1168,7 +1254,7 @@ class Reline::LineEditor
|
|
1168
1254
|
height = render_partial(prompt, prompt_width, line, back, with_control: false)
|
1169
1255
|
end
|
1170
1256
|
if index < (@buffer_of_lines.size - 1)
|
1171
|
-
move_cursor_down(
|
1257
|
+
move_cursor_down(1)
|
1172
1258
|
back += height
|
1173
1259
|
end
|
1174
1260
|
end
|
@@ -1351,7 +1437,10 @@ class Reline::LineEditor
|
|
1351
1437
|
end
|
1352
1438
|
@waiting_operator_proc = nil
|
1353
1439
|
@waiting_operator_vi_arg = nil
|
1354
|
-
@vi_arg
|
1440
|
+
if @vi_arg
|
1441
|
+
@rerender_all = true
|
1442
|
+
@vi_arg = nil
|
1443
|
+
end
|
1355
1444
|
else
|
1356
1445
|
block.(false)
|
1357
1446
|
end
|
@@ -1402,7 +1491,10 @@ class Reline::LineEditor
|
|
1402
1491
|
wrap_method_call(method_symbol, method_obj, key) if method_obj
|
1403
1492
|
end
|
1404
1493
|
@kill_ring.process
|
1405
|
-
@vi_arg
|
1494
|
+
if @vi_arg
|
1495
|
+
@rerender_al = true
|
1496
|
+
@vi_arg = nil
|
1497
|
+
end
|
1406
1498
|
elsif @vi_arg
|
1407
1499
|
if key.chr =~ /[0-9]/
|
1408
1500
|
ed_argument_digit(key)
|
@@ -1419,7 +1511,10 @@ class Reline::LineEditor
|
|
1419
1511
|
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
|
1420
1512
|
end
|
1421
1513
|
@kill_ring.process
|
1422
|
-
@vi_arg
|
1514
|
+
if @vi_arg
|
1515
|
+
@rerender_all = true
|
1516
|
+
@vi_arg = nil
|
1517
|
+
end
|
1423
1518
|
end
|
1424
1519
|
elsif @waiting_proc
|
1425
1520
|
@waiting_proc.(key)
|
@@ -1478,9 +1573,9 @@ class Reline::LineEditor
|
|
1478
1573
|
|
1479
1574
|
def input_key(key)
|
1480
1575
|
@last_key = key
|
1576
|
+
@config.reset_oneshot_key_bindings
|
1481
1577
|
@dialogs.each do |dialog|
|
1482
|
-
|
1483
|
-
if dialog.trap_key and dialog.trap_key.match?(key)
|
1578
|
+
if key.char.instance_of?(Symbol) and key.char == dialog.name
|
1484
1579
|
return
|
1485
1580
|
end
|
1486
1581
|
end
|
@@ -1858,6 +1953,8 @@ class Reline::LineEditor
|
|
1858
1953
|
end
|
1859
1954
|
end
|
1860
1955
|
|
1956
|
+
# Editline:: +ed-unassigned+ This editor command always results in an error.
|
1957
|
+
# GNU Readline:: There is no corresponding macro.
|
1861
1958
|
private def ed_unassigned(key) end # do nothing
|
1862
1959
|
|
1863
1960
|
private def process_insert(force: false)
|
@@ -1875,6 +1972,19 @@ class Reline::LineEditor
|
|
1875
1972
|
@continuous_insertion_buffer.clear
|
1876
1973
|
end
|
1877
1974
|
|
1975
|
+
# Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters)
|
1976
|
+
# In insert mode, insert the input character left of the cursor
|
1977
|
+
# position. In replace mode, overwrite the character at the
|
1978
|
+
# cursor and move the cursor to the right by one character
|
1979
|
+
# position. Accept an argument to do this repeatedly. It is an
|
1980
|
+
# error if the input character is the NUL character (+Ctrl-@+).
|
1981
|
+
# Failure to enlarge the edit buffer also results in an error.
|
1982
|
+
# Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append
|
1983
|
+
# the input digit to the argument being read. Otherwise, call
|
1984
|
+
# +ed-insert+. It is an error if the input character is not a
|
1985
|
+
# digit or if the existing argument is already greater than a
|
1986
|
+
# million.
|
1987
|
+
# GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
|
1878
1988
|
private def ed_insert(key)
|
1879
1989
|
str = nil
|
1880
1990
|
width = nil
|
@@ -1925,6 +2035,8 @@ class Reline::LineEditor
|
|
1925
2035
|
arg.times do
|
1926
2036
|
if key == "\C-j".ord or key == "\C-m".ord
|
1927
2037
|
key_newline(key)
|
2038
|
+
elsif key == 0
|
2039
|
+
# Ignore NUL.
|
1928
2040
|
else
|
1929
2041
|
ed_insert(key)
|
1930
2042
|
end
|
@@ -2359,6 +2471,7 @@ class Reline::LineEditor
|
|
2359
2471
|
arg -= 1
|
2360
2472
|
ed_prev_history(key, arg: arg) if arg > 0
|
2361
2473
|
end
|
2474
|
+
alias_method :previous_history, :ed_prev_history
|
2362
2475
|
|
2363
2476
|
private def ed_next_history(key, arg: 1)
|
2364
2477
|
if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
|
@@ -2406,6 +2519,7 @@ class Reline::LineEditor
|
|
2406
2519
|
arg -= 1
|
2407
2520
|
ed_next_history(key, arg: arg) if arg > 0
|
2408
2521
|
end
|
2522
|
+
alias_method :next_history, :ed_next_history
|
2409
2523
|
|
2410
2524
|
private def ed_newline(key)
|
2411
2525
|
process_insert(force: true)
|
@@ -2440,7 +2554,7 @@ class Reline::LineEditor
|
|
2440
2554
|
end
|
2441
2555
|
end
|
2442
2556
|
|
2443
|
-
private def em_delete_prev_char(key)
|
2557
|
+
private def em_delete_prev_char(key, arg: 1)
|
2444
2558
|
if @is_multiline and @cursor == 0 and @line_index > 0
|
2445
2559
|
@buffer_of_lines[@line_index] = @line
|
2446
2560
|
@cursor = calculate_width(@buffer_of_lines[@line_index - 1])
|
@@ -2458,9 +2572,16 @@ class Reline::LineEditor
|
|
2458
2572
|
@cursor -= width
|
2459
2573
|
@cursor_max -= width
|
2460
2574
|
end
|
2575
|
+
arg -= 1
|
2576
|
+
em_delete_prev_char(key, arg: arg) if arg > 0
|
2461
2577
|
end
|
2462
2578
|
alias_method :backward_delete_char, :em_delete_prev_char
|
2463
2579
|
|
2580
|
+
# Editline:: +ed-kill-line+ (vi command: +D+, +Ctrl-K+; emacs: +Ctrl-K+,
|
2581
|
+
# +Ctrl-U+) + Kill from the cursor to the end of the line.
|
2582
|
+
# GNU Readline:: +kill-line+ (+C-k+) Kill the text from point to the end of
|
2583
|
+
# the line. With a negative numeric argument, kill backward
|
2584
|
+
# from the cursor to the beginning of the current line.
|
2464
2585
|
private def ed_kill_line(key)
|
2465
2586
|
if @line.bytesize > @byte_pointer
|
2466
2587
|
@line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer)
|
@@ -2477,8 +2598,14 @@ class Reline::LineEditor
|
|
2477
2598
|
@rest_height += 1
|
2478
2599
|
end
|
2479
2600
|
end
|
2601
|
+
alias_method :kill_line, :ed_kill_line
|
2480
2602
|
|
2481
|
-
|
2603
|
+
# Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the
|
2604
|
+
# beginning of the edit buffer to the cursor and save it to the
|
2605
|
+
# cut buffer.
|
2606
|
+
# GNU Readline:: +unix-line-discard+ (+C-u+) Kill backward from the cursor
|
2607
|
+
# to the beginning of the current line.
|
2608
|
+
private def vi_kill_line_prev(key)
|
2482
2609
|
if @byte_pointer > 0
|
2483
2610
|
@line, deleted = byteslice!(@line, 0, @byte_pointer)
|
2484
2611
|
@byte_pointer = 0
|
@@ -2487,7 +2614,22 @@ class Reline::LineEditor
|
|
2487
2614
|
@cursor = 0
|
2488
2615
|
end
|
2489
2616
|
end
|
2490
|
-
alias_method :
|
2617
|
+
alias_method :unix_line_discard, :vi_kill_line_prev
|
2618
|
+
|
2619
|
+
# Editline:: +em-kill-line+ (not bound) Delete the entire contents of the
|
2620
|
+
# edit buffer and save it to the cut buffer. +vi-kill-line-prev+
|
2621
|
+
# GNU Readline:: +kill-whole-line+ (not bound) Kill all characters on the
|
2622
|
+
# current line, no matter where point is.
|
2623
|
+
private def em_kill_line(key)
|
2624
|
+
if @line.size > 0
|
2625
|
+
@kill_ring.append(@line.dup, true)
|
2626
|
+
@line.clear
|
2627
|
+
@byte_pointer = 0
|
2628
|
+
@cursor_max = 0
|
2629
|
+
@cursor = 0
|
2630
|
+
end
|
2631
|
+
end
|
2632
|
+
alias_method :kill_whole_line, :em_kill_line
|
2491
2633
|
|
2492
2634
|
private def em_delete(key)
|
2493
2635
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
@@ -2992,7 +3134,14 @@ class Reline::LineEditor
|
|
2992
3134
|
|
2993
3135
|
private def ed_argument_digit(key)
|
2994
3136
|
if @vi_arg.nil?
|
2995
|
-
|
3137
|
+
if key.chr.to_i.zero?
|
3138
|
+
if key.anybits?(0b10000000)
|
3139
|
+
unescaped_key = key ^ 0b10000000
|
3140
|
+
unless unescaped_key.chr.to_i.zero?
|
3141
|
+
@vi_arg = unescaped_key.chr.to_i
|
3142
|
+
end
|
3143
|
+
end
|
3144
|
+
else
|
2996
3145
|
@vi_arg = key.chr.to_i
|
2997
3146
|
end
|
2998
3147
|
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/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/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
|
|
@@ -322,12 +323,13 @@ class Reline::Windows
|
|
322
323
|
end
|
323
324
|
|
324
325
|
def self.erase_after_cursor
|
325
|
-
csbi = 0.chr *
|
326
|
+
csbi = 0.chr * 22
|
326
327
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
327
|
-
|
328
|
+
attributes = csbi[8, 2].unpack1('S')
|
329
|
+
cursor = csbi[4, 4].unpack1('L')
|
328
330
|
written = 0.chr * 4
|
329
331
|
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
|
330
|
-
@@FillConsoleOutputAttribute.call(@@hConsoleHandle,
|
332
|
+
@@FillConsoleOutputAttribute.call(@@hConsoleHandle, attributes, get_screen_size.last - cursor_pos.x, cursor, written)
|
331
333
|
end
|
332
334
|
|
333
335
|
def self.scroll_down(val)
|
@@ -343,8 +345,8 @@ class Reline::Windows
|
|
343
345
|
def self.clear_screen
|
344
346
|
csbi = 0.chr * 22
|
345
347
|
return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
|
346
|
-
buffer_width = csbi[0, 2].
|
347
|
-
attributes = csbi[8, 2].
|
348
|
+
buffer_width = csbi[0, 2].unpack1('S')
|
349
|
+
attributes = csbi[8, 2].unpack1('S')
|
348
350
|
_window_left, window_top, _window_right, window_bottom = *csbi[10,8].unpack('S*')
|
349
351
|
fill_length = buffer_width * (window_bottom - window_top + 1)
|
350
352
|
screen_topleft = window_top * 65536
|