Create Intuitive User Interfaces in the Console with Spectre

Today I want to talk about a library that I absolutely love, but is rarely used, at least not publicly, we're talking about the Spectre library.

 

 

1 - What is the Spectre library?

 

The Spectre library allows us to modify our console applications to make them more interactive, a functionality that is greatly appreciated. 

This library allows, among other things, colors, tables, trees, single and multiple item selections, etc.

 

You can find all the information about its features on the official page: 

Website link: https://spectreconsole.net/quick-start 

example spectre console

In this blog, we are not going to review the entire library because the website does a great job explaining everything clearly. 

 

Instead, we are going to simulate a use case for a real application you might find in companies. 

 

 

2 - Implementing Spectre Console with C#

 

As I said, let’s look at an example where you can see the features I use the most. The code is available on GitHub.

As is well known, a console application or script is the go-to CI/CD solution for those deploying hobby apps. 

 

Today, we’re going to see several features that will help us work with Spectre. 

First, create a new console project and include the following NuGet packages:

Spectre.Console
Spectre.Console.Cli

With this, you can start coding. But pay attention, you won’t be using the Console class, but instead will use AnsiConsole.

 

 

2.1 - Keyboard Input with Spectre

 

As an entry point, we'll ask for a username and password, so the app knows it's us. This scenario is very common for any type of software like this, whether it's a hobby project or for a company, to get temporary access to certain features, username and password at a minimum.

 

For that, we create the following code: 

public record UserInfo(string Username, string Role);


UserInfo LoginUser()
{
    string username = AnsiConsole.Prompt(new TextPrompt<string>("Username:")
        .Validate(username =>
        {
            if (!username.Equals("netmentor", StringComparison.OrdinalIgnoreCase))
            {
                return ValidationResult.Error("[red]user not found[/]");
            }

            return ValidationResult.Success();
        }));

    string role = string.Empty;
    AnsiConsole.Prompt(new TextPrompt<string>("Password:")
        .Secret()
        .Validate(password =>
        {
            if (!password.Equals("pass", StringComparison.OrdinalIgnoreCase))
            {
                return ValidationResult.Error("[orange1]Wrong password[/], try again");
            }

            // logic to validate user and password
            role = "invented-role-1";
            return ValidationResult.Success();
        }));

    return new UserInfo(username, role);
}

In this code, you can see several things. First, we're using AnsiConsole with the prompt method, where we ask the user for their username. Once the user hits enter, we validate the input, and if valid, continue.

If it's not valid, we show a message, and you can see that we're returning this message in a different color.

 

In the second prompt, we have a very important method, Secret, which ensures that instead of displaying the characters entered, we see asterisks, just like entering passwords on a website. 

 

Here, we evaluate the password, simulate user validation, and that the service returns a role for the user, a pretty normal feature in authentication systems. 

 

This is what the result looks like: 

spectre consola entrada de secretos

 

2.2 - Selecting an Item from a List in a Console App

 

Now, the usual thing is that we’d get several options on what we want to do. In a business environment, that could be things like deploying an app to a specific environment, logging into AWS/Azure to access k8s, checking the state of some apps, etc. 

 

First, we'll select the environment where we want to deploy the application:

public enum Environment
{
    CodeSpaces,
    Development,
    Staging,
    Production
}

Environment environment = AnsiConsole.Prompt(
    new SelectionPrompt<Environment>()
        .Title("in which environment?")
        .AddChoices(
            Environment.CodeSpaces,
            Environment.Development,
            Environment.Staging,
            Environment.Production));

AnsiConsole.MarkupLine($"Selected Environment:[blue] >[/] {environment}");

 

And we’ll do the same to show a list of applications and select one, which will be deployed in the selected environment:

string application = AnsiConsole.Prompt(
    new SelectionPrompt<string>()
        .Title("Which application?")
        .AddChoices(
            "Test app 1",
            "test app 2",
            "test app 3"));

AnsiConsole.Markup($"[blue]Application: >[/] {application}");

 

This is what the result looks like: 

 

2.3 - Confirmation in a Console App

 

Once we have all the necessary elements, we’ll ask the user to confirm (or not) that everything is correct. 

 

Unfortunately, there isn't a specific confirmation type, but we can use the prompt to force the user to enter yes or no, also allowing a default selection:

string shouldDeployString = AnsiConsole.Prompt(new TextPrompt<string>($"deploy {application} in {environment} [[y/n]] (y):")
    .DefaultValue("y")
    .AddChoice("y")
    .AddChoice("n")
    .AllowEmpty());

if (shouldDeployString.Equals("y", StringComparison.OrdinalIgnoreCase))
{
    AnsiConsole.MarkupLine($"[yellow]deploying...[/]");
}

This is the image: 

If you hit enter without entering a value, the default will be used.

 

 

2.4 - Progress Indicator

 

Letting the user know something is happening is very important. We can’t just show a static message because, usually, people will think the program is stuck. That’s the main reason spinners exist on websites. 

 

In our console application, we can do exactly the same:

if (shouldDeployString.Equals("y", StringComparison.OrdinalIgnoreCase))
{
 
    AnsiConsole.Status()
        .Spinner(Spinner.Known.Dots)
        .Start("[yellow]Deploying... [/]", ctx => {
            //This simulates the deployment process
            Thread.Sleep(5000);
            
            AnsiConsole.MarkupLine("[green]deployment completed![/]");
        });
}

In this example, instead of just printing "deploying" we do it with a spinner.

Note: here’s the complete list of spinners.

 

With this, the experience will be much more intuitive for the user. 

 

 

 

 

2.5 - Displaying a Table in a Console App in C#

 

As a final feature that I find most important is the ability to have tables, and with these tables you have full control: you can have nested tables, colored borders, different border types, etc.

 

For a simple example, we’ll display a table summarizing what we've deployed: 

tablas en aplicaciones de consola

To get this table, you need code like the following: 

if (shouldDeployString.Equals("y", StringComparison.OrdinalIgnoreCase))
{
 
    ...

    Table table = new Table();
    table.Title = new TableTitle("Deployment details");
    table.AddColumn(new TableColumn("User"));
    table.AddColumn(new TableColumn("Environment"));
    table.AddColumn(new TableColumn("Application"));
    table.AddRow([
        user.Username,
        environment.ToString(),
        application
    ]);
    
    AnsiConsole.Write(table);
}

 

 

3 - Should We Use Spectre?

 

Strictly speaking, you don't have to, but the reality is that using this library drastically improves the user experience. If you’re building an app only for yourself, it’s up to you. But if your console app will be used by many more users, I strongly recommend you use Spectre, as it provides a considerable upgrade over the default C# console class. 

 

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café