La .NET CONF 2024 acaba de terminar. Descubre las NOVEDADES de .NET 9 junto a los CAMBIOS que trae C# 13.
Puedes ver el contenido de este vídeo junto con su curso en el modo vídeo (similar a Udemy) si pulsas aquí.

Crea interfaces de usuario intuitivas en la consola con Spectre

Hoy vengo a hablar de una librería que a mi me encanta pero apenas se usa, por lo menos no de forma pública, hablamos de la librería Spectre.

 

 

1 - Qué es la librería Spectre?

 

La librería Spectre nos permite modificar nuestras aplicaciones de consola para que sean algo más interactivas, funcionalidad que se agradece mucho. 

Esta librería permite entre otras cosas tener colores, tablas, árboles, selección de elementos, selección de múltiples elementos, etc. 

 

Toda la información de las funcionalidades la podéis encontrar en la página oficial. 

Enlace a la web: https://spectreconsole.net/quick-start 

example spectre console

En este blog no vamos a ver toda la librería porque para eso, ya tenéis la página web que la verdad esta muy bien y todo está muy claro. 

 

Lo que vamos a hacer es simular un caso de uso de una aplicación real que solemos encontrar en empresas. 

 

 

2 - Implementar Spectre console con C#

 

Como digo, vamos a ver un ejemplo con el que poder ver las funcionalidades que yo le doy más uso. El código está disponible en GitHub

Bien es sabido que una aplicación de consola o un script es el CI/CD de los que tienen aplicaciones de hobby desplegadas. 

 

Eso vamos a ver hoy, vamos a ver diferentes funcionalidades que nos van a permitir trabajar con Spectre. 

Lo primero es crear un nuevo proyecto de consola e incluir los paquetes NuGet:

Spectre.Console
Spectre.Console.Cli

Con esto ya podemos empezar a programar. Pero ojo, no vas a utilizar la clase Console, sino que vas a utilizar AnsiConsole.

 

 

2.1 - Entrada por teclado con Spectre

 

Como punto de entrada vamos a pedir un usuario y contraseña, para así decirle a la app que somos nosotros, este escenario es muy común en cualquier software de este tipo, ya bien sea propio para hobby o en una empresa  para conseguir acceso temporal a ciertas características, que nos pida usuario y contraseña es lo mínimo.

 

Para ello creamos el siguiente código: 

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);
}

En este código podemos ver varias cosas, primero que estamos utilizando AnsiConsole con el método prompt, donde le pedimos al usuario que nos de su nombre de usuario, y una vez el usuario hace enter, vamos a validar el input y si es válido, continuaremos.

Si no es válido, lo que hacemos es mostrar un mensaje, pero puedes darte cuenta que estamos devolviendo ese mensaje con diferente color.

 

En el segundo prompt, tenemos un método muy importante, que es el método Secret, este va a hacer que cuando pongamos texto, en vez de ver las letras que ponemos nosotros, vamos a ver asteriscos, como cuando pones contraseñas en cualquier web. 

 

Aquí, valoraremos la contraseña y simulamos que el usuario está siendo validado y que el servicio nos devuelve un rol para el usuario, que es una funcionalidad muy normal dentro de los sistemas de autenticación. 

 

Este sería el resultado: 

spectre consola entrada de secretos

 

2.2 - Selección de un elemento en una lista en una aplicación de consola

 

Ahora lo normal es que la nos diera múltiples opciones sobre qué queremos hacer, si esto fuera una empresa pues podrías tener varias cosas como desplegar una app en un entorno concreto, hacer login en AWS/Azure para acceder a k8s, mirar el estado de ciertas apps. ETC. 

 

Para ello lo primero será seleccionar un entorno donde queremos desplegar la aplicación:

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}");

 

Y hacemos lo mismo para mostrar una lista de aplicaciones y lo que vamos a hacer es seleccionar una, la cual será desplegada en un entorno:

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}");

 

Este sería el resultado: 

 

2.3 - confirmación en una aplicación de consola

 

Una vez ya tenemos todos los elementos que necesitamos, vamos a pedirle al usuario que confirme (o no) que todo está correcto. 

 

Desafortunadamente no hay un tipo directo que sea confirmación, pero podemos utilizar el prompt para que fuerce al usuario a poner si o no, permitiendo además elegir una por defecto:

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...[/]");
}

Esta es la imagen: 

Si damos intro sin introducir ningún valor, se pondrá el valor por defecto.

 

 

2.4 - Carga

 

Indicarle al usuario que algo está sucediendo es muy importante, no podemos poner texto estático y ya, porque por norma general van a pensar que el programa se ha quedado colgado, ese es el motivo principal por el que los spinners en las webs existen. 

 

En nuestra aplicación de consola, podemos hacer exactamente lo mismo:

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![/]");
        });
}

En este ejemplo en vez de simplemente imprimir desplegando, lo hacemos un un spinner.

Nota: aquí tienes la lista completa de spinners.

 

Con lo que así será mucho más intuitivo para el usuario. 

 

 

 

 

2.5 - Mostrar una tabla en una app de consola en C#

 

Como punto final de las funcionalidades que me parece más importante es el hecho de tener tablas, y con estas tablas tienes control total, puedes tener tablas dentro de tablas, bordes de colores, diferentes tipos de borde, etc.

 

Para un ejemplo sencillo vamos a mostrar una tabla con el resumen de lo que hemos desplegado: 

tablas en aplicaciones de consola

Para conseguir esta tabla, tienes que tener un código como el siguiente: 

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 - Debemos utilizar Spectre? 

 

Por deber, no, pero, la realidad es que utilizar esta librería mejora la experiencia de usuario una barbaridad, si te creas una app únicamente para ti, pues bueno, como veas. Pero si tu app de consola va a ser utilizada por muchos más usuarios yo recomiendo que sí utilices Spectre ya que proporciona una mejora considerable a la clase consola con la que viene C# por defecto. 

 

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 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café