@@ -249,10 +249,7 @@ def reset_variables(prompt = '', encoding:)
249
249
@drop_terminate_spaces = false
250
250
@in_pasting = false
251
251
@auto_indent_proc = nil
252
- @dialog_column = nil
253
- @dialog_vertical_offset = nil
254
- @dialog_contents = nil
255
- @dialog_lines_backup = nil
252
+ @dialogs = [ ]
256
253
reset_line
257
254
end
258
255
@@ -521,75 +518,98 @@ def call
521
518
end
522
519
end
523
520
524
- def dialog_proc = ( p )
525
- @dialog_proc_scope = DialogProcScope . new ( self , p )
526
- @dialog_proc = p
521
+ class Dialog
522
+ attr_reader :name
523
+ attr_accessor :column , :vertical_offset , :contents , :lines_backup
524
+
525
+ def initialize ( name , proc_scope )
526
+ @name = name
527
+ @proc_scope = proc_scope
528
+ end
529
+
530
+ def set_cursor_pos ( col , row )
531
+ @proc_scope . set_cursor_pos ( col , row )
532
+ end
533
+
534
+ def call
535
+ @proc_scope . call
536
+ end
527
537
end
528
538
529
- DIALOG_HEIGHT = 5
539
+ def add_dialog_proc ( name , p )
540
+ return if @dialogs . any? { |d | d . name == name }
541
+ @dialogs << Dialog . new ( name , DialogProcScope . new ( self , p ) )
542
+ end
543
+
544
+ DIALOG_HEIGHT = 20
530
545
DIALOG_WIDTH = 40
531
546
private def render_dialog ( cursor_column )
532
- return if @dialog_proc_scope . nil?
547
+ @dialogs . each do |dialog |
548
+ render_each_dialog ( dialog , cursor_column )
549
+ end
550
+ end
551
+
552
+ private def render_each_dialog ( dialog , cursor_column )
533
553
if @in_pasting
534
- @dialog_contents = nil
554
+ dialog . contents = nil
535
555
return
536
556
end
537
- @dialog_proc_scope . set_cursor_pos ( cursor_column , @first_line_started_from + @started_from )
538
- pos , result , pointer = @dialog_proc_scope . call
539
- old_dialog_contents = @dialog_contents
540
- old_dialog_column = @dialog_column
541
- old_dialog_vertical_offset = @dialog_vertical_offset
557
+ dialog . set_cursor_pos ( cursor_column , @first_line_started_from + @started_from )
558
+ pos , result , pointer = dialog . call
559
+ old_dialog_contents = dialog . contents
560
+ old_dialog_column = dialog . column
561
+ old_dialog_vertical_offset = dialog . vertical_offset
542
562
if result and not result . empty?
543
- @dialog_contents = result
544
- @dialog_contents = @dialog_contents [ 0 ...DIALOG_HEIGHT ] if @dialog_contents . size > DIALOG_HEIGHT
563
+ dialog . contents = result
564
+ dialog . contents = dialog . contents [ 0 ...DIALOG_HEIGHT ] if dialog . contents . size > DIALOG_HEIGHT
545
565
else
546
- @dialog_lines_backup = {
566
+ dialog . lines_backup = {
547
567
lines : modify_lines ( whole_lines ) ,
548
568
line_index : @line_index ,
549
569
first_line_started_from : @first_line_started_from ,
550
570
started_from : @started_from ,
551
571
byte_pointer : @byte_pointer
552
572
}
553
- clear_dialog
554
- @dialog_contents = nil
573
+ clear_each_dialog ( dialog )
574
+ dialog . contents = nil
555
575
return
556
576
end
557
577
upper_space = @first_line_started_from - @started_from
558
578
lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
559
- @dialog_column = pos . x
560
- diff = ( @dialog_column + DIALOG_WIDTH ) - ( @screen_size . last - 1 )
579
+ dialog . column = pos . x
580
+ diff = ( dialog . column + DIALOG_WIDTH ) - ( @screen_size . last - 1 )
561
581
if diff > 0
562
- @dialog_column -= diff
582
+ dialog . column -= diff
563
583
end
564
584
if ( lower_space + @rest_height ) >= DIALOG_HEIGHT
565
- @dialog_vertical_offset = pos . y + 1
585
+ dialog . vertical_offset = pos . y + 1
566
586
elsif upper_space >= DIALOG_HEIGHT
567
- @dialog_vertical_offset = pos . y + -( DIALOG_HEIGHT + 1 )
587
+ dialog . vertical_offset = pos . y + -( DIALOG_HEIGHT + 1 )
568
588
else
569
589
if ( lower_space + @rest_height ) < DIALOG_HEIGHT
570
590
scroll_down ( DIALOG_HEIGHT )
571
591
move_cursor_up ( DIALOG_HEIGHT )
572
592
end
573
- @dialog_vertical_offset = pos . y + 1
593
+ dialog . vertical_offset = pos . y + 1
574
594
end
575
595
Reline ::IOGate . hide_cursor
576
- reset_dialog ( old_dialog_contents , old_dialog_column , old_dialog_vertical_offset )
577
- move_cursor_down ( @dialog_vertical_offset )
578
- Reline ::IOGate . move_cursor_column ( @dialog_column )
579
- @dialog_contents . each_with_index do |item , i |
596
+ reset_dialog ( dialog , old_dialog_contents , old_dialog_column , old_dialog_vertical_offset )
597
+ move_cursor_down ( dialog . vertical_offset )
598
+ Reline ::IOGate . move_cursor_column ( dialog . column )
599
+ dialog . contents . each_with_index do |item , i |
580
600
if i == pointer
581
601
bg_color = '45'
582
602
else
583
603
bg_color = '46'
584
604
end
585
605
@output . write "\e [#{ bg_color } m%-#{ DIALOG_WIDTH } s\e [49m" % item . slice ( 0 , DIALOG_WIDTH )
586
- Reline ::IOGate . move_cursor_column ( @dialog_column )
587
- move_cursor_down ( 1 ) if i < ( @dialog_contents . size - 1 )
606
+ Reline ::IOGate . move_cursor_column ( dialog . column )
607
+ move_cursor_down ( 1 ) if i < ( dialog . contents . size - 1 )
588
608
end
589
609
Reline ::IOGate . move_cursor_column ( cursor_column )
590
- move_cursor_up ( @dialog_vertical_offset + @dialog_contents . size - 1 )
610
+ move_cursor_up ( dialog . vertical_offset + dialog . contents . size - 1 )
591
611
Reline ::IOGate . show_cursor
592
- @dialog_lines_backup = {
612
+ dialog . lines_backup = {
593
613
lines : modify_lines ( whole_lines ) ,
594
614
line_index : @line_index ,
595
615
first_line_started_from : @first_line_started_from ,
@@ -598,53 +618,61 @@ def dialog_proc=(p)
598
618
}
599
619
end
600
620
601
- private def reset_dialog ( old_dialog_contents , old_dialog_column , old_dialog_vertical_offset )
602
- return if @dialog_lines_backup . nil? or old_dialog_contents . nil?
603
- prompt , prompt_width , prompt_list = check_multiline_prompt ( @dialog_lines_backup [ :lines ] , prompt )
621
+ private def reset_dialog ( dialog , old_dialog_contents , old_dialog_column , old_dialog_vertical_offset )
622
+ return if dialog . lines_backup . nil? or old_dialog_contents . nil?
623
+ prompt , prompt_width , prompt_list = check_multiline_prompt ( dialog . lines_backup [ :lines ] , prompt )
604
624
visual_lines = [ ]
605
625
visual_start = nil
606
- @dialog_lines_backup [ :lines ] . each_with_index { |l , i |
626
+ dialog . lines_backup [ :lines ] . each_with_index { |l , i |
607
627
pr = prompt_list ? prompt_list [ i ] : prompt
608
628
vl , _ = split_by_width ( pr + l , @screen_size . last )
609
629
vl . compact!
610
- if i == @dialog_lines_backup [ :line_index ]
611
- visual_start = visual_lines . size + @dialog_lines_backup [ :started_from ]
630
+ if i == dialog . lines_backup [ :line_index ]
631
+ visual_start = visual_lines . size + dialog . lines_backup [ :started_from ]
612
632
end
613
633
visual_lines . concat ( vl )
614
634
}
615
- old_y = @dialog_lines_backup [ :first_line_started_from ] + @dialog_lines_backup [ :started_from ]
635
+ old_y = dialog . lines_backup [ :first_line_started_from ] + dialog . lines_backup [ :started_from ]
616
636
y = @first_line_started_from + @started_from
617
637
y_diff = y - old_y
618
- if ( old_y + old_dialog_vertical_offset ) < ( y + @dialog_vertical_offset )
638
+ if ( old_y + old_dialog_vertical_offset ) < ( y + dialog . vertical_offset )
619
639
# rerender top
620
640
move_cursor_down ( old_dialog_vertical_offset - y_diff )
621
641
start = visual_start + old_dialog_vertical_offset
622
- line_num = @dialog_vertical_offset - old_dialog_vertical_offset
642
+ line_num = dialog . vertical_offset - old_dialog_vertical_offset
623
643
line_num . times do |i |
624
- Reline ::IOGate . move_cursor_column ( 0 )
625
- @output . write "\e [39m\e [49m#{ visual_lines [ start + i ] } \e [39m\e [49m"
626
- Reline ::IOGate . erase_after_cursor
644
+ Reline ::IOGate . move_cursor_column ( old_dialog_column )
645
+ if visual_lines [ start + i ] . nil?
646
+ s = ' ' * DIALOG_WIDTH
647
+ else
648
+ s = Reline ::Unicode . take_range ( visual_lines [ start + i ] , old_dialog_column , DIALOG_WIDTH )
649
+ end
650
+ @output . write "\e [39m\e [49m%-#{ DIALOG_WIDTH } s\e [39m\e [49m" % s
627
651
move_cursor_down ( 1 ) if i < ( line_num - 1 )
628
652
end
629
653
move_cursor_up ( old_dialog_vertical_offset + line_num - 1 - y_diff )
630
654
end
631
- if ( old_y + old_dialog_vertical_offset + old_dialog_contents . size ) > ( y + @dialog_vertical_offset + @dialog_contents . size )
655
+ if ( old_y + old_dialog_vertical_offset + old_dialog_contents . size ) > ( y + dialog . vertical_offset + dialog . contents . size )
632
656
# rerender bottom
633
- move_cursor_down ( @dialog_vertical_offset + @dialog_contents . size - y_diff )
634
- start = visual_start + @dialog_vertical_offset + @dialog_contents . size
635
- line_num = ( old_dialog_vertical_offset + old_dialog_contents . size ) - ( @dialog_vertical_offset + @dialog_contents . size )
657
+ move_cursor_down ( dialog . vertical_offset + dialog . contents . size - y_diff )
658
+ start = visual_start + dialog . vertical_offset + dialog . contents . size
659
+ line_num = ( old_dialog_vertical_offset + old_dialog_contents . size ) - ( dialog . vertical_offset + dialog . contents . size )
636
660
line_num . times do |i |
637
- Reline ::IOGate . move_cursor_column ( 0 )
638
- @output . write "\e [39m\e [49m#{ visual_lines [ start + i ] } \e [39m\e [49m"
639
- Reline ::IOGate . erase_after_cursor
661
+ Reline ::IOGate . move_cursor_column ( old_dialog_column )
662
+ if visual_lines [ start + i ] . nil?
663
+ s = ' ' * DIALOG_WIDTH
664
+ else
665
+ s = Reline ::Unicode . take_range ( visual_lines [ start + i ] , old_dialog_column , DIALOG_WIDTH )
666
+ end
667
+ @output . write "\e [39m\e [49m%-#{ DIALOG_WIDTH } s\e [39m\e [49m" % s
640
668
move_cursor_down ( 1 ) if i < ( line_num - 1 )
641
669
end
642
- move_cursor_up ( @dialog_vertical_offset + @dialog_contents . size + line_num - 1 - y_diff )
670
+ move_cursor_up ( dialog . vertical_offset + dialog . contents . size + line_num - 1 - y_diff )
643
671
end
644
- if old_dialog_column < @dialog_column
672
+ if old_dialog_column < dialog . column
645
673
# rerender left
646
674
move_cursor_down ( old_dialog_vertical_offset - y_diff )
647
- width = @dialog_column - old_dialog_column
675
+ width = dialog . column - old_dialog_column
648
676
start = visual_start + old_dialog_vertical_offset
649
677
line_num = old_dialog_contents . size
650
678
line_num . times do |i |
@@ -659,10 +687,10 @@ def dialog_proc=(p)
659
687
end
660
688
move_cursor_up ( old_dialog_vertical_offset + line_num - 1 - y_diff )
661
689
end
662
- if ( old_dialog_column + DIALOG_WIDTH ) > ( @dialog_column + DIALOG_WIDTH )
690
+ if ( old_dialog_column + DIALOG_WIDTH ) > ( dialog . column + DIALOG_WIDTH )
663
691
# rerender right
664
692
move_cursor_down ( old_dialog_vertical_offset + y_diff )
665
- width = ( old_dialog_column + DIALOG_WIDTH ) - ( @dialog_column + DIALOG_WIDTH )
693
+ width = ( old_dialog_column + DIALOG_WIDTH ) - ( dialog . column + DIALOG_WIDTH )
666
694
start = visual_start + old_dialog_vertical_offset
667
695
line_num = old_dialog_contents . size
668
696
line_num . times do |i |
@@ -672,7 +700,7 @@ def dialog_proc=(p)
672
700
else
673
701
s = Reline ::Unicode . take_range ( visual_lines [ start + i ] , old_dialog_column + DIALOG_WIDTH , width )
674
702
end
675
- Reline ::IOGate . move_cursor_column ( @dialog_column + DIALOG_WIDTH )
703
+ Reline ::IOGate . move_cursor_column ( dialog . column + DIALOG_WIDTH )
676
704
@output . write "\e [39m\e [49m%-#{ width } s\e [39m\e [49m" % s
677
705
move_cursor_down ( 1 ) if i < ( line_num - 1 )
678
706
end
@@ -682,36 +710,42 @@ def dialog_proc=(p)
682
710
end
683
711
684
712
private def clear_dialog
685
- return unless @dialog_contents
686
- prompt , prompt_width , prompt_list = check_multiline_prompt ( @dialog_lines_backup [ :lines ] , prompt )
713
+ @dialogs . each do |dialog |
714
+ clear_each_dialog ( dialog )
715
+ end
716
+ end
717
+
718
+ private def clear_each_dialog ( dialog )
719
+ return unless dialog . contents
720
+ prompt , prompt_width , prompt_list = check_multiline_prompt ( dialog . lines_backup [ :lines ] , prompt )
687
721
visual_lines = [ ]
688
722
visual_lines_under_dialog = [ ]
689
723
visual_start = nil
690
- @dialog_lines_backup [ :lines ] . each_with_index { |l , i |
724
+ dialog . lines_backup [ :lines ] . each_with_index { |l , i |
691
725
pr = prompt_list ? prompt_list [ i ] : prompt
692
726
vl , _ = split_by_width ( pr + l , @screen_size . last )
693
727
vl . compact!
694
- if i == @dialog_lines_backup [ :line_index ]
695
- visual_start = visual_lines . size + @dialog_lines_backup [ :started_from ] + @dialog_vertical_offset
728
+ if i == dialog . lines_backup [ :line_index ]
729
+ visual_start = visual_lines . size + dialog . lines_backup [ :started_from ] + dialog . vertical_offset
696
730
end
697
731
visual_lines . concat ( vl )
698
732
}
699
- visual_lines_under_dialog = visual_lines [ visual_start , @dialog_contents . size ]
733
+ visual_lines_under_dialog = visual_lines [ visual_start , dialog . contents . size ]
700
734
Reline ::IOGate . hide_cursor
701
- move_cursor_down ( @dialog_vertical_offset )
702
- dialog_vertical_size = @dialog_contents . size
735
+ move_cursor_down ( dialog . vertical_offset )
736
+ dialog_vertical_size = dialog . contents . size
703
737
dialog_vertical_size . times do |i |
704
738
if i < visual_lines_under_dialog . size
705
739
Reline ::IOGate . move_cursor_column ( 0 )
706
740
@output . write "\e [39m\e [49m%-#{ DIALOG_WIDTH } s\e [39m\e [49m" % visual_lines_under_dialog [ i ]
707
741
else
708
- Reline ::IOGate . move_cursor_column ( @dialog_column )
742
+ Reline ::IOGate . move_cursor_column ( dialog . column )
709
743
@output . write "\e [39m\e [49m#{ ' ' * DIALOG_WIDTH } \e [39m\e [49m"
710
744
end
711
745
Reline ::IOGate . erase_after_cursor
712
746
move_cursor_down ( 1 ) if i < ( dialog_vertical_size - 1 )
713
747
end
714
- move_cursor_up ( dialog_vertical_size - 1 + @dialog_vertical_offset )
748
+ move_cursor_up ( dialog_vertical_size - 1 + dialog . vertical_offset )
715
749
Reline ::IOGate . move_cursor_column ( ( prompt_width + @cursor ) % @screen_size . last )
716
750
Reline ::IOGate . show_cursor
717
751
end
0 commit comments