Stuart Lang 397b742bec
Add selection orompt Search (#1289)
* Add selection prompt search as you type

* Fix small bug

* Simplify

* Simplify

* Remove spacebar as a selection prompt submit key

* Trigger CI

* Update src/Spectre.Console/Prompts/SelectionPrompt.cs

Co-authored-by: Martin Costello <martin@martincostello.com>

* Simplifty Mask method

* Handle multi-selection prompt better

* Update API naming

* Address feedback

* Add some tests

* Remove whitespace

* Improve search and highlighting

* Add test case for previous issue

* Add extra test case

* Make prompt searchable

---------

Co-authored-by: Martin Costello <martin@martincostello.com>
Co-authored-by: Patrik Svensson <patrik@patriksvensson.se>
2024-02-25 12:57:27 +01:00

182 lines
6.4 KiB
C#

using Spectre.Console;
namespace Prompt
{
public static class Program
{
public static void Main(string[] args)
{
// Check if we can accept key strokes
if (!AnsiConsole.Profile.Capabilities.Interactive)
{
AnsiConsole.MarkupLine("[red]Environment does not support interaction.[/]");
return;
}
// Confirmation
if (!AskConfirmation())
{
return;
}
// Ask the user for some different things
WriteDivider("Strings");
var name = AskName();
WriteDivider("Lists");
var fruit = AskFruit();
WriteDivider("Choices");
var sport = AskSport();
WriteDivider("Integers");
var age = AskAge();
WriteDivider("Secrets");
var password = AskPassword();
WriteDivider("Mask");
var mask = AskPasswordWithCustomMask();
WriteDivider("Null Mask");
var nullMask = AskPasswordWithNullMask();
WriteDivider("Optional");
var color = AskColor();
// Summary
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftJustified());
AnsiConsole.Write(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]")
.RoundedBorder()
.BorderColor(Color.Grey)
.AddRow("[grey]Name[/]", name)
.AddRow("[grey]Favorite fruit[/]", fruit)
.AddRow("[grey]Favorite sport[/]", sport)
.AddRow("[grey]Age[/]", age.ToString())
.AddRow("[grey]Password[/]", password)
.AddRow("[grey]Mask[/]", mask)
.AddRow("[grey]Null Mask[/]", nullMask)
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
}
private static void WriteDivider(string text)
{
AnsiConsole.WriteLine();
AnsiConsole.Write(new Rule($"[yellow]{text}[/]").RuleStyle("grey").LeftJustified());
}
public static bool AskConfirmation()
{
if (!AnsiConsole.Confirm("Run prompt example?"))
{
AnsiConsole.MarkupLine("Ok... :(");
return false;
}
return true;
}
public static string AskName()
{
var name = AnsiConsole.Ask<string>("What's your [green]name[/]?");
return name;
}
public static string AskFruit()
{
var favorites = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.PageSize(10)
.Title("What are your [green]favorite fruits[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
.AddChoiceGroup("Berries", new[]
{
"Blackcurrant", "Blueberry", "Cloudberry",
"Elderberry", "Honeyberry", "Mulberry"
})
.AddChoices(new[]
{
"Apple", "Apricot", "Avocado", "Banana",
"Cherry", "Cocunut", "Date", "Dragonfruit", "Durian",
"Egg plant", "Fig", "Grape", "Guava",
"Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo",
"Lychee", "Melon", "Nectarine", "Orange", "Olive"
}));
var fruit = favorites.Count == 1 ? favorites[0] : null;
if (string.IsNullOrWhiteSpace(fruit))
{
fruit = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.EnableSearch()
.Title("Ok, but if you could only choose [green]one[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.AddChoices(favorites));
}
AnsiConsole.MarkupLine("You selected: [yellow]{0}[/]", fruit);
return fruit;
}
public static string AskSport()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("What's your [green]favorite sport[/]?")
.InvalidChoiceMessage("[red]That's not a sport![/]")
.DefaultValue("Sport?")
.AddChoice("Soccer")
.AddChoice("Hockey")
.AddChoice("Basketball"));
}
public static int AskAge()
{
return AnsiConsole.Prompt(
new TextPrompt<int>("How [green]old[/] are you?")
.PromptStyle("green")
.ValidationErrorMessage("[red]That's not a valid age[/]")
.Validate(age =>
{
return age switch
{
<= 0 => ValidationResult.Error("[red]You must at least be 1 years old[/]"),
>= 123 => ValidationResult.Error("[red]You must be younger than the oldest person alive[/]"),
_ => ValidationResult.Success(),
};
}));
}
public static string AskPassword()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret());
}
public static string AskPasswordWithCustomMask()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret('-'));
}
public static string AskPasswordWithNullMask()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("Enter [green]password[/]?")
.PromptStyle("red")
.Secret(null));
}
public static string AskColor()
{
return AnsiConsole.Prompt(
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
.AllowEmpty());
}
}
}