Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor naming rule and optimize #245

Merged
merged 1 commit into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Sharprompt.Tests/PaginatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ public void Basic()
{
var paginator = new Paginator<int>(Enumerable.Range(0, 20), 5, Optional<int>.Empty, x => x.ToString());

var subset1 = paginator.ToSubset();
var currentItems1 = paginator.CurrentItems;

Assert.Equal(5, subset1.Count);
Assert.Equal(new[] { 0, 1, 2, 3, 4 }, subset1);
Assert.Equal(5, currentItems1.Length);
Assert.Equal(new[] { 0, 1, 2, 3, 4 }, currentItems1.ToArray());

paginator.NextPage();

var subset2 = paginator.ToSubset();
var currentItems2 = paginator.CurrentItems;

Assert.Equal(5, subset2.Count);
Assert.Equal(new[] { 5, 6, 7, 8, 9 }, subset2);
Assert.Equal(5, currentItems2.Length);
Assert.Equal(new[] { 5, 6, 7, 8, 9 }, currentItems2.ToArray());
}

[Fact]
Expand All @@ -33,10 +33,10 @@ public void Filter_NotEmpty()

paginator.UpdateFilter("0");

var subset = paginator.ToSubset();
var currentItems = paginator.CurrentItems;

Assert.Equal(2, subset.Count);
Assert.Equal(new[] { 0, 10 }, subset);
Assert.Equal(2, currentItems.Length);
Assert.Equal(new[] { 0, 10 }, currentItems.ToArray());
}

[Fact]
Expand All @@ -46,9 +46,9 @@ public void Filter_Empty()

paginator.UpdateFilter("x");

var subset = paginator.ToSubset();
var subset = paginator.CurrentItems;

Assert.Empty(subset);
Assert.True(subset.IsEmpty);
}

[Fact]
Expand Down
64 changes: 32 additions & 32 deletions Sharprompt/Forms/FormBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,6 @@ public T Start()
}
}

protected bool TryGetResult([NotNullWhen(true)] out T? result)
{
do
{
var keyInfo = _consoleDriver.ReadKey();

if (keyInfo.Key == ConsoleKey.Enter)
{
return HandleEnter(out result);
}

if (KeyHandlerMaps.TryGetValue(keyInfo.Key, out var keyHandler) && keyHandler(keyInfo))
{
continue;
}

if (!char.IsControl(keyInfo.KeyChar))
{
HandleTextInput(keyInfo);
}
else
{
_consoleDriver.Beep();
}

} while (_consoleDriver.KeyAvailable);

result = default;

return false;
}

protected abstract void InputTemplate(OffscreenBuffer offscreenBuffer);

protected abstract void FinishTemplate(OffscreenBuffer offscreenBuffer, T result);
Expand Down Expand Up @@ -116,6 +84,38 @@ protected bool TryValidate([NotNullWhen(true)] object? input, IList<Func<object?
return true;
}

private bool TryGetResult([NotNullWhen(true)] out T? result)
{
do
{
var keyInfo = _consoleDriver.ReadKey();

if (keyInfo.Key == ConsoleKey.Enter)
{
return HandleEnter(out result);
}

if (KeyHandlerMaps.TryGetValue(keyInfo.Key, out var keyHandler) && keyHandler(keyInfo))
{
continue;
}

if (!char.IsControl(keyInfo.KeyChar))
{
HandleTextInput(keyInfo);
}
else
{
_consoleDriver.Beep();
}

} while (_consoleDriver.KeyAvailable);

result = default;

return false;
}

private void CancellationHandler()
{
_formRenderer.Cancel();
Expand Down
2 changes: 1 addition & 1 deletion Sharprompt/Forms/InputForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ protected override bool HandleEnter([NotNullWhen(true)] out T? result)
{
if (string.IsNullOrEmpty(input))
{
if (TypeHelper<T>.IsValueType && !_defaultValue.HasValue)
if (!TypeHelper<T>.IsNullable && !_defaultValue.HasValue)
{
SetError(Resource.Validation_Required);

Expand Down
14 changes: 6 additions & 8 deletions Sharprompt/Forms/MultiSelectForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,16 @@ public MultiSelectForm(MultiSelectOptions<T> options)
protected override void InputTemplate(OffscreenBuffer offscreenBuffer)
{
offscreenBuffer.WritePrompt(_options.Message);
offscreenBuffer.Write(_paginator.FilterTerm);
offscreenBuffer.Write(_paginator.FilterKeyword);

offscreenBuffer.PushCursor();

if (string.IsNullOrEmpty(_paginator.FilterTerm))
if (string.IsNullOrEmpty(_paginator.FilterKeyword))
{
offscreenBuffer.WriteHint(Resource.MultiSelectForm_Message_Hint);
}

var subset = _paginator.ToSubset();

foreach (var item in subset)
foreach (var item in _paginator.CurrentItems)
{
var value = _options.TextSelector(item);

Expand All @@ -80,7 +78,7 @@ protected override void InputTemplate(OffscreenBuffer offscreenBuffer)
if (_paginator.PageCount > 1)
{
offscreenBuffer.WriteLine();
offscreenBuffer.WriteHint(_options.Pagination(_paginator.TotalCount, _paginator.SelectedPage + 1, _paginator.PageCount));
offscreenBuffer.WriteHint(_options.Pagination(_paginator.TotalCount, _paginator.CurrentPage + 1, _paginator.PageCount));
}
}

Expand Down Expand Up @@ -197,7 +195,7 @@ private bool HandleAWithControl(ConsoleKeyInfo keyInfo)
}
else
{
foreach (var item in _paginator.FilteredItems)
foreach (var item in _paginator)
{
_selectedItems.Add(item);
}
Expand All @@ -213,7 +211,7 @@ private bool HandleIWithControl(ConsoleKeyInfo keyInfo)
return false;
}

var invertedItems = _paginator.FilteredItems.Except(_selectedItems).ToArray();
var invertedItems = _paginator.Except(_selectedItems).ToArray();

_selectedItems.Clear();

Expand Down
8 changes: 3 additions & 5 deletions Sharprompt/Forms/SelectForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ public SelectForm(SelectOptions<T> options)
protected override void InputTemplate(OffscreenBuffer offscreenBuffer)
{
offscreenBuffer.WritePrompt(_options.Message);
offscreenBuffer.Write(_paginator.FilterTerm);
offscreenBuffer.Write(_paginator.FilterKeyword);

offscreenBuffer.PushCursor();

var subset = _paginator.ToSubset();

foreach (var item in subset)
foreach (var item in _paginator.CurrentItems)
{
var value = _options.TextSelector(item);

Expand All @@ -57,7 +55,7 @@ protected override void InputTemplate(OffscreenBuffer offscreenBuffer)
if (_paginator.PageCount > 1)
{
offscreenBuffer.WriteLine();
offscreenBuffer.WriteHint(_options.Pagination(_paginator.TotalCount, _paginator.SelectedPage + 1, _paginator.PageCount));
offscreenBuffer.WriteHint(_options.Pagination(_paginator.TotalCount, _paginator.CurrentPage + 1, _paginator.PageCount));
}
}

Expand Down
54 changes: 29 additions & 25 deletions Sharprompt/Internal/Paginator.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace Sharprompt.Internal;

internal class Paginator<T> where T : notnull
internal class Paginator<T> : IEnumerable<T> where T : notnull
{
public Paginator(IEnumerable<T> items, int pageSize, Optional<T> defaultValue, Func<T, string> textSelector)
{
Expand All @@ -20,37 +21,38 @@ public Paginator(IEnumerable<T> items, int pageSize, Optional<T> defaultValue, F
private readonly int _pageSize;
private readonly Func<T, string> _textSelector;

private T[] _filteredItems = Array.Empty<T>();
private int _selectedIndex = -1;

public T[] FilteredItems { get; private set; } = Array.Empty<T>();
public ReadOnlySpan<T> CurrentItems => new(_filteredItems, _pageSize * CurrentPage, Count);

public int PageCount { get; private set; }

public int SelectedPage { get; private set; }
public int CurrentPage { get; private set; }

public int Count => Math.Min(FilteredItems.Length - (_pageSize * SelectedPage), _pageSize);
public int Count => Math.Min(_filteredItems.Length - (_pageSize * CurrentPage), _pageSize);

public int TotalCount => FilteredItems.Length;
public int TotalCount => _filteredItems.Length;

public string FilterTerm { get; private set; } = "";
public string FilterKeyword { get; private set; } = "";

public bool TryGetSelectedItem([NotNullWhen(true)] out T? selectedItem)
{
if (FilteredItems.Length == 1)
if (_filteredItems.Length == 1)
{
selectedItem = FilteredItems[0];
selectedItem = _filteredItems[0];

return true;
}

if (_selectedIndex == -1 || FilteredItems.Length == 0)
if (_selectedIndex == -1 || _filteredItems.Length == 0)
{
selectedItem = default;

return false;
}

selectedItem = FilteredItems[(_pageSize * SelectedPage) + _selectedIndex];
selectedItem = _filteredItems[(_pageSize * CurrentPage) + _selectedIndex];

return true;
}
Expand All @@ -72,8 +74,8 @@ public void NextPage()
return;
}

SelectedPage = SelectedPage >= PageCount - 1 ? 0 : SelectedPage + 1;
_selectedIndex = -1;
CurrentPage = CurrentPage >= PageCount - 1 ? 0 : CurrentPage + 1;
}

public void PreviousPage()
Expand All @@ -83,45 +85,47 @@ public void PreviousPage()
return;
}

SelectedPage = SelectedPage <= 0 ? PageCount - 1 : SelectedPage - 1;
_selectedIndex = -1;
CurrentPage = CurrentPage <= 0 ? PageCount - 1 : CurrentPage - 1;
}

public void UpdateFilter(string term)
public void UpdateFilter(string keyword)
{
FilterTerm = term;
FilterKeyword = keyword;

_selectedIndex = -1;
SelectedPage = 0;
CurrentPage = 0;

UpdateItems();
UpdateFilteredItems();
}

public ArraySegment<T> ToSubset() => new(FilteredItems, _pageSize * SelectedPage, Count);
public IEnumerator<T> GetEnumerator() => (IEnumerator<T>)_filteredItems.GetEnumerator();

private void UpdateItems()
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

private void UpdateFilteredItems()
{
FilteredItems = _items.Where(x => _textSelector(x).IndexOf(FilterTerm, StringComparison.OrdinalIgnoreCase) != -1)
.ToArray();
_filteredItems = _items.Where(x => _textSelector(x).IndexOf(FilterKeyword, StringComparison.OrdinalIgnoreCase) != -1)
.ToArray();

PageCount = (FilteredItems.Length - 1) / _pageSize + 1;
PageCount = (_filteredItems.Length - 1) / _pageSize + 1;
}

private void InitializeDefaults(Optional<T> defaultValue)
{
UpdateItems();
UpdateFilteredItems();

if (!defaultValue.HasValue)
{
return;
}

for (var i = 0; i < FilteredItems.Length; i++)
for (var i = 0; i < _filteredItems.Length; i++)
{
if (EqualityComparer<T>.Default.Equals(FilteredItems[i], defaultValue))
if (EqualityComparer<T>.Default.Equals(_filteredItems[i], defaultValue))
{
_selectedIndex = i % _pageSize;
SelectedPage = i / _pageSize;
CurrentPage = i / _pageSize;

break;
}
Expand Down
18 changes: 3 additions & 15 deletions Sharprompt/Internal/PropertyMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public PropertyMetadata(object model, PropertyInfo propertyInfo)
.Select(x => new ValidationAttributeAdapter(x).GetValidator(propertyInfo.Name, model))
.ToArray();
ItemsProvider = GetItemsProvider(propertyInfo);
BindIgnore = propertyInfo.GetCustomAttribute<BindIgnoreAttribute>() is not null;
}

public PropertyInfo PropertyInfo { get; }
Expand All @@ -45,7 +44,6 @@ public PropertyMetadata(object model, PropertyInfo propertyInfo)
public object? DefaultValue { get; }
public IReadOnlyList<Func<object?, ValidationResult?>> Validators { get; }
public IItemsProvider ItemsProvider { get; }
public bool BindIgnore { get; set; }

public FormType DetermineFormType()
{
Expand All @@ -59,22 +57,12 @@ public FormType DetermineFormType()
return FormType.Confirm;
}

if (!IsCollection && ItemsProvider is not NullItemsProvider)
if (ItemsProvider is not NullItemsProvider)
{
return FormType.Select;
return IsCollection ? FormType.MultiSelect : FormType.Select;
}

if (IsCollection && ItemsProvider is not NullItemsProvider)
{
return FormType.MultiSelect;
}

if (IsCollection && ItemsProvider is NullItemsProvider)
{
return FormType.List;
}

return FormType.Input;
return IsCollection ? FormType.List : FormType.Input;
}

private IItemsProvider GetItemsProvider(PropertyInfo propertyInfo)
Expand Down
3 changes: 1 addition & 2 deletions Sharprompt/Internal/PropertyMetadataFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ internal static class PropertyMetadataFactory
public static IReadOnlyList<PropertyMetadata> Create<T>(T model) where T : notnull
{
return typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.CanWrite)
.Where(x => x.CanWrite && x.GetCustomAttribute<BindIgnoreAttribute>() is null)
.Select(x => new PropertyMetadata(model, x))
.Where(x => !x.BindIgnore)
.OrderBy(x => x.Order)
.ToArray();
}
Expand Down
Loading