diff --git a/Sharprompt.Example/Program.cs b/Sharprompt.Example/Program.cs index b1bc839..323d366 100644 --- a/Sharprompt.Example/Program.cs +++ b/Sharprompt.Example/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text; using System.Text.Json; @@ -79,6 +80,7 @@ private static void RunSelectSample() private static void RunMultiSelectSample() { var options = Prompt.MultiSelect("Which cities would you like to visit?", new[] { "Seattle", "London", "Tokyo", "New York", "Singapore", "Shanghai" }, pageSize: 3, defaultValues: new[] { "Tokyo" }); + Console.WriteLine($"You picked {string.Join(", ", options)}"); } diff --git a/Sharprompt.Tests/PaginatorTests.cs b/Sharprompt.Tests/PaginatorTests.cs index 3d9b8c9..308f48d 100644 --- a/Sharprompt.Tests/PaginatorTests.cs +++ b/Sharprompt.Tests/PaginatorTests.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using Sharprompt.Internal; @@ -8,10 +9,12 @@ namespace Sharprompt.Tests; public class PaginatorTests { + private readonly Func _containsTextInputFilter = (item, keyword) => item.ToString().Contains(keyword, StringComparison.OrdinalIgnoreCase); + [Fact] public void Basic() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); var currentItems1 = paginator.CurrentItems; @@ -29,7 +32,7 @@ public void Basic() [Fact] public void Filter_NotEmpty() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); paginator.UpdateFilter("0"); @@ -42,7 +45,7 @@ public void Filter_NotEmpty() [Fact] public void Filter_Empty() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); paginator.UpdateFilter("x"); @@ -54,7 +57,7 @@ public void Filter_Empty() [Fact] public void SelectedItem() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); paginator.NextPage(); paginator.NextItem(); @@ -68,7 +71,7 @@ public void SelectedItem() [Fact] public void SelectedItem_NotSelected() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); var selected = paginator.TryGetSelectedItem(out _); @@ -78,7 +81,7 @@ public void SelectedItem_NotSelected() [Fact] public void SelectedItem_EmptyList() { - var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString()); + var paginator = new Paginator(Enumerable.Range(0, 20), 5, Optional.Empty, x => x.ToString(), _containsTextInputFilter); paginator.UpdateFilter("x"); paginator.NextItem(); diff --git a/Sharprompt/Forms/MultiSelectForm.cs b/Sharprompt/Forms/MultiSelectForm.cs index 0b477a1..c55872f 100644 --- a/Sharprompt/Forms/MultiSelectForm.cs +++ b/Sharprompt/Forms/MultiSelectForm.cs @@ -15,7 +15,7 @@ public MultiSelectForm(MultiSelectOptions options) options.EnsureOptions(); _options = options; - _paginator = new Paginator(options.Items, Math.Min(options.PageSize, Height - 2), Optional.Empty, options.TextSelector) + _paginator = new Paginator(options.Items, Math.Min(options.PageSize, Height - 2), Optional.Empty, options.TextSelector, options.TextInputFilter) { LoopingSelection = options.LoopingSelection }; diff --git a/Sharprompt/Forms/SelectForm.cs b/Sharprompt/Forms/SelectForm.cs index 241db25..9475af1 100644 --- a/Sharprompt/Forms/SelectForm.cs +++ b/Sharprompt/Forms/SelectForm.cs @@ -14,7 +14,7 @@ public SelectForm(SelectOptions options) options.EnsureOptions(); _options = options; - _paginator = new Paginator(options.Items, Math.Min(options.PageSize, Height - 2), Optional.Create(options.DefaultValue), options.TextSelector) + _paginator = new Paginator(options.Items, Math.Min(options.PageSize, Height - 2), Optional.Create(options.DefaultValue), options.TextSelector, options.TextInputFilter) { LoopingSelection = options.LoopingSelection }; diff --git a/Sharprompt/Internal/Paginator.cs b/Sharprompt/Internal/Paginator.cs index e1e5680..c367522 100644 --- a/Sharprompt/Internal/Paginator.cs +++ b/Sharprompt/Internal/Paginator.cs @@ -8,17 +8,19 @@ namespace Sharprompt.Internal; internal class Paginator : IEnumerable where T : notnull { - public Paginator(IEnumerable items, int pageSize, Optional defaultValue, Func textSelector) + public Paginator(IEnumerable items, int pageSize, Optional defaultValue, Func textSelector, Func textInputFilter) { _items = items.ToArray(); _pageSize = pageSize <= 0 ? _items.Length : Math.Min(pageSize, _items.Length); _textSelector = textSelector; + _filterFunc = textInputFilter; InitializeDefaults(defaultValue); } private readonly T[] _items; private readonly Func _textSelector; + private readonly Func _filterFunc; private int _pageSize; private T[] _filteredItems = Array.Empty(); @@ -144,8 +146,8 @@ public void UpdatePageSize(int newPageSize) private void UpdateFilteredItems() { - _filteredItems = _items.Where(x => _textSelector(x).IndexOf(FilterKeyword, StringComparison.OrdinalIgnoreCase) != -1) - .ToArray(); + _filteredItems = _items.Where(x => _filterFunc(x, FilterKeyword)) + .ToArray(); PageCount = (_filteredItems.Length - 1) / _pageSize + 1; diff --git a/Sharprompt/MultiSelectOptions.cs b/Sharprompt/MultiSelectOptions.cs index 02e636a..948e47c 100644 --- a/Sharprompt/MultiSelectOptions.cs +++ b/Sharprompt/MultiSelectOptions.cs @@ -32,6 +32,8 @@ public MultiSelectOptions() public Func TextSelector { get; set; } = x => x.ToString()!; + public Func TextInputFilter { get; set; } = (item, keyword) => item.ToString().Contains(keyword, StringComparison.OrdinalIgnoreCase); + public Func Pagination { get; set; } = (count, current, total) => string.Format(Resource.Message_Pagination, count, current, total); public bool LoopingSelection { get; set; } = true; diff --git a/Sharprompt/Prompt.Basic.cs b/Sharprompt/Prompt.Basic.cs index 2a12620..d8a3ee3 100644 --- a/Sharprompt/Prompt.Basic.cs +++ b/Sharprompt/Prompt.Basic.cs @@ -106,7 +106,7 @@ public static T Select(Action> configure) where T : notnull return Select(options); } - public static T Select(string message, IEnumerable? items = default, int pageSize = int.MaxValue, object? defaultValue = default, Func? textSelector = default) where T : notnull + public static T Select(string message, IEnumerable? items = default, int pageSize = int.MaxValue, object? defaultValue = default, Func? textSelector = default, Func? textInputFilter = default) where T : notnull { return Select(options => { @@ -124,6 +124,11 @@ public static T Select(string message, IEnumerable? items = default, int p { options.TextSelector = textSelector; } + + if (textInputFilter is not null) + { + options.TextInputFilter = textInputFilter; + } }); } @@ -143,7 +148,9 @@ public static IEnumerable MultiSelect(Action> config return MultiSelect(options); } - public static IEnumerable MultiSelect(string message, IEnumerable? items = null, int pageSize = int.MaxValue, int minimum = 1, int maximum = int.MaxValue, IEnumerable? defaultValues = default, Func? textSelector = default) where T : notnull + public static IEnumerable MultiSelect(string message, + IEnumerable? items = null, int pageSize = int.MaxValue, int minimum = 1, int maximum = int.MaxValue, + IEnumerable? defaultValues = default, Func? textSelector = default, Func? textInputFilter = default) where T : notnull { return MultiSelect(options => { @@ -167,6 +174,11 @@ public static IEnumerable MultiSelect(string message, IEnumerable? item { options.TextSelector = textSelector; } + + if (textInputFilter is not null) + { + options.TextInputFilter = textInputFilter; + } }); } diff --git a/Sharprompt/SelectOptions.cs b/Sharprompt/SelectOptions.cs index e3c2e15..6e28790 100644 --- a/Sharprompt/SelectOptions.cs +++ b/Sharprompt/SelectOptions.cs @@ -27,6 +27,8 @@ public SelectOptions() public Func TextSelector { get; set; } = x => x.ToString()!; + public Func TextInputFilter { get; set; } = (item, keyword) => item.ToString().Contains(keyword, StringComparison.OrdinalIgnoreCase); + public Func Pagination { get; set; } = (count, current, total) => string.Format(Resource.Message_Pagination, count, current, total); public bool LoopingSelection { get; set; } = true;