Skip to content

Commit

Permalink
Fix 2 menu completion issues that happen when we need to scroll scree…
Browse files Browse the repository at this point in the history
…n buffer (#2949)
  • Loading branch information
daxian-dbw authored Nov 4, 2021
1 parent 203d55c commit 81bf866
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 31 deletions.
24 changes: 7 additions & 17 deletions PSReadLine/Completion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,15 +445,8 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
SaveCursor();
}

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

var bufferWidth = console.BufferWidth;
var columnWidth = this.ColumnWidth;
Expand Down Expand Up @@ -514,7 +507,7 @@ public void DrawMenu(Menu previousMenu, bool menuSelect)
}

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

Singleton.WriteBlankLines(PreviousTop - bufferEndPoint.Y);
Singleton.WriteBlankLines(PreviousTop - Top);
}

PreviousTop = bufferEndPoint.Y;

if (menuSelect)
{
RestoreCursor();
Expand Down Expand Up @@ -797,7 +788,7 @@ private void PossibleCompletionsImpl(CommandCompletion completions, bool menuSel
}
else
{
menu.DrawMenu(null, menuSelect:false);
menu.DrawMenu(null, menuSelect: false);
InvokePrompt(key: null, arg: _console.CursorTop);
}
}
Expand Down Expand Up @@ -879,7 +870,6 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)

if (topAdjustment != 0)
{
menu.Top += topAdjustment;
menu.DrawMenu(null, menuSelect: true);
}
if (topAdjustment > 0)
Expand Down Expand Up @@ -963,7 +953,7 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
{
var newMenu = menuStack.Pop();

newMenu.DrawMenu(menu, menuSelect:true);
newMenu.DrawMenu(menu, menuSelect: true);
previousSelection = -1;

menu = newMenu;
Expand Down Expand Up @@ -1025,7 +1015,7 @@ private void MenuCompleteImpl(Menu menu, CommandCompletion completions)
{
var newMenu = CreateCompletionMenu(newMatches);

newMenu.DrawMenu(menu, menuSelect:true);
newMenu.DrawMenu(menu, menuSelect: true);
previousSelection = -1;

// Remember the current menu for when we see Backspace.
Expand Down
38 changes: 38 additions & 0 deletions PSReadLine/DisplayBlockBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ protected void MoveCursorDown(int cnt)
}
}

protected void AdjustForActualScroll(int scrollCnt)
{
if (scrollCnt > 0)
{
Top -= scrollCnt;
_singleton._initialY -= scrollCnt;
_savedCursorTop -= scrollCnt;
}
}

protected void AdjustForPossibleScroll(int cnt)
{
IConsole console = Singleton._console;
Expand All @@ -35,6 +45,34 @@ protected void AdjustForPossibleScroll(int cnt)
}
}

protected void MoveCursorToStartDrawingPosition(IConsole console)
{
// Calculate the coord to place the cursor at the end of current input.
Point bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length);
// Top must be initialized before any possible adjustion by 'AdjustForPossibleScroll' or 'AdjustForActualScroll',
// otherwise its value would be corrupted and cause rendering issue.
Top = bufferEndPoint.Y + 1;

if (bufferEndPoint.Y == console.BufferHeight)
{
// The input happens to end at the very last cell of the current buffer, so 'bufferEndPoint' is pointing to
// the first cell at one line below the current buffer, and thus we need to scroll up the buffer.
console.SetCursorPosition(console.BufferWidth - 1, console.BufferHeight - 1);
// We scroll the buffer by 2 lines here, so the cursor is placed at the start of the first line after 'bufferEndPoint'.
MoveCursorDown(2);
bufferEndPoint.Y -= 2;
AdjustForActualScroll(2);
}
else
{
// Move the cursor to the end of our input.
console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y);
// Move cursor to the start of the first line after our input (after 'bufferEndPoint').
AdjustForPossibleScroll(1);
MoveCursorDown(1);
}
}

private int _savedCursorLeft;
private int _savedCursorTop;

Expand Down
18 changes: 4 additions & 14 deletions PSReadLine/DynamicHelp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,21 +241,11 @@ public void DrawMultilineBlock()

multilineItems = 0;

this.SaveCursor();

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

var bufferWidth = console.BufferWidth;

var items = this.ItemsToDisplay;
var items = ItemsToDisplay;

for (var index = 0; index < items.Count; index++)
{
Expand All @@ -282,7 +272,7 @@ public void DrawMultilineBlock()
}
}

this.RestoreCursor();
RestoreCursor();
}

public void Clear()
Expand Down

0 comments on commit 81bf866

Please sign in to comment.