Fix search bug in prompt related to custom item types

Closes #1626
This commit is contained in:
Patrik Svensson
2024-09-03 00:37:00 +02:00
committed by Patrik Svensson
parent 753894de94
commit fd69ad0b01
6 changed files with 70 additions and 7 deletions

View File

@ -14,6 +14,7 @@ internal sealed class ListPrompt<T>
public async Task<ListPromptState<T>> Show(
ListPromptTree<T> tree,
Func<T, string> converter,
SelectionMode selectionMode,
bool skipUnselectableItems,
bool searchEnabled,
@ -41,7 +42,7 @@ internal sealed class ListPrompt<T>
}
var nodes = tree.Traverse().ToList();
var state = new ListPromptState<T>(nodes, _strategy.CalculatePageSize(_console, nodes.Count, requestedPageSize), wrapAround, selectionMode, skipUnselectableItems, searchEnabled);
var state = new ListPromptState<T>(nodes, converter, _strategy.CalculatePageSize(_console, nodes.Count, requestedPageSize), wrapAround, selectionMode, skipUnselectableItems, searchEnabled);
var hook = new ListPromptRenderHook<T>(_console, () => BuildRenderable(state));
using (new RenderHookScope(_console, hook))

View File

@ -3,6 +3,8 @@ namespace Spectre.Console;
internal sealed class ListPromptState<T>
where T : notnull
{
private readonly Func<T, string> _converter;
public int Index { get; private set; }
public int ItemCount => Items.Count;
public int PageSize { get; }
@ -16,8 +18,15 @@ internal sealed class ListPromptState<T>
public ListPromptItem<T> Current => Items[Index];
public string SearchText { get; private set; }
public ListPromptState(IReadOnlyList<ListPromptItem<T>> items, int pageSize, bool wrapAround, SelectionMode mode, bool skipUnselectableItems, bool searchEnabled)
public ListPromptState(
IReadOnlyList<ListPromptItem<T>> items,
Func<T, string> converter,
int pageSize, bool wrapAround,
SelectionMode mode,
bool skipUnselectableItems,
bool searchEnabled)
{
_converter = converter ?? throw new ArgumentNullException(nameof(converter));
Items = items;
PageSize = pageSize;
WrapAround = wrapAround;
@ -126,7 +135,11 @@ internal sealed class ListPromptState<T>
if (!char.IsControl(keyInfo.KeyChar))
{
search = SearchText + keyInfo.KeyChar;
var item = Items.FirstOrDefault(x => x.Data.ToString()?.Contains(search, StringComparison.OrdinalIgnoreCase) == true && (!x.IsGroup || Mode != SelectionMode.Leaf));
var item = Items.FirstOrDefault(x =>
_converter.Invoke(x.Data).Contains(search, StringComparison.OrdinalIgnoreCase)
&& (!x.IsGroup || Mode != SelectionMode.Leaf));
if (item != null)
{
index = Items.IndexOf(item);
@ -140,7 +153,10 @@ internal sealed class ListPromptState<T>
search = search.Substring(0, search.Length - 1);
}
var item = Items.FirstOrDefault(x => x.Data.ToString()?.Contains(search, StringComparison.OrdinalIgnoreCase) == true && (!x.IsGroup || Mode != SelectionMode.Leaf));
var item = Items.FirstOrDefault(x =>
_converter.Invoke(x.Data).Contains(search, StringComparison.OrdinalIgnoreCase) &&
(!x.IsGroup || Mode != SelectionMode.Leaf));
if (item != null)
{
index = Items.IndexOf(item);

View File

@ -94,7 +94,8 @@ public sealed class MultiSelectionPrompt<T> : IPrompt<List<T>>, IListPromptStrat
{
// Create the list prompt
var prompt = new ListPrompt<T>(console, this);
var result = await prompt.Show(Tree, Mode, false, false, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
var converter = Converter ?? TypeConverterHelper.ConvertToString;
var result = await prompt.Show(Tree, converter, Mode, false, false, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
if (Mode == SelectionMode.Leaf)
{

View File

@ -99,7 +99,8 @@ public sealed class SelectionPrompt<T> : IPrompt<T>, IListPromptStrategy<T>
{
// Create the list prompt
var prompt = new ListPrompt<T>(console, this);
var result = await prompt.Show(_tree, Mode, true, SearchEnabled, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
var converter = Converter ?? TypeConverterHelper.ConvertToString;
var result = await prompt.Show(_tree, converter, Mode, true, SearchEnabled, PageSize, WrapAround, cancellationToken).ConfigureAwait(false);
// Return the selected item
return result.Items[result.Index].Data;