Code Monkey home page Code Monkey logo

handiercli's Introduction

Nuget GitHub GitHub top language GitHub last commit (branch)

HandierCli

A package that allows for fast creation of command line interface functionalities.


Quick Start

CLI

Console progress

CLI

Creating the CLI

// Create the CLI with a builder pattern, use Intellisense for more methods
CommandLine cli = CommandLine.Factory()   
         // Set what to do when a command is not recognized (not registered), see below registration
        .OnUnrecognized((logger, cmd) => logger.Log($"{cmd} not recognized", ConsoleColor.DarkRed))   
        // Register the default help command, when typing help, all the registered commands and their usage will be displayed
        .RegisterHelpCommand()
        // Set a default global help symbol, when typing the help symbol after a command, its usage will be displayed
        .GlobalHelpSymbol("-h")
        .Build();

await cli.RunAsync();

Commands

Commands are registered with the function cli.RegisterCommand(Command.Builder command). Commands are created using the builder pattern.

Register a command that runs when usefulcmd is typed in the CLI.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .Add(handler =>
    {
        // Useful code goes here
    }));

Command callbacks

Commands work with callback. Callbacks are added to the builder pattern of the Command. They can be added with the Add(...) method or with the AddAsync(...) method.

  • When added in the normal version, commands are executed sequentially in an order determined by the registration order
  • When added in the async way, commands are executed in parallel and awaited

Arguments

The arguments of a Command are defined by its ArgumentsHandler. Omitting the ArgumentsHandler will create a command with no arguments that runs simply when typing it into the CLI.
Guess what, ArgumentsHandler are build with the builder pattern too.
The three types of arguments can of course be mixed.

Mandatory arguments

Mandatory (positional) arguments must be provided and are position sensitive. Their order is defined by the order in which they are registered in the builder pattern.

Mandatory arguments

Register a command that runs when usefulcmd is typed in the CLI with a mandatory argument in first position.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .WithArguments(ArgumentsHandler.Factory()
        .Mandatory("a mandatory argument")
    .Add(handler =>
    {
        string arg = handler.GetPositional(0);
        // Useful code goes here
    }));

Register a command that runs when usefulcmd is typed in the CLI with two mandatory arguments.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .WithArguments(ArgumentsHandler.Factory()
        .Mandatory("a mandatory argument")
        .Mandatory("another mandatory argument")
    .Add(handler =>
    {
        string arg = handler.GetPositional(0);
        string arg1 = handler.GetPositional(1);
        // Useful code goes here
    }));

Optional arguments

Keys are optional arguments. Keys are defined with a key. The key can be used to retrieve the value of the provided argument in the callback.

Register a command that runs when usefulcmd is typed in the CLI with an optional argument.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .WithArguments(ArgumentsHandler.Factory()
        .Keyed("-k", "an optional keyed argument")
    .Add(handler =>
    {
        if(handler.TryGetKeyed("-k", out string val)
        {
            // Key was provided
        }
        else
        {
            // Key was not provided :(
        }
    }));

Flag arguments

Flags are arguments with no value that are useful to detect binary conditions.

Register a command that runs when usefulcmd is typed in the CLI with a flag.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .WithArguments(ArgumentsHandler.Factory()
        .Flag("/f", "a useful flag")
    .Add(handler =>
    {
        if(handler.HasFlag("/k"))
        {
            // Flag was provided
        }
        else
        {
            // Flag was not provided :(
        }
    }));

Arguments domain

It is possible to define domains for the arguments. In case the provided string for the argument does not belong to the domain, the CLI will print an error and display the usage of the command the argument is referred to.

Domains are defined as follows:

  • Value collection: in this case when adding an argument, provide also an array of possible option for the argument value
  • Regular expressions: in this case, a regular expression logic will be run on the argument value

Register a command that runs when usefulcmd is typed in the CLI with two mandatory arguments with two different domains.

cli.Register(Command.Factory("usefulcmd")
    .Description("execute an extremely useful piece of code")
    .WithArguments(ArgumentsHandler.Factory()
        .Mandatory("a mandatory argument", new string[] { "option1", "option2", "option3" })
        .Mandatory("another mandatory argument", ".json$")
    .Add(handler =>
    {
        string arg = handler.GetPositional(0);
        string arg1 = handler.GetPositional(1);
        // Useful code goes here, argument values are assured to be contained into the defined domain
    }));

Console progress

HandierCli also provides some useful constructs to easily manage progress report in the console.

Progress bar

Progress bar is used to report works that are able to report a progress in the interval [0, 1]. The following example shows how to create and use the progress bar:

var bar = ConsoleProgressBar.Factory()
    // Customize the style :D
    .Style('X', ' ', '[', ']')
    // Set the lenght
    .Lenght(50)
    // Start the progress bar rendering as soon as the Build() is called otherwise it can be started when wanted with Start()
    .StartOnBuild()
    // Extremely long but very cool shark animation :D
    .Spinner(8, "||\\________|",
                "|_|\\_______|",
                "|__|\\______|",
                "|___|\\_____|",
                "|____|\\____|",
                "|_____|\\___|",
                "|______|\\__|",
                "|_______|\\_|",
                "|________|\\|",
                "|________/||",
                "|_______/|_|",
                "|______/|__|",
                "|_____/|___|",
                "|____/|____|",
                "|___/|_____|",
                "|__/|______|",
                "|_/|_______|",
                "|/|________|")
    .Build();

// Progress bar implements IDisposable, otherwise dispose it manually with Dispose()
using (bar)
{
    int length = 100;
    for (int i = 0; i < length; i++)
    {
        bar.Report((float)i / (length - 1));
        await Task.Delay(50);
    }
}

Spinner

The spinner is used to show the user that a job is working, whenever a progress value is not available. The following examples show how to use the spinner class:

// Build the spinner
var spinner = ConsoleSpinner.Factory()
    // Set the default info text
    .Info("I am doing a very heavy job X(   ")
    // Set the default completed text
    .Completed("Done :D")
    .Frames(12, "|o        |",
                "| o       |",
                "|  o      |",
                "|   o     |",
                "|    o    |",
                "|     o   |",
                "|      o  |",
                "|       o |",
                "|        o|",
                "|       o |",
                "|      o  |",
                "|     o   |",
                "|    o    |",
                "|   o     |",
                "|  o      |",
                "| o       |")
    .Build();

using (spinner)
{
    spinner.Start();
    await Task.Delay(2000);
    spinner.Completed();

    await Task.Delay(500);

    // Await a dummy task
    await spinner.Await(Task.Run(async () => await Task.Delay(2000)));

    await Task.Delay(500);

    // Spinner can await task with return types
    var res = await spinner.Await(Task.Run(async () =>
    {
        // Spinner supports custom reports, overriding the default info text
        await Task.Delay(1000);
        spinner.Report("Step 1  ");
        await Task.Delay(1000);
        spinner.Report("Step 2  ");
        await Task.Delay(1000);
        return 10;
    }));
}

handiercli's People

Contributors

tratteo avatar

Stargazers

 avatar Nicolò Madia avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.