Skip to content

Commit 81bf866

Browse files
authored
Fix 2 menu completion issues that happen when we need to scroll screen buffer (PowerShell#2949)
1 parent 203d55c commit 81bf866

File tree

3 files changed

+49
-31
lines changed

3 files changed

+49
-31
lines changed

PSReadLine/Completion.cs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -445,15 +445,8 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
445445
SaveCursor();
446446
}
447447

448-
// Move cursor to the start of the first line after our input.
449-
var bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length);
450-
console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y);
451-
// Top must be initialized before calling AdjustForPossibleScroll, otherwise
452-
// on the last line of the buffer, the scroll operation causes Top to point
453-
// past the buffer, which in turn causes the menu to be printed twice.
454-
this.Top = bufferEndPoint.Y + 1;
455-
AdjustForPossibleScroll(1);
456-
MoveCursorDown(1);
448+
PreviousTop = Top;
449+
MoveCursorToStartDrawingPosition(console);
457450

458451
var bufferWidth = console.BufferWidth;
459452
var columnWidth = this.ColumnWidth;
@@ -514,7 +507,7 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
514507
}
515508

516509
// if the menu has moved, we need to clear the lines under it
517-
if (bufferEndPoint.Y < PreviousTop)
510+
if (Top < PreviousTop)
518511
{
519512
// In either of the following two cases, we will need to move the cursor to the next line:
520513
// - if extra rows from previous menu were cleared, then we know the current line was erased
@@ -528,11 +521,9 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
528521
MoveCursorDown(1);
529522
}
530523

531-
Singleton.WriteBlankLines(PreviousTop - bufferEndPoint.Y);
524+
Singleton.WriteBlankLines(PreviousTop - Top);
532525
}
533526

534-
PreviousTop = bufferEndPoint.Y;
535-
536527
if (menuSelect)
537528
{
538529
RestoreCursor();
@@ -797,7 +788,7 @@ private void PossibleCompletionsImpl(CommandCompletion completions, bool menuSel
797788
}
798789
else
799790
{
800-
menu.DrawMenu(null, menuSelect:false);
791+
menu.DrawMenu(null, menuSelect: false);
801792
InvokePrompt(key: null, arg: _console.CursorTop);
802793
}
803794
}
@@ -879,7 +870,6 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
879870

880871
if (topAdjustment != 0)
881872
{
882-
menu.Top += topAdjustment;
883873
menu.DrawMenu(null, menuSelect: true);
884874
}
885875
if (topAdjustment > 0)
@@ -963,7 +953,7 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
963953
{
964954
var newMenu = menuStack.Pop();
965955

966-
newMenu.DrawMenu(menu, menuSelect:true);
956+
newMenu.DrawMenu(menu, menuSelect: true);
967957
previousSelection = -1;
968958

969959
menu = newMenu;
@@ -1025,7 +1015,7 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
10251015
{
10261016
var newMenu = CreateCompletionMenu(newMatches);
10271017

1028-
newMenu.DrawMenu(menu, menuSelect:true);
1018+
newMenu.DrawMenu(menu, menuSelect: true);
10291019
previousSelection = -1;
10301020

10311021
// Remember the current menu for when we see Backspace.

PSReadLine/DisplayBlockBase.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ protected void MoveCursorDown(int cnt)
2323
}
2424
}
2525

26+
protected void AdjustForActualScroll(int scrollCnt)
27+
{
28+
if (scrollCnt > 0)
29+
{
30+
Top -= scrollCnt;
31+
_singleton._initialY -= scrollCnt;
32+
_savedCursorTop -= scrollCnt;
33+
}
34+
}
35+
2636
protected void AdjustForPossibleScroll(int cnt)
2737
{
2838
IConsole console = Singleton._console;
@@ -35,6 +45,34 @@ protected void AdjustForPossibleScroll(int cnt)
3545
}
3646
}
3747

48+
protected void MoveCursorToStartDrawingPosition(IConsole console)
49+
{
50+
// Calculate the coord to place the cursor at the end of current input.
51+
Point bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length);
52+
// Top must be initialized before any possible adjustion by 'AdjustForPossibleScroll' or 'AdjustForActualScroll',
53+
// otherwise its value would be corrupted and cause rendering issue.
54+
Top = bufferEndPoint.Y + 1;
55+
56+
if (bufferEndPoint.Y == console.BufferHeight)
57+
{
58+
// The input happens to end at the very last cell of the current buffer, so 'bufferEndPoint' is pointing to
59+
// the first cell at one line below the current buffer, and thus we need to scroll up the buffer.
60+
console.SetCursorPosition(console.BufferWidth - 1, console.BufferHeight - 1);
61+
// We scroll the buffer by 2 lines here, so the cursor is placed at the start of the first line after 'bufferEndPoint'.
62+
MoveCursorDown(2);
63+
bufferEndPoint.Y -= 2;
64+
AdjustForActualScroll(2);
65+
}
66+
else
67+
{
68+
// Move the cursor to the end of our input.
69+
console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y);
70+
// Move cursor to the start of the first line after our input (after 'bufferEndPoint').
71+
AdjustForPossibleScroll(1);
72+
MoveCursorDown(1);
73+
}
74+
}
75+
3876
private int _savedCursorLeft;
3977
private int _savedCursorTop;
4078

PSReadLine/DynamicHelp.cs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -241,21 +241,11 @@ public void DrawMultilineBlock()
241241

242242
multilineItems = 0;
243243

244-
this.SaveCursor();
245-
246-
// Move cursor to the start of the first line after our input.
247-
var bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length);
248-
console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y);
249-
// Top must be initialized before calling AdjustForPossibleScroll, otherwise
250-
// on the last line of the buffer, the scroll operation causes Top to point
251-
// past the buffer, which in turn causes the menu to be printed twice.
252-
this.Top = bufferEndPoint.Y + 1;
253-
AdjustForPossibleScroll(1);
254-
MoveCursorDown(1);
244+
SaveCursor();
245+
MoveCursorToStartDrawingPosition(console);
255246

256247
var bufferWidth = console.BufferWidth;
257-
258-
var items = this.ItemsToDisplay;
248+
var items = ItemsToDisplay;
259249

260250
for (var index = 0; index < items.Count; index++)
261251
{
@@ -282,7 +272,7 @@ public void DrawMultilineBlock()
282272
}
283273
}
284274

285-
this.RestoreCursor();
275+
RestoreCursor();
286276
}
287277

288278
public void Clear()

0 commit comments

Comments
 (0)