Skip to content

Commit

Permalink
Add async API
Browse files Browse the repository at this point in the history
resolves #10
  • Loading branch information
lechu445 committed Feb 17, 2023
1 parent 6d4f3b8 commit c73a044
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 55 deletions.
109 changes: 102 additions & 7 deletions ConsoleMenu/ConsoleMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

[assembly: InternalsVisibleTo("ConsoleMenuTests")]

Expand Down Expand Up @@ -68,7 +70,7 @@ private IReadOnlyList<string> Titles
get
{
ConsoleMenu? current = this;
List<string> titles = new List<string>();
List<string> titles = new();
while (current != null)
{
titles.Add(current.config.Title ?? "");
Expand All @@ -83,7 +85,10 @@ private IReadOnlyList<string> Titles
/// <summary>
/// Don't run this method directly. Just pass a reference to this method.
/// </summary>
public static void Close() => throw new InvalidOperationException("Don't run this method directly. Just pass a reference to this method.");
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
/// <exception cref="InvalidOperationException">Thrown if this method is called directly.</exception>
public static Task Close(CancellationToken cancellationToken) => throw new InvalidOperationException("Don't run this method directly. Just pass a reference to this method.");

/// <summary>
/// Close the menu before or after a menu action was triggered.
Expand All @@ -94,7 +99,7 @@ public void CloseMenu()
}

/// <summary>
/// Adds a menu item into this instance.
/// Adds a menu action into this instance.
/// </summary>
/// <param name="name">Name of menu item.</param>
/// <param name="action">Action to call when menu item is chosen.</param>
Expand All @@ -116,12 +121,43 @@ public ConsoleMenu Add(string name, Action action)
child.parent = this;
}

this.menuItems.Add(name, (_) =>
{
action();
return Task.CompletedTask;
});
return this;
}

/// <summary>
/// Adds an asynchronous menu action into this instance.
/// </summary>
/// <param name="name">Name of menu item.</param>
/// <param name="action">Action to call when menu item is chosen.</param>
/// <returns>This instance with added menu item.</returns>
public ConsoleMenu Add(string name, Func<CancellationToken, Task> action)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}

if (action == null)
{
throw new ArgumentNullException(nameof(action));
}

if (action.Target is ConsoleMenu child && action == child.ShowAsync)
{
child.parent = this;
}

this.menuItems.Add(name, action);
return this;
}

/// <summary>
/// Adds a menu item into this instance.
/// Adds a menu action into this instance.
/// </summary>
/// <param name="name">Name of menu item.</param>
/// <param name="action">Action to call when menu item is chosen.</param>
Expand All @@ -138,12 +174,38 @@ public ConsoleMenu Add(string name, Action<ConsoleMenu> action)
throw new ArgumentNullException(nameof(action));
}

this.menuItems.Add(name, () => action(this));
this.menuItems.Add(name, (_) =>
{
action(this);
return Task.CompletedTask;
});
return this;
}

/// <summary>
/// Adds an asynchronous menu action into this instance.
/// </summary>
/// <param name="name">Name of menu item.</param>
/// <param name="action">Action to call when menu item is chosen.</param>
/// <returns>This instance with added menu item.</returns>
public ConsoleMenu Add(string name, Func<ConsoleMenu, CancellationToken, Task> action)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}

if (action is null)
{
throw new ArgumentNullException(nameof(action));
}

this.menuItems.Add(name, (cancellationToken) => action(this, cancellationToken));
return this;
}

/// <summary>
/// Adds range of menu items into this instance.
/// Adds range of menu actions into this instance.
/// </summary>
/// <param name="menuItems">Menu items to add.</param>
/// <returns>This instance with added menu items.</returns>
Expand All @@ -162,6 +224,26 @@ public ConsoleMenu AddRange(IEnumerable<Tuple<string, Action>> menuItems)
return this;
}

/// <summary>
/// Adds range of asynchronous menu actions into this instance.
/// </summary>
/// <param name="menuItems">Menu items to add.</param>
/// <returns>This instance with added menu items.</returns>
public ConsoleMenu AddRange(IEnumerable<Tuple<string, Func<CancellationToken, Task>>> menuItems)
{
if (menuItems is null)
{
throw new ArgumentNullException(nameof(menuItems));
}

foreach (var item in menuItems)
{
this.Add(item.Item1, item.Item2);
}

return this;
}

/// <summary>
/// Applies an configuration action on this instance.
/// </summary>
Expand Down Expand Up @@ -206,7 +288,20 @@ public void Show()
this.Console,
new List<string>(this.Titles),
this.config,
this.closeTrigger).Show();
this.closeTrigger).ShowAsync(CancellationToken.None).GetAwaiter().GetResult();
}

/// <summary>
/// Displays the menu in console.
/// </summary>
public async Task ShowAsync(CancellationToken cancellationToken = default)
{
await new ConsoleMenuDisplay(
this.menuItems,
this.Console,
new List<string>(this.Titles),
this.config,
this.closeTrigger).ShowAsync(cancellationToken);
}

/// <summary>
Expand Down
9 changes: 6 additions & 3 deletions ConsoleMenu/ConsoleMenuDisplay.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleTools;

Expand Down Expand Up @@ -30,12 +32,12 @@ public ConsoleMenuDisplay(
this.noSelectorLine = new string(' ', this.config.Selector.Length);
}

public void Show()
public async Task ShowAsync(CancellationToken token)
{
var selectedItem = this.menuItems.GetSeletedItem();
if (selectedItem != null)
{
selectedItem.Action.Invoke();
await selectedItem.Action.Invoke(token);
return;
}

Expand All @@ -48,6 +50,7 @@ public void Show()

while (true)
{
token.ThrowIfCancellationRequested();
do
{
if (this.config.ClearConsole)
Expand Down Expand Up @@ -145,7 +148,7 @@ public void Show()
}
else
{
action();
await action(token).ConfigureAwait(false);
if (this.closeTrigger.IsOn())
{
this.menuItems.UnsetSelectedIndex();
Expand Down
4 changes: 3 additions & 1 deletion ConsoleMenu/ItemsCollection.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleTools;

Expand Down Expand Up @@ -28,7 +30,7 @@ public MenuItem CurrentItem
set => this.menuItems[this.currentItemIndex] = value;
}

public void Add(string name, Action action)
public void Add(string name, Func<CancellationToken, Task> action)
{
this.menuItems.Add(new MenuItem(name, action, this.menuItems.Count));
}
Expand Down
72 changes: 36 additions & 36 deletions ConsoleMenu/MenuConfig.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
#pragma warning disable SA1401 // Fields should be private
#pragma warning disable SA1401 // Fields should be private
using System;
using System.Collections.Generic;

namespace ConsoleTools;

/// <summary>
/// Menu configuration.

/// <summary>
/// Menu configuration.
/// </summary>
public class MenuConfig
{
/// <summary>
/// Initializes a new instance of the <see cref="MenuConfig"/> class.
/// </summary>
public MenuConfig()
{
}

internal MenuConfig(MenuConfig config)
{
this.ArgsPreselectedItemsKey = config.ArgsPreselectedItemsKey;
this.ArgsPreselectedItemsValueSeparator = config.ArgsPreselectedItemsValueSeparator;
this.ClearConsole = config.ClearConsole;
this.EnableBreadcrumb = config.EnableBreadcrumb;
this.EnableFilter = config.EnableFilter;
this.EnableWriteTitle = config.EnableWriteTitle;
this.FilterPrompt = config.FilterPrompt;
this.ItemBackgroundColor = config.ItemBackgroundColor;
this.ItemForegroundColor = config.ItemForegroundColor;
this.SelectedItemBackgroundColor = config.SelectedItemBackgroundColor;
this.SelectedItemForegroundColor = config.SelectedItemForegroundColor;
this.Selector = config.Selector;
this.Title = config.Title;
this.WriteBreadcrumbAction = config.WriteBreadcrumbAction;
this.WriteHeaderAction = config.WriteHeaderAction;
this.WriteItemAction = config.WriteItemAction;
this.WriteTitleAction = config.WriteTitleAction;
}
{
/// <summary>
/// Initializes a new instance of the <see cref="MenuConfig"/> class.
/// </summary>
public MenuConfig()
{
}

internal MenuConfig(MenuConfig config)
{
this.ArgsPreselectedItemsKey = config.ArgsPreselectedItemsKey;
this.ArgsPreselectedItemsValueSeparator = config.ArgsPreselectedItemsValueSeparator;
this.ClearConsole = config.ClearConsole;
this.EnableBreadcrumb = config.EnableBreadcrumb;
this.EnableFilter = config.EnableFilter;
this.EnableWriteTitle = config.EnableWriteTitle;
this.FilterPrompt = config.FilterPrompt;
this.ItemBackgroundColor = config.ItemBackgroundColor;
this.ItemForegroundColor = config.ItemForegroundColor;
this.SelectedItemBackgroundColor = config.SelectedItemBackgroundColor;
this.SelectedItemForegroundColor = config.SelectedItemForegroundColor;
this.Selector = config.Selector;
this.Title = config.Title;
this.WriteBreadcrumbAction = config.WriteBreadcrumbAction;
this.WriteHeaderAction = config.WriteHeaderAction;
this.WriteItemAction = config.WriteItemAction;
this.WriteTitleAction = config.WriteTitleAction;
}

/// <summary>default: Console.ForegroundColor</summary>
public ConsoleColor SelectedItemBackgroundColor = Console.ForegroundColor;
Expand All @@ -47,11 +47,11 @@ internal MenuConfig(MenuConfig config)
public ConsoleColor ItemBackgroundColor = Console.BackgroundColor;

/// <summary>default: Console.ForegroundColor</summary>
public ConsoleColor ItemForegroundColor = Console.ForegroundColor;

public ConsoleColor ItemForegroundColor = Console.ForegroundColor;

/// <summary>default: () => Console.WriteLine("Pick an option:")</summary>
public Action WriteHeaderAction = () => Console.WriteLine("Pick an option:");

public Action WriteHeaderAction = () => Console.WriteLine("Pick an option:");

/// <summary>default: (item) => Console.Write("[{0}] {1}", item.Index, item.Name)</summary>
public Action<MenuItem> WriteItemAction = item => Console.Write("[{0}] {1}", item.Index, item.Name);

Expand Down
6 changes: 4 additions & 2 deletions ConsoleMenu/MenuItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleTools;

Expand All @@ -8,7 +10,7 @@ namespace ConsoleTools;
/// </summary>
public sealed class MenuItem
{
internal MenuItem(string name, Action action, int index)
internal MenuItem(string name, Func<CancellationToken, Task> action, int index)
{
Debug.Assert(index >= 0);

Expand All @@ -25,7 +27,7 @@ internal MenuItem(string name, Action action, int index)
/// <summary>
/// Gets or sets an action of the menu item that will be called when the item is called.
/// </summary>
public Action Action { get; set; }
public Func<CancellationToken, Task> Action { get; set; }

/// <summary>
/// Gets an index of the menu item.
Expand Down
5 changes: 4 additions & 1 deletion ConsoleMenu/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
ConsoleTools.ConsoleMenu
ConsoleTools.ConsoleMenu.Add(string! name, System.Action! action) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.Add(string! name, System.Action<ConsoleTools.ConsoleMenu!>! action) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.Add(string! name, System.Func<ConsoleTools.ConsoleMenu!, System.Threading.CancellationToken, System.Threading.Tasks.Task!>! action) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.Add(string! name, System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task!>! action) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.AddRange(System.Collections.Generic.IEnumerable<System.Tuple<string!, System.Action!>!>! menuItems) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.AddRange(System.Collections.Generic.IEnumerable<System.Tuple<string!, System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task!>!>!>! menuItems) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.CloseMenu() -> void
ConsoleTools.ConsoleMenu.Configure(ConsoleTools.MenuConfig! config) -> ConsoleTools.ConsoleMenu!
ConsoleTools.ConsoleMenu.Configure(System.Action<ConsoleTools.MenuConfig!>! configure) -> ConsoleTools.ConsoleMenu!
Expand Down Expand Up @@ -37,4 +40,4 @@ ConsoleTools.MenuItem.Action.set -> void
ConsoleTools.MenuItem.Index.get -> int
ConsoleTools.MenuItem.Name.get -> string!
ConsoleTools.MenuItem.Name.set -> void
static ConsoleTools.ConsoleMenu.Close() -> void
static ConsoleTools.ConsoleMenu.Close(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task!
Loading

0 comments on commit c73a044

Please # to comment.