Skip to content

Commit

Permalink
Address feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
slang25 committed Sep 16, 2023
1 parent 7145357 commit e65251b
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 23 deletions.
8 changes: 2 additions & 6 deletions src/Spectre.Console/Prompts/List/IListPromptStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ 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 All @@ -36,8 +31,9 @@ internal interface IListPromptStrategy<T>
/// <param name="scrollable">Whether or not the list is scrollable.</param>
/// <param name="cursorIndex">The cursor index.</param>
/// <param name="items">The visible items.</param>
/// <param name="skipUnselectableItems">A value indicating whether or not the prompt should skip unselectable items.</param>
/// <param name="searchText">The search text.</param>
/// <returns>A <see cref="IRenderable"/> representing the items.</returns>
public IRenderable Render(IAnsiConsole console, bool scrollable, int cursorIndex,
IEnumerable<(int Index, ListPromptItem<T> Node)> items, string searchText);
IEnumerable<(int Index, ListPromptItem<T> Node)> items, bool skipUnselectableItems, string searchText);
}
4 changes: 3 additions & 1 deletion src/Spectre.Console/Prompts/List/ListPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public ListPrompt(IAnsiConsole console, IListPromptStrategy<T> strategy)
public async Task<ListPromptState<T>> Show(
ListPromptTree<T> tree,
SelectionMode selectionMode,
bool skipUnselectableItems,
bool searchEnabled,
int requestedPageSize,
bool wrapAround,
Expand All @@ -40,7 +41,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, _strategy.ShouldSkipUnselectableItems, searchEnabled);
var state = new ListPromptState<T>(nodes, _strategy.CalculatePageSize(_console, nodes.Count, requestedPageSize), wrapAround, selectionMode, skipUnselectableItems, searchEnabled);
var hook = new ListPromptRenderHook<T>(_console, () => BuildRenderable(state));

using (new RenderHookScope(_console, hook))
Expand Down Expand Up @@ -112,6 +113,7 @@ private IRenderable BuildRenderable(ListPromptState<T> state)
scrollable, cursorIndex,
state.Items.Skip(skip).Take(take)
.Select((node, index) => (index, node)),
state.SkipUnselectableItems,
state.SearchText);
}
}
7 changes: 2 additions & 5 deletions src/Spectre.Console/Prompts/MultiSelectionPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task<List<T>> ShowAsync(IAnsiConsole console, CancellationToken can
{
// Create the list prompt
var prompt = new ListPrompt<T>(console, this);
var result = await prompt.Show(Tree, Mode, false, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
var result = await prompt.Show(Tree, Mode, false, false, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);

if (Mode == SelectionMode.Leaf)
{
Expand Down Expand Up @@ -145,9 +145,6 @@ 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 Expand Up @@ -226,7 +223,7 @@ int IListPromptStrategy<T>.CalculatePageSize(IAnsiConsole console, int totalItem

/// <inheritdoc/>
IRenderable IListPromptStrategy<T>.Render(IAnsiConsole console, bool scrollable, int cursorIndex,
IEnumerable<(int Index, ListPromptItem<T> Node)> items, string searchText)
IEnumerable<(int Index, ListPromptItem<T> Node)> items, bool skipUnselectableItems, string searchText)
{
var list = new List<IRenderable>();
var highlightStyle = HighlightStyle ?? Color.Blue;
Expand Down
16 changes: 9 additions & 7 deletions src/Spectre.Console/Prompts/SelectionPrompt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public sealed class SelectionPrompt<T> : IPrompt<T>, IListPromptStrategy<T>
/// </summary>
public Style? SearchHighlightStyle { get; set; }

/// <summary>
/// Gets or sets the text that will be displayed when no search text has been entered.
/// </summary>
public string? SearchPlaceholderText { get; set; }

/// <summary>
/// Gets or sets the converter to get the display string for a choice. By default
/// the corresponding <see cref="TypeConverter"/> is used.
Expand Down Expand Up @@ -83,9 +88,6 @@ public ISelectionItem<T> AddChoice(T item)
return node;
}

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

/// <inheritdoc/>
public T Show(IAnsiConsole console)
{
Expand All @@ -97,7 +99,7 @@ public async Task<T> ShowAsync(IAnsiConsole console, CancellationToken cancellat
{
// Create the list prompt
var prompt = new ListPrompt<T>(console, this);
var result = await prompt.Show(_tree, Mode, SearchEnabled, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
var result = await prompt.Show(_tree, Mode, true, SearchEnabled, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);

// Return the selected item
return result.Items[result.Index].Data;
Expand All @@ -106,7 +108,7 @@ public async Task<T> ShowAsync(IAnsiConsole console, CancellationToken cancellat
/// <inheritdoc/>
ListPromptInputResult IListPromptStrategy<T>.HandleInput(ConsoleKeyInfo key, ListPromptState<T> state)
{
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Packet)
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Spacebar || key.Key == ConsoleKey.Packet)
{
// Selecting a non leaf in "leaf mode" is not allowed
if (state.Current.IsGroup && Mode == SelectionMode.Leaf)
Expand Down Expand Up @@ -157,7 +159,7 @@ int IListPromptStrategy<T>.CalculatePageSize(IAnsiConsole console, int totalItem

/// <inheritdoc/>
IRenderable IListPromptStrategy<T>.Render(IAnsiConsole console, bool scrollable, int cursorIndex,
IEnumerable<(int Index, ListPromptItem<T> Node)> items, string searchText)
IEnumerable<(int Index, ListPromptItem<T> Node)> items, bool skipUnselectableItems, string searchText)
{
var list = new List<IRenderable>();
var disabledStyle = DisabledStyle ?? Color.Grey;
Expand Down Expand Up @@ -224,7 +226,7 @@ IRenderable IListPromptStrategy<T>.Render(IAnsiConsole console, bool scrollable,
if (SearchEnabled)
{
list.Add(new Markup(
searchText.Length > 0 ? searchText.EscapeMarkup() : ListPromptConstants.SearchPlaceholderMarkup));
searchText.Length > 0 ? searchText.EscapeMarkup() : SearchPlaceholderText ?? ListPromptConstants.SearchPlaceholderMarkup));
}

if (scrollable)
Expand Down
44 changes: 40 additions & 4 deletions src/Spectre.Console/Prompts/SelectionPromptExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,21 +183,57 @@ public static SelectionPrompt<T> WrapAround<T>(this SelectionPrompt<T> obj, bool
}

/// <summary>
/// Sets whether the search filter should be enabled.
/// Enables search for the prompt.
/// </summary>
/// <typeparam name="T">The prompt result type.</typeparam>
/// <param name="obj">The prompt.</param>
/// <param name="enabled">Whether the search filter should be enabled.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static SelectionPrompt<T> Search<T>(this SelectionPrompt<T> obj, bool enabled = true)
public static SelectionPrompt<T> EnableSearch<T>(this SelectionPrompt<T> obj)
where T : notnull
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}

obj.SearchEnabled = enabled;
obj.SearchEnabled = true;
return obj;
}

/// <summary>
/// Disables search for the prompt.
/// </summary>
/// <typeparam name="T">The prompt result type.</typeparam>
/// <param name="obj">The prompt.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static SelectionPrompt<T> DisableSearch<T>(this SelectionPrompt<T> obj)
where T : notnull
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}

obj.SearchEnabled = false;
return obj;
}

/// <summary>
/// Sets the text that will be displayed when no search text has been entered.
/// </summary>
/// <typeparam name="T">The prompt result type.</typeparam>
/// <param name="obj">The prompt.</param>
/// <param name="text">The text to display.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static SelectionPrompt<T> SearchPlaceholderText<T>(this SelectionPrompt<T> obj, string? text)
where T : notnull
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}

obj.SearchPlaceholderText = text;
return obj;
}

Expand Down

0 comments on commit e65251b

Please sign in to comment.