Skip to content

Commit 372212e

Browse files
authored
Improve the list view to be scrollable and auto-adjust the list view height (#3583)
1 parent 513aaff commit 372212e

14 files changed

+1992
-170
lines changed

PSReadLine/KeyBindings.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ public static void ShowKeyBindings(ConsoleKeyInfo? key = null, object arg = null
664664
}
665665

666666
// Don't overwrite any of the line - so move to first line after the end of our buffer.
667-
var point = _singleton.ConvertOffsetToPoint(_singleton._buffer.Length);
667+
var point = _singleton.EndOfBufferPosition();
668668
console.SetCursorPosition(point.X, point.Y);
669669
console.Write("\n");
670670

@@ -721,7 +721,7 @@ public static void WhatIsKey(ConsoleKeyInfo? key = null, object arg = null)
721721

722722
var console = _singleton._console;
723723
// Don't overwrite any of the line - so move to first line after the end of our buffer.
724-
var point = _singleton.ConvertOffsetToPoint(_singleton._buffer.Length);
724+
var point = _singleton.EndOfBufferPosition();
725725
console.SetCursorPosition(point.X, point.Y);
726726
console.Write("\n");
727727

PSReadLine/PSReadLineResources.Designer.cs

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

PSReadLine/PSReadLineResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,9 @@ Or not saving history with:
840840
<data name="WindowSizeTooSmallForListView" xml:space="preserve">
841841
<value>The prediction 'ListView' is temporarily disabled because the current window size of the console is too small. To use the 'ListView', please make sure the 'WindowWidth' is not less than '{0}' and the 'WindowHeight' is not less than '{1}'.</value>
842842
</data>
843+
<data name="WindowSizeTooSmallWarning" xml:space="preserve">
844+
<value>! terminal size too small to show the list view</value>
845+
</data>
843846
<data name="NeedsUpdateHelp" xml:space="preserve">
844847
<value>No help content available. Please use Update-Help to download the latest help content.</value>
845848
</data>

PSReadLine/Prediction.Entry.cs

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,52 @@ namespace Microsoft.PowerShell
99
{
1010
public partial class PSConsoleReadLine
1111
{
12+
/// <summary>
13+
/// Represents a prediction source.
14+
/// </summary>
15+
private readonly struct SourceInfo
16+
{
17+
internal readonly string SourceName;
18+
internal readonly int EndIndex;
19+
internal readonly int PrevSourceEndIndex;
20+
internal readonly int ItemCount;
21+
22+
internal SourceInfo(string sourceName, int endIndex, int prevSourceEndIndex)
23+
{
24+
SourceName = sourceName;
25+
int sourceWidth = LengthInBufferCells(SourceName);
26+
if (sourceWidth > PredictionListView.SourceMaxWidth)
27+
{
28+
sourceWidth = PredictionListView.SourceMaxWidth - 1;
29+
int sourceStrLen = SubstringLengthByCells(sourceName, sourceWidth);
30+
SourceName = sourceName.Substring(0, sourceStrLen) + SuggestionEntry.Ellipsis;
31+
}
32+
33+
EndIndex = endIndex;
34+
PrevSourceEndIndex = prevSourceEndIndex;
35+
ItemCount = EndIndex - PrevSourceEndIndex;
36+
}
37+
}
38+
1239
/// <summary>
1340
/// This type represents an individual suggestion entry.
1441
/// </summary>
1542
private struct SuggestionEntry
1643
{
44+
internal const char Ellipsis = '\u2026';
45+
internal const string HistorySource = "History";
46+
1747
internal readonly Guid PredictorId;
1848
internal readonly uint? PredictorSession;
1949
internal readonly string Source;
2050
internal readonly string SuggestionText;
2151
internal readonly int InputMatchIndex;
2252

53+
private string _listItemTextRegular;
54+
private string _listItemTextSelected;
55+
2356
internal SuggestionEntry(string suggestion, int matchIndex)
24-
: this(source: "History", predictorId: Guid.Empty, predictorSession: null, suggestion, matchIndex)
57+
: this(source: HistorySource, predictorId: Guid.Empty, predictorSession: null, suggestion, matchIndex)
2558
{
2659
}
2760

@@ -32,6 +65,8 @@ internal SuggestionEntry(string source, Guid predictorId, uint? predictorSession
3265
PredictorSession = predictorSession;
3366
SuggestionText = suggestion;
3467
InputMatchIndex = matchIndex;
68+
69+
_listItemTextRegular = _listItemTextSelected = null;
3570
}
3671

3772
/// <summary>
@@ -57,8 +92,19 @@ private static int DivideAndRoundUp(int dividend, int divisor)
5792
/// <param name="selectionHighlighting">The highlighting sequences for a selected list item.</param>
5893
internal string GetListItemText(int width, string input, string selectionHighlighting)
5994
{
60-
const string ellipsis = "...";
61-
const int ellipsisLength = 3;
95+
const int ellipsisLength = 1;
96+
97+
if (selectionHighlighting is null)
98+
{
99+
if (_listItemTextRegular is not null)
100+
{
101+
return _listItemTextRegular;
102+
}
103+
}
104+
else if (_listItemTextSelected is not null)
105+
{
106+
return _listItemTextSelected;
107+
}
62108

63109
// Calculate the 'SOURCE' portion to be rendered.
64110
int sourceStrLen = Source.Length;
@@ -119,7 +165,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
119165
// The suggestion text doesn't contain the user input.
120166
int length = SubstringLengthByCells(SuggestionText, textWidth - ellipsisLength);
121167
line.Append(SuggestionText, 0, length)
122-
.Append(ellipsis);
168+
.Append(Ellipsis);
123169
break;
124170
}
125171

@@ -136,7 +182,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
136182
.Append(SuggestionText, 0, input.Length)
137183
.EndColorSection(selectionHighlighting)
138184
.Append(SuggestionText, input.Length, length - input.Length)
139-
.Append(ellipsis);
185+
.Append(Ellipsis);
140186
}
141187
else
142188
{
@@ -149,7 +195,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
149195
int remainingLenInCells = textWidth - ellipsisLength - rightLenInCells;
150196
int length = SubstringLengthByCellsFromEnd(SuggestionText, input.Length - 1, remainingLenInCells);
151197
line.Append(_singleton._options.EmphasisColor)
152-
.Append(ellipsis)
198+
.Append(Ellipsis)
153199
.Append(SuggestionText, input.Length - length, length)
154200
.EndColorSection(selectionHighlighting)
155201
.Append(SuggestionText, input.Length, SuggestionText.Length - input.Length);
@@ -162,11 +208,11 @@ internal string GetListItemText(int width, string input, string selectionHighlig
162208
int startIndex = input.Length - leftStrLen;
163209
int totalStrLen = SubstringLengthByCells(SuggestionText, startIndex, textWidth - ellipsisLength * 2);
164210
line.Append(_singleton._options.EmphasisColor)
165-
.Append(ellipsis)
211+
.Append(Ellipsis)
166212
.Append(SuggestionText, startIndex, leftStrLen)
167213
.EndColorSection(selectionHighlighting)
168214
.Append(SuggestionText, input.Length, totalStrLen - leftStrLen)
169-
.Append(ellipsis);
215+
.Append(Ellipsis);
170216
}
171217
}
172218

@@ -192,7 +238,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
192238
.Append(SuggestionText, InputMatchIndex, input.Length)
193239
.EndColorSection(selectionHighlighting)
194240
.Append(SuggestionText, rightStartindex, rightStrLen)
195-
.Append(ellipsis);
241+
.Append(Ellipsis);
196242
break;
197243
}
198244

@@ -201,7 +247,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
201247
{
202248
// Otherwise, if the (mid+right) portions take up to 2/3 of the text width, we just truncate the suggestion text at the beginning.
203249
int leftStrLen = SubstringLengthByCellsFromEnd(SuggestionText, InputMatchIndex - 1, textWidth - midRightLenInCells - ellipsisLength);
204-
line.Append(ellipsis)
250+
line.Append(Ellipsis)
205251
.Append(SuggestionText, InputMatchIndex - leftStrLen, leftStrLen)
206252
.Append(_singleton._options.EmphasisColor)
207253
.Append(SuggestionText, InputMatchIndex, input.Length)
@@ -223,13 +269,13 @@ internal string GetListItemText(int width, string input, string selectionHighlig
223269
int leftStrLen = SubstringLengthByCellsFromEnd(SuggestionText, InputMatchIndex - 1, leftCellLen - ellipsisLength);
224270
int rightStrLen = SubstringLengthByCells(SuggestionText, rightStartindex, rigthCellLen - ellipsisLength);
225271

226-
line.Append(ellipsis)
272+
line.Append(Ellipsis)
227273
.Append(SuggestionText, InputMatchIndex - leftStrLen, leftStrLen)
228274
.Append(_singleton._options.EmphasisColor)
229275
.Append(SuggestionText, InputMatchIndex, input.Length)
230276
.EndColorSection(selectionHighlighting)
231277
.Append(SuggestionText, rightStartindex, rightStrLen)
232-
.Append(ellipsis);
278+
.Append(Ellipsis);
233279
break;
234280
}
235281

@@ -249,7 +295,7 @@ internal string GetListItemText(int width, string input, string selectionHighlig
249295
line.Append(SuggestionText, 0, InputMatchIndex)
250296
.Append(_singleton._options.EmphasisColor)
251297
.Append(SuggestionText, InputMatchIndex, midLeftStrLen)
252-
.Append(ellipsis)
298+
.Append(Ellipsis)
253299
.Append(SuggestionText, rightStartindex - midRightStrLen, midRightStrLen)
254300
.EndColorSection(selectionHighlighting)
255301
.Append(SuggestionText, rightStartindex, SuggestionText.Length - rightStartindex);
@@ -277,11 +323,11 @@ internal string GetListItemText(int width, string input, string selectionHighlig
277323
line.Append(SuggestionText, 0, InputMatchIndex)
278324
.Append(_singleton._options.EmphasisColor)
279325
.Append(SuggestionText, InputMatchIndex, midLeftStrLen)
280-
.Append(ellipsis)
326+
.Append(Ellipsis)
281327
.Append(SuggestionText, rightStartindex - midRightStrLen, midRightStrLen)
282328
.EndColorSection(selectionHighlighting)
283329
.Append(SuggestionText, rightStartindex, rightStrLen)
284-
.Append(ellipsis);
330+
.Append(Ellipsis);
285331
break;
286332
}
287333

@@ -298,11 +344,11 @@ internal string GetListItemText(int width, string input, string selectionHighlig
298344
int midRightStrLen = SubstringLengthByCellsFromEnd(SuggestionText, rightStartindex - 1, midRightCellLen);
299345
int leftStrLen = SubstringLengthByCellsFromEnd(SuggestionText, InputMatchIndex - 1, midRemainingLenInCells);
300346

301-
line.Append(ellipsis)
347+
line.Append(Ellipsis)
302348
.Append(SuggestionText, InputMatchIndex - leftStrLen, leftStrLen)
303349
.Append(_singleton._options.EmphasisColor)
304350
.Append(SuggestionText, InputMatchIndex, midLeftStrLen)
305-
.Append(ellipsis)
351+
.Append(Ellipsis)
306352
.Append(SuggestionText, rightStartindex - midRightStrLen, midRightStrLen)
307353
.EndColorSection(selectionHighlighting)
308354
.Append(SuggestionText, rightStartindex, SuggestionText.Length - rightStartindex);
@@ -324,15 +370,15 @@ internal string GetListItemText(int width, string input, string selectionHighlig
324370
int spacesNeeded = textWidth - midRemainingLenInCells * 3 - ellipsisLength * 3;
325371
string spaces = spacesNeeded > 0 ? Spaces(spacesNeeded) : string.Empty;
326372

327-
line.Append(ellipsis)
373+
line.Append(Ellipsis)
328374
.Append(SuggestionText, InputMatchIndex - leftStrLen, leftStrLen)
329375
.Append(_singleton._options.EmphasisColor)
330376
.Append(SuggestionText, InputMatchIndex, midLeftStrLen)
331-
.Append(ellipsis)
377+
.Append(Ellipsis)
332378
.Append(SuggestionText, rightStartindex - midRightStrLen, midRightStrLen)
333379
.EndColorSection(selectionHighlighting)
334380
.Append(SuggestionText, rightStartindex, rightStrLen)
335-
.Append(ellipsis)
381+
.Append(Ellipsis)
336382
.Append(spaces);
337383
break;
338384
}
@@ -351,13 +397,29 @@ internal string GetListItemText(int width, string input, string selectionHighlig
351397
else
352398
{
353399
line.Append(Source, 0, sourceStrLen)
354-
.Append(ellipsis);
400+
.Append(Ellipsis);
355401
}
356402

357403
line.EndColorSection(selectionHighlighting)
358404
.Append(']');
359405

360-
return line.ToString();
406+
if (selectionHighlighting is not null)
407+
{
408+
// Need to reset at the end if the selection highlighting is being applied.
409+
line.Append(VTColorUtils.AnsiReset);
410+
}
411+
412+
string textForRendering = line.ToString();
413+
if (selectionHighlighting is null)
414+
{
415+
_listItemTextRegular = textForRendering;
416+
}
417+
else
418+
{
419+
_listItemTextSelected = textForRendering;
420+
}
421+
422+
return textForRendering;
361423
}
362424
}
363425
}

0 commit comments

Comments
 (0)