reline 0.2.8.pre.2 → 0.2.8.pre.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/reline/general_io.rb +1 -0
- data/lib/reline/line_editor.rb +113 -67
- data/lib/reline/unicode.rb +6 -5
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +5 -3
- 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: 161818586702ae2834bf5e6490adf5dcec415256925ffd83339ffe6ef3c13012
|
4
|
+
data.tar.gz: 3ab65900ed4022e1baa2213d560938339711264e3188597c4eb98bc1891c81a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 610c5367d68b627fb7e0a7bef7919d147b5a19539725f9a2d184bbed69b0988c613acf1f001d2f05857fce2490e7309e666a4327f1f15cd0541e3bb7db5089ec
|
7
|
+
data.tar.gz: b567f8283fe5637161e21536f500f6824d9a92aadf940e10386d27cf4df29940d3e3d6cb95a7a4fff6e711ac33c73f870ee419b45d44274184160b37354d9d77
|
data/lib/reline/general_io.rb
CHANGED
data/lib/reline/line_editor.rb
CHANGED
@@ -499,6 +499,14 @@ class Reline::LineEditor
|
|
499
499
|
@line_editor.call_completion_proc_with_checking_args(pre, target, post)
|
500
500
|
end
|
501
501
|
|
502
|
+
def set_dialog(dialog)
|
503
|
+
@dialog = dialog
|
504
|
+
end
|
505
|
+
|
506
|
+
def dialog
|
507
|
+
@dialog
|
508
|
+
end
|
509
|
+
|
502
510
|
def set_cursor_pos(col, row)
|
503
511
|
@cursor_pos.x = col
|
504
512
|
@cursor_pos.y = row
|
@@ -530,19 +538,33 @@ class Reline::LineEditor
|
|
530
538
|
end
|
531
539
|
|
532
540
|
class Dialog
|
533
|
-
attr_reader :name
|
534
|
-
attr_accessor :
|
541
|
+
attr_reader :name, :contents, :width
|
542
|
+
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup
|
535
543
|
|
536
544
|
def initialize(name, proc_scope)
|
537
545
|
@name = name
|
538
546
|
@proc_scope = proc_scope
|
547
|
+
@width = nil
|
548
|
+
@scroll_top = 0
|
539
549
|
end
|
540
550
|
|
541
551
|
def set_cursor_pos(col, row)
|
542
552
|
@proc_scope.set_cursor_pos(col, row)
|
543
553
|
end
|
544
554
|
|
555
|
+
def width=(v)
|
556
|
+
@width = v
|
557
|
+
end
|
558
|
+
|
559
|
+
def contents=(contents)
|
560
|
+
@contents = contents
|
561
|
+
if contents and @width.nil?
|
562
|
+
@width = contents.map{ |line| Reline::Unicode.calculate_width(line, true) }.max
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
545
566
|
def call
|
567
|
+
@proc_scope.set_dialog(self)
|
546
568
|
@proc_scope.call
|
547
569
|
end
|
548
570
|
end
|
@@ -553,27 +575,24 @@ class Reline::LineEditor
|
|
553
575
|
end
|
554
576
|
|
555
577
|
DIALOG_HEIGHT = 20
|
556
|
-
DIALOG_WIDTH = 40
|
557
578
|
private def render_dialog(cursor_column)
|
558
579
|
@dialogs.each do |dialog|
|
559
580
|
render_each_dialog(dialog, cursor_column)
|
560
581
|
end
|
561
582
|
end
|
562
583
|
|
584
|
+
private def padding_space_with_escape_sequences(str, width)
|
585
|
+
str + (' ' * (width - calculate_width(str, true)))
|
586
|
+
end
|
587
|
+
|
563
588
|
private def render_each_dialog(dialog, cursor_column)
|
564
589
|
if @in_pasting
|
565
590
|
dialog.contents = nil
|
566
591
|
return
|
567
592
|
end
|
568
593
|
dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
|
569
|
-
|
570
|
-
|
571
|
-
old_dialog_column = dialog.column
|
572
|
-
old_dialog_vertical_offset = dialog.vertical_offset
|
573
|
-
if result and not result.empty?
|
574
|
-
dialog.contents = result
|
575
|
-
dialog.contents = dialog.contents[0...DIALOG_HEIGHT] if dialog.contents.size > DIALOG_HEIGHT
|
576
|
-
else
|
594
|
+
dialog_render_info = dialog.call
|
595
|
+
if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
|
577
596
|
dialog.lines_backup = {
|
578
597
|
lines: modify_lines(whole_lines),
|
579
598
|
line_index: @line_index,
|
@@ -585,39 +604,59 @@ class Reline::LineEditor
|
|
585
604
|
dialog.contents = nil
|
586
605
|
return
|
587
606
|
end
|
607
|
+
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
|
+
dialog.contents = dialog_render_info.contents
|
612
|
+
height = dialog.contents.size if dialog.contents.size < height
|
613
|
+
if dialog.contents.size > height
|
614
|
+
if dialog_render_info.pointer
|
615
|
+
if dialog_render_info.pointer < 0
|
616
|
+
dialog.scroll_top = 0
|
617
|
+
elsif (dialog_render_info.pointer - dialog.scroll_top) >= (height - 1)
|
618
|
+
dialog.scroll_top = dialog_render_info.pointer - (height - 1)
|
619
|
+
elsif (dialog_render_info.pointer - dialog.scroll_top) < 0
|
620
|
+
dialog.scroll_top = dialog_render_info.pointer
|
621
|
+
end
|
622
|
+
pointer = dialog_render_info.pointer - dialog.scroll_top
|
623
|
+
end
|
624
|
+
dialog.contents = dialog.contents[dialog.scroll_top, height]
|
625
|
+
end
|
588
626
|
upper_space = @first_line_started_from - @started_from
|
589
627
|
lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
|
590
|
-
dialog.column = pos.x
|
591
|
-
diff = (dialog.column +
|
628
|
+
dialog.column = dialog_render_info.pos.x
|
629
|
+
diff = (dialog.column + dialog.width) - (@screen_size.last - 1)
|
592
630
|
if diff > 0
|
593
631
|
dialog.column -= diff
|
594
632
|
end
|
595
|
-
if (lower_space + @rest_height) >=
|
596
|
-
dialog.vertical_offset = pos.y + 1
|
597
|
-
elsif upper_space >=
|
598
|
-
dialog.vertical_offset = pos.y
|
633
|
+
if (lower_space + @rest_height - dialog_render_info.pos.y) >= height
|
634
|
+
dialog.vertical_offset = dialog_render_info.pos.y + 1
|
635
|
+
elsif upper_space >= height
|
636
|
+
dialog.vertical_offset = dialog_render_info.pos.y - height
|
599
637
|
else
|
600
|
-
if (lower_space + @rest_height) <
|
601
|
-
scroll_down(
|
602
|
-
move_cursor_up(
|
638
|
+
if (lower_space + @rest_height - dialog_render_info.pos.y) < height
|
639
|
+
scroll_down(height + dialog_render_info.pos.y)
|
640
|
+
move_cursor_up(height + dialog_render_info.pos.y)
|
603
641
|
end
|
604
|
-
dialog.vertical_offset = pos.y + 1
|
642
|
+
dialog.vertical_offset = dialog_render_info.pos.y + 1
|
605
643
|
end
|
606
644
|
Reline::IOGate.hide_cursor
|
607
|
-
reset_dialog(dialog,
|
645
|
+
reset_dialog(dialog, old_dialog)
|
608
646
|
move_cursor_down(dialog.vertical_offset)
|
609
647
|
Reline::IOGate.move_cursor_column(dialog.column)
|
610
648
|
dialog.contents.each_with_index do |item, i|
|
611
649
|
if i == pointer
|
612
650
|
bg_color = '45'
|
613
651
|
else
|
614
|
-
if
|
615
|
-
bg_color =
|
652
|
+
if dialog_render_info.bg_color
|
653
|
+
bg_color = dialog_render_info.bg_color
|
616
654
|
else
|
617
655
|
bg_color = '46'
|
618
656
|
end
|
619
657
|
end
|
620
|
-
|
658
|
+
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width)
|
659
|
+
@output.write "\e[#{bg_color}m#{str}\e[49m"
|
621
660
|
Reline::IOGate.move_cursor_column(dialog.column)
|
622
661
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
623
662
|
end
|
@@ -633,8 +672,8 @@ class Reline::LineEditor
|
|
633
672
|
}
|
634
673
|
end
|
635
674
|
|
636
|
-
private def reset_dialog(dialog,
|
637
|
-
return if dialog.lines_backup.nil? or
|
675
|
+
private def reset_dialog(dialog, old_dialog)
|
676
|
+
return if dialog.lines_backup.nil? or old_dialog.contents.nil?
|
638
677
|
prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
|
639
678
|
visual_lines = []
|
640
679
|
visual_start = nil
|
@@ -650,76 +689,80 @@ class Reline::LineEditor
|
|
650
689
|
old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from]
|
651
690
|
y = @first_line_started_from + @started_from
|
652
691
|
y_diff = y - old_y
|
653
|
-
if (old_y +
|
692
|
+
if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset)
|
654
693
|
# rerender top
|
655
|
-
move_cursor_down(
|
656
|
-
start = visual_start +
|
657
|
-
line_num = dialog.vertical_offset -
|
694
|
+
move_cursor_down(old_dialog.vertical_offset - y_diff)
|
695
|
+
start = visual_start + old_dialog.vertical_offset
|
696
|
+
line_num = dialog.vertical_offset - old_dialog.vertical_offset
|
658
697
|
line_num.times do |i|
|
659
|
-
Reline::IOGate.move_cursor_column(
|
698
|
+
Reline::IOGate.move_cursor_column(old_dialog.column)
|
660
699
|
if visual_lines[start + i].nil?
|
661
|
-
s = ' ' *
|
700
|
+
s = ' ' * dialog.width
|
662
701
|
else
|
663
|
-
s = Reline::Unicode.take_range(visual_lines[start + i],
|
702
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, dialog.width)
|
703
|
+
s = padding_space_with_escape_sequences(s, dialog.width)
|
664
704
|
end
|
665
|
-
@output.write "\e[39m\e[49m
|
705
|
+
@output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
|
666
706
|
move_cursor_down(1) if i < (line_num - 1)
|
667
707
|
end
|
668
|
-
move_cursor_up(
|
708
|
+
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
669
709
|
end
|
670
|
-
if (old_y +
|
710
|
+
if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
|
671
711
|
# rerender bottom
|
672
712
|
move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff)
|
673
713
|
start = visual_start + dialog.vertical_offset + dialog.contents.size
|
674
|
-
line_num = (
|
714
|
+
line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size)
|
675
715
|
line_num.times do |i|
|
676
|
-
Reline::IOGate.move_cursor_column(
|
716
|
+
Reline::IOGate.move_cursor_column(old_dialog.column)
|
677
717
|
if visual_lines[start + i].nil?
|
678
|
-
s = ' ' *
|
718
|
+
s = ' ' * dialog.width
|
679
719
|
else
|
680
|
-
s = Reline::Unicode.take_range(visual_lines[start + i],
|
720
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, dialog.width)
|
721
|
+
s = padding_space_with_escape_sequences(s, dialog.width)
|
681
722
|
end
|
682
|
-
@output.write "\e[39m\e[49m
|
723
|
+
@output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
|
683
724
|
move_cursor_down(1) if i < (line_num - 1)
|
684
725
|
end
|
685
726
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
|
686
727
|
end
|
687
|
-
if
|
728
|
+
if old_dialog.column < dialog.column
|
688
729
|
# rerender left
|
689
|
-
move_cursor_down(
|
690
|
-
width = dialog.column -
|
691
|
-
start = visual_start +
|
692
|
-
line_num =
|
730
|
+
move_cursor_down(old_dialog.vertical_offset - y_diff)
|
731
|
+
width = dialog.column - old_dialog.column
|
732
|
+
start = visual_start + old_dialog.vertical_offset
|
733
|
+
line_num = old_dialog.contents.size
|
693
734
|
line_num.times do |i|
|
694
|
-
Reline::IOGate.move_cursor_column(
|
735
|
+
Reline::IOGate.move_cursor_column(old_dialog.column)
|
695
736
|
if visual_lines[start + i].nil?
|
696
737
|
s = ' ' * width
|
697
738
|
else
|
698
|
-
s = Reline::Unicode.take_range(visual_lines[start + i],
|
739
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
|
740
|
+
s = padding_space_with_escape_sequences(s, dialog.width)
|
699
741
|
end
|
700
|
-
@output.write "\e[39m\e[49m
|
742
|
+
@output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
|
701
743
|
move_cursor_down(1) if i < (line_num - 1)
|
702
744
|
end
|
703
|
-
move_cursor_up(
|
745
|
+
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
704
746
|
end
|
705
|
-
if (
|
747
|
+
if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
|
706
748
|
# rerender right
|
707
|
-
move_cursor_down(
|
708
|
-
width = (
|
709
|
-
start = visual_start +
|
710
|
-
line_num =
|
749
|
+
move_cursor_down(old_dialog.vertical_offset + y_diff)
|
750
|
+
width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)
|
751
|
+
start = visual_start + old_dialog.vertical_offset
|
752
|
+
line_num = old_dialog.contents.size
|
711
753
|
line_num.times do |i|
|
712
|
-
Reline::IOGate.move_cursor_column(
|
754
|
+
Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width)
|
713
755
|
if visual_lines[start + i].nil?
|
714
756
|
s = ' ' * width
|
715
757
|
else
|
716
|
-
s = Reline::Unicode.take_range(visual_lines[start + i],
|
758
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
|
759
|
+
s = padding_space_with_escape_sequences(s, dialog.width)
|
717
760
|
end
|
718
|
-
Reline::IOGate.move_cursor_column(dialog.column +
|
719
|
-
@output.write "\e[39m\e[49m
|
761
|
+
Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
|
762
|
+
@output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
|
720
763
|
move_cursor_down(1) if i < (line_num - 1)
|
721
764
|
end
|
722
|
-
move_cursor_up(
|
765
|
+
move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
|
723
766
|
end
|
724
767
|
Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
|
725
768
|
end
|
@@ -752,13 +795,14 @@ class Reline::LineEditor
|
|
752
795
|
dialog_vertical_size = dialog.contents.size
|
753
796
|
dialog_vertical_size.times do |i|
|
754
797
|
if i < visual_lines_under_dialog.size
|
755
|
-
Reline::IOGate.move_cursor_column(
|
756
|
-
|
798
|
+
Reline::IOGate.move_cursor_column(dialog.column)
|
799
|
+
str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
|
800
|
+
str = padding_space_with_escape_sequences(str, dialog.width)
|
801
|
+
@output.write "\e[39m\e[49m#{str}\e[39m\e[49m"
|
757
802
|
else
|
758
803
|
Reline::IOGate.move_cursor_column(dialog.column)
|
759
|
-
@output.write "\e[39m\e[49m#{' ' *
|
804
|
+
@output.write "\e[39m\e[49m#{' ' * dialog.width}\e[39m\e[49m"
|
760
805
|
end
|
761
|
-
Reline::IOGate.erase_after_cursor
|
762
806
|
move_cursor_down(1) if i < (dialog_vertical_size - 1)
|
763
807
|
end
|
764
808
|
move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset)
|
@@ -1252,8 +1296,10 @@ class Reline::LineEditor
|
|
1252
1296
|
end
|
1253
1297
|
end
|
1254
1298
|
completed = @completion_journey_data.list[@completion_journey_data.pointer]
|
1255
|
-
|
1256
|
-
|
1299
|
+
new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index]
|
1300
|
+
@line = new_line.nil? ? String.new(encoding: @encoding) : new_line
|
1301
|
+
line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last
|
1302
|
+
line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil?
|
1257
1303
|
@cursor_max = calculate_width(@line)
|
1258
1304
|
@cursor = calculate_width(line_to_pointer)
|
1259
1305
|
@byte_pointer = line_to_pointer.bytesize
|
data/lib/reline/unicode.rb
CHANGED
@@ -186,9 +186,9 @@ class Reline::Unicode
|
|
186
186
|
end
|
187
187
|
|
188
188
|
# Take a chunk of a String with escape sequences.
|
189
|
-
def self.take_range(str,
|
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
|
192
192
|
rest = str.encode(Encoding::UTF_8)
|
193
193
|
in_zero_width = false
|
194
194
|
rest.scan(WIDTH_SCANNER) do |gc|
|
@@ -206,9 +206,10 @@ class Reline::Unicode
|
|
206
206
|
if in_zero_width
|
207
207
|
chunk << gc
|
208
208
|
else
|
209
|
-
|
210
|
-
|
211
|
-
|
209
|
+
mbchar_width = get_mbchar_width(gc)
|
210
|
+
total_width += mbchar_width
|
211
|
+
break if (start_col + max_width) < total_width
|
212
|
+
chunk << gc if start_col < total_width
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
data/lib/reline/version.rb
CHANGED
data/lib/reline.rb
CHANGED
@@ -18,6 +18,7 @@ module Reline
|
|
18
18
|
|
19
19
|
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
20
20
|
CursorPos = Struct.new(:x, :y)
|
21
|
+
DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, keyword_init: true)
|
21
22
|
|
22
23
|
class Core
|
23
24
|
ATTR_READER_NAMES = %i(
|
@@ -193,7 +194,7 @@ module Reline
|
|
193
194
|
# Auto complete starts only when edited
|
194
195
|
return nil
|
195
196
|
end
|
196
|
-
pre, target, post= retrieve_completion_block(true)
|
197
|
+
pre, target, post = retrieve_completion_block(true)
|
197
198
|
if target.nil? or target.empty?# or target.size <= 3
|
198
199
|
return nil
|
199
200
|
end
|
@@ -219,9 +220,9 @@ module Reline
|
|
219
220
|
cursor_pos_to_render = Reline::CursorPos.new(x, y)
|
220
221
|
if context and context.is_a?(Array)
|
221
222
|
context.clear
|
222
|
-
context.push(cursor_pos_to_render, result, pointer)
|
223
|
+
context.push(cursor_pos_to_render, result, pointer, dialog)
|
223
224
|
end
|
224
|
-
|
225
|
+
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, height: 15)
|
225
226
|
}
|
226
227
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
227
228
|
|
@@ -483,6 +484,7 @@ module Reline
|
|
483
484
|
def_single_delegators :core, :last_incremental_search
|
484
485
|
def_single_delegators :core, :last_incremental_search=
|
485
486
|
def_single_delegators :core, :add_dialog_proc
|
487
|
+
def_single_delegators :core, :autocompletion, :autocompletion=
|
486
488
|
|
487
489
|
def_single_delegators :core, :readmultiline
|
488
490
|
def_instance_delegators self, :readmultiline
|
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.6
|
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-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|