@@ -113,14 +113,6 @@ private static string GetUnquotedText(CompletionResult match, bool consistentQuo
113
113
return GetUnquotedText ( s , consistentQuoting ) ;
114
114
}
115
115
116
- private void WriteBlankLines ( int top , int count )
117
- {
118
- _console . SaveCursor ( ) ;
119
- _console . SetCursorPosition ( 0 , top ) ;
120
- WriteBlankLines ( count ) ;
121
- _console . RestoreCursor ( ) ;
122
- }
123
-
124
116
private void WriteBlankLines ( int count )
125
117
{
126
118
var spaces = Spaces ( _console . BufferWidth ) ;
@@ -464,48 +456,20 @@ private class Menu
464
456
internal CompletionResult CurrentMenuItem => MenuItems [ CurrentSelection ] ;
465
457
internal int CurrentSelection ;
466
458
467
- void EnsureMenuAndInputIsVisible ( IConsole console , int tooltipLineCount )
468
- {
469
- // The +1 lets us write a newline after the last row, which isn't strictly necessary
470
- // It does help with:
471
- // * Console selecting multiple lines of text
472
- // * Adds a little extra space underneath the menu
473
- var bottom = this . Top + this . Rows + tooltipLineCount + 1 ;
474
- if ( bottom > console . BufferHeight )
475
- {
476
- var toScroll = bottom - console . BufferHeight ;
477
- console . ScrollBuffer ( toScroll ) ;
478
- Singleton . _initialY -= toScroll ;
479
- this . Top -= toScroll ;
480
-
481
- var point = Singleton . ConvertOffsetToPoint ( Singleton . _current ) ;
482
- Singleton . PlaceCursor ( point . X , point . Y ) ;
483
- }
484
- }
485
-
486
459
public void DrawMenu ( Menu previousMenu , bool menuSelect )
487
460
{
488
461
IConsole console = Singleton . _console ;
489
462
490
463
// Move cursor to the start of the first line after our input.
491
- this . Top = Singleton . ConvertOffsetToPoint ( Singleton . _buffer . Length ) . Y + 1 ;
464
+ var bufferEndPoint = Singleton . ConvertOffsetToPoint ( Singleton . _buffer . Length ) ;
465
+ console . SetCursorPosition ( bufferEndPoint . X , bufferEndPoint . Y ) ;
466
+ AdjustForPossibleScroll ( 1 ) ;
467
+ MoveCursorDown ( 1 ) ;
468
+ this . Top = bufferEndPoint . Y + 1 ;
492
469
if ( menuSelect )
493
470
{
494
- EnsureMenuAndInputIsVisible ( console , tooltipLineCount : 0 ) ;
495
-
496
471
console . CursorVisible = false ;
497
- console . SaveCursor ( ) ;
498
- console . SetCursorPosition ( 0 , this . Top ) ;
499
- }
500
- else
501
- {
502
- // Start a new line to show the menu contents
503
- console . SetCursorPosition ( 0 , this . Top ) ;
504
- // Scroll one line up if the cursor is at the bottom of the window
505
- if ( this . Top == console . BufferHeight )
506
- {
507
- console . Write ( "\n " ) ;
508
- }
472
+ SaveCursor ( ) ;
509
473
}
510
474
511
475
var bufferWidth = console . BufferWidth ;
@@ -533,8 +497,12 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
533
497
console . BlankRestOfLine ( ) ;
534
498
}
535
499
536
- // Explicit newline so consoles see each row as distinct lines.
537
- console . Write ( "\n " ) ;
500
+ // Explicit newline so consoles see each row as distinct lines, but skip the
501
+ // last line so we don't scroll.
502
+ if ( row != ( this . Rows - 1 ) || ! menuSelect ) {
503
+ AdjustForPossibleScroll ( 1 ) ;
504
+ MoveCursorDown ( 1 ) ;
505
+ }
538
506
}
539
507
540
508
if ( previousMenu != null )
@@ -547,14 +515,14 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
547
515
548
516
if ( menuSelect )
549
517
{
550
- console . RestoreCursor ( ) ;
518
+ RestoreCursor ( ) ;
551
519
console . CursorVisible = true ;
552
520
}
553
521
}
554
522
555
523
public void Clear ( )
556
524
{
557
- Singleton . WriteBlankLines ( Top , Rows + ToolTipLines ) ;
525
+ WriteBlankLines ( Top , Rows + ToolTipLines ) ;
558
526
}
559
527
560
528
public void UpdateMenuSelection ( int selectedItem , bool select , bool showTooltips , string toolTipColor )
@@ -614,12 +582,7 @@ public void UpdateMenuSelection(int selectedItem, bool select, bool showTooltips
614
582
}
615
583
}
616
584
617
- if ( showTooltips )
618
- {
619
- EnsureMenuAndInputIsVisible ( console , toolTipLines ) ;
620
- }
621
-
622
- console . SaveCursor ( ) ;
585
+ SaveCursor ( ) ;
623
586
624
587
var row = Top + selectedItem % Rows ;
625
588
var col = ColumnWidth * ( selectedItem / Rows ) ;
@@ -634,15 +597,18 @@ public void UpdateMenuSelection(int selectedItem, bool select, bool showTooltips
634
597
if ( showTooltips )
635
598
{
636
599
Debug . Assert ( select , "On unselect, caller must clear the tooltip" ) ;
637
- console . SetCursorPosition ( 0 , Top + Rows + 1 ) ;
600
+ console . SetCursorPosition ( 0 , Top + Rows - 1 ) ;
601
+ // Move down 2 so we have 1 blank line between the menu and buffer.
602
+ AdjustForPossibleScroll ( toolTipLines ) ;
603
+ MoveCursorDown ( 2 ) ;
638
604
console . Write ( toolTipColor ) ;
639
605
console . Write ( toolTip ) ;
640
606
ToolTipLines = toolTipLines ;
641
607
642
608
console . Write ( "\x1b [0m" ) ;
643
609
}
644
610
645
- console . RestoreCursor ( ) ;
611
+ RestoreCursor ( ) ;
646
612
}
647
613
648
614
public void MoveRight ( ) => CurrentSelection = Math . Min ( CurrentSelection + Rows , MenuItems . Count - 1 ) ;
@@ -661,6 +627,47 @@ public void MoveN(int n)
661
627
CurrentSelection += MenuItems . Count ;
662
628
}
663
629
}
630
+
631
+ private void MoveCursorDown ( int cnt )
632
+ {
633
+ IConsole console = Singleton . _console ;
634
+ while ( cnt -- > 0 )
635
+ {
636
+ console . Write ( "\n " ) ;
637
+ }
638
+ }
639
+
640
+ private void AdjustForPossibleScroll ( int cnt )
641
+ {
642
+ IConsole console = Singleton . _console ;
643
+ var scrollCnt = console . CursorTop + cnt + 1 - console . BufferHeight ;
644
+ if ( scrollCnt > 0 )
645
+ {
646
+ Top -= scrollCnt ;
647
+ _singleton . _initialY -= scrollCnt ;
648
+ _savedCursorTop -= scrollCnt ;
649
+ }
650
+ }
651
+
652
+ public void WriteBlankLines ( int top , int count )
653
+ {
654
+ SaveCursor ( ) ;
655
+ Singleton . _console . SetCursorPosition ( 0 , top ) ;
656
+ Singleton . WriteBlankLines ( count ) ;
657
+ RestoreCursor ( ) ;
658
+ }
659
+
660
+ private int _savedCursorLeft ;
661
+ private int _savedCursorTop ;
662
+
663
+ public void SaveCursor ( )
664
+ {
665
+ IConsole console = Singleton . _console ;
666
+ _savedCursorLeft = console . CursorLeft ;
667
+ _savedCursorTop = console . CursorTop ;
668
+ }
669
+
670
+ public void RestoreCursor ( ) => Singleton . _console . SetCursorPosition ( _savedCursorLeft , _savedCursorTop ) ;
664
671
}
665
672
666
673
private Menu CreateCompletionMenu ( Collection < CompletionResult > matches )
@@ -746,7 +753,7 @@ private void PossibleCompletionsImpl(CommandCompletion completions, bool menuSel
746
753
// if not, we'll skip the menu.
747
754
748
755
var endBufferPoint = ConvertOffsetToPoint ( _buffer . Length ) ;
749
- menu . BufferLines = endBufferPoint . Y - _initialY + 1 ;
756
+ menu . BufferLines = endBufferPoint . Y - _initialY + 1 + _options . ExtraPromptLineCount ;
750
757
if ( menu . BufferLines + menu . Rows > _console . WindowHeight )
751
758
{
752
759
menuSelect = false ;
@@ -844,18 +851,18 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
844
851
{
845
852
// Render did not clear the rest of the command line which flowed
846
853
// into the menu, so we must do that here.
847
- _console . SaveCursor ( ) ;
854
+ menu . SaveCursor ( ) ;
848
855
_console . SetCursorPosition ( endOfCommandLine . X , endOfCommandLine . Y ) ;
849
856
_console . Write ( Spaces ( _console . BufferWidth - endOfCommandLine . X ) ) ;
850
- _console . RestoreCursor ( ) ;
857
+ menu . RestoreCursor ( ) ;
851
858
}
852
859
853
860
if ( previousSelection != - 1 )
854
861
{
855
862
if ( menu . ToolTipLines > 0 )
856
863
{
857
864
// Erase previous tooltip, taking into account if the menu moved up/down.
858
- WriteBlankLines ( menu . Top + menu . Rows , - topAdjustment + menu . ToolTipLines ) ;
865
+ menu . WriteBlankLines ( menu . Top + menu . Rows , - topAdjustment + menu . ToolTipLines ) ;
859
866
}
860
867
menu . UpdateMenuSelection ( previousSelection , /*select*/ false ,
861
868
/*showToolTips*/ false , VTColorUtils . AsEscapeSequence ( Options . EmphasisColor ) ) ;
0 commit comments