Skip to content

Commit

Permalink
Handle multi-selection prompt better
Browse files Browse the repository at this point in the history
  • Loading branch information
slang25 committed Sep 4, 2023
1 parent ead4332 commit 81b80f9
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 17 deletions.
5 changes: 5 additions & 0 deletions src/Spectre.Console/Prompts/List/IListPromptStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace Spectre.Console;
internal interface IListPromptStrategy<T>
where T : notnull
{
/// <summary>
/// Gets a value indicating whether or not the prompt should skip unselectable items.
/// </summary>
public bool ShouldSkipUnselectableItems { get; }

/// <summary>
/// Handles any input received from the user.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Spectre.Console/Prompts/List/ListPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public async Task<ListPromptState<T>> Show(
}

var nodes = tree.Traverse().ToList();
var state = new ListPromptState<T>(nodes, _strategy.CalculatePageSize(_console, nodes.Count, requestedPageSize), wrapAround, selectionMode, searchFilterEnabled);
var state = new ListPromptState<T>(nodes, _strategy.CalculatePageSize(_console, nodes.Count, requestedPageSize), wrapAround, selectionMode, _strategy.ShouldSkipUnselectableItems, searchFilterEnabled);
var hook = new ListPromptRenderHook<T>(_console, () => BuildRenderable(state));

using (new RenderHookScope(_console, hook))
Expand Down
10 changes: 6 additions & 4 deletions src/Spectre.Console/Prompts/List/ListPromptState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,25 @@ internal sealed class ListPromptState<T>
public int PageSize { get; }
public bool WrapAround { get; }
public SelectionMode Mode { get; }
public bool SkipUnselectableItems { get; private set; }
public bool SearchFilterEnabled { get; }
public IReadOnlyList<ListPromptItem<T>> Items { get; }
private readonly IReadOnlyList<int>? _leafIndexes;

public ListPromptItem<T> Current => Items[Index];
public string SearchFilter { get; set; }
public string SearchFilter { get; private set; }

public ListPromptState(IReadOnlyList<ListPromptItem<T>> items, int pageSize, bool wrapAround, SelectionMode mode, bool searchFilterEnabled)
public ListPromptState(IReadOnlyList<ListPromptItem<T>> items, int pageSize, bool wrapAround, SelectionMode mode, bool skipUnselectableItems, bool searchFilterEnabled)
{
Items = items;
PageSize = pageSize;
WrapAround = wrapAround;
Mode = mode;
SkipUnselectableItems = skipUnselectableItems;
SearchFilterEnabled = searchFilterEnabled;
SearchFilter = string.Empty;

if (mode == SelectionMode.Leaf)
if (SkipUnselectableItems && mode == SelectionMode.Leaf)
{
_leafIndexes =
Items
Expand All @@ -45,7 +47,7 @@ public ListPromptState(IReadOnlyList<ListPromptItem<T>> items, int pageSize, boo
public bool Update(ConsoleKeyInfo keyInfo)
{
var index = Index;
if (Mode == SelectionMode.Leaf)
if (SkipUnselectableItems && Mode == SelectionMode.Leaf)
{
Debug.Assert(_leafIndexes != null, nameof(_leafIndexes) + " != null");
var currentLeafIndex = _leafIndexes.IndexOf(index);
Expand Down
3 changes: 3 additions & 0 deletions src/Spectre.Console/Prompts/MultiSelectionPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ public IEnumerable<T> GetParents(T item)
return GetParents(item).LastOrDefault();
}

/// <inheritdoc />
bool IListPromptStrategy<T>.ShouldSkipUnselectableItems => false;

/// <inheritdoc/>
ListPromptInputResult IListPromptStrategy<T>.HandleInput(ConsoleKeyInfo key, ListPromptState<T> state)
{
Expand Down
32 changes: 21 additions & 11 deletions src/Spectre.Console/Prompts/SelectionPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public ISelectionItem<T> AddChoice(T item)
return node;
}

/// <inheritdoc />
bool IListPromptStrategy<T>.ShouldSkipUnselectableItems => true;

/// <inheritdoc/>
public T Show(IAnsiConsole console)
{
Expand Down Expand Up @@ -128,17 +131,20 @@ int IListPromptStrategy<T>.CalculatePageSize(IAnsiConsole console, int totalItem
extra += 2;
}

// Scrolling?
if (totalItemCount > requestedPageSize)
var scrollable = totalItemCount > requestedPageSize;
if (SearchFilterEnabled || scrollable)
{
// The scrolling instructions takes up two rows
extra += 2;
extra += 1;
}

if (SearchFilterEnabled)
{
// The search instructions takes up two rows
extra += 2;
extra += 1;
}

if (scrollable)
{
extra += 1;
}

if (requestedPageSize > console.Profile.Height - extra)
Expand Down Expand Up @@ -209,18 +215,22 @@ IRenderable IListPromptStrategy<T>.Render(IAnsiConsole console, bool scrollable,

list.Add(grid);

if (scrollable)
if (SearchFilterEnabled || scrollable)
{
// (Move up and down to reveal more choices)
// Add padding
list.Add(Text.Empty);
list.Add(new Markup(MoreChoicesText ?? ListPromptConstants.MoreChoicesMarkup));
}

if (SearchFilterEnabled)
{
list.Add(Text.Empty);
list.Add(new Markup(
$"search: {(stateSearchFilter.Length > 0 ? stateSearchFilter.EscapeMarkup() : ListPromptConstants.SearchPlaceholderMarkup)}"));
stateSearchFilter.Length > 0 ? stateSearchFilter.EscapeMarkup() : ListPromptConstants.SearchPlaceholderMarkup));
}

if (scrollable)
{
// (Move up and down to reveal more choices)
list.Add(new Markup(MoreChoicesText ?? ListPromptConstants.MoreChoicesMarkup));
}

return new Rows(list);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Spectre.Console.Tests.Unit;
public sealed class ListPromptStateTests
{
private ListPromptState<string> CreateListPromptState(int count, int pageSize, bool shouldWrap)
=> new(Enumerable.Repeat(new ListPromptItem<string>(string.Empty), count).ToList(), pageSize, shouldWrap, SelectionMode.Independent, false);
=> new(Enumerable.Repeat(new ListPromptItem<string>(string.Empty), count).ToList(), pageSize, shouldWrap, SelectionMode.Independent, true, false);

[Fact]
public void Should_Have_Start_Index_Zero()
Expand Down

0 comments on commit 81b80f9

Please sign in to comment.