Skip to content

tareqimbasher/konsole

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Konsole

dev

A light-weight System.Console utility wrapper for .NET with lots of useful and common extensions.

Install

Package Manager

Install-Package Konsole

.NET CLI

dotnet add package Konsole

Why?

When writing applications geared for use with the console, I often end up rolling my own helpers for formatting output, getting user input..etc. This library aims to provide a good collection of utilities and extensions to save you from having to do it every time.

Usage

You can use the built-in Konsole class to quickly get up and running:

var console = new Konsole();

It should be a drop-in replacement for System.Console

console.WriteLine("Lorem ipsum");

Defaults

You can change the defaults for an IKonsole instance. Below are the defaults out of the box:

console.Defaults.ForegroundColor = Console.ForegroundColor;
console.Defaults.BackgroundColor = Console.BackgroundColor;

console.Defaults.Info = (console, text) => console.WriteLine(text, ConsoleColor.White);
console.Defaults.Debug = (console, text) => console.WriteLine(text, ConsoleColor.Green);
console.Defaults.Warn = (console, text) => console.WriteLine(text, ConsoleColor.Yellow);
console.Defaults.Error = (console, text) => console.WriteLine(text, ConsoleColor.Red);

console.Defaults.PostWriteAction = (console, text) => { }; // Gets called after every write to the console

Chaining

All methods are chainable.

console.WriteLine("Header")
    .WriteDivider()
    .Write("Status: ").WriteLine("Loaded");

Coloring Output

Write() and WriteLine() have overrides to specify foreground and background colors.

console.Write("Status: ", ConsoleColor.Green).WriteLine("Loaded");

You can set the current foreground and background colors.

console.ForegroundColor = ConsoleColor.Green;
console.BackgroundColor = ConsoleColor.Black;

Use ResetColors() to reset the current foreground and background colors as defined in console.Defaults

console.ResetColors();

Formatting Output

console.Clear();
console.ClearCurrentLine();
console.ReplaceCurrentLine("New text");
console.WriteDivider();
console.List("Vanilla", "Chocolate", "Strawberry");
console.OrderedList("Vanilla", "Chocolate", "Strawberry");
console.WriteLineAlignCenter("Center aligned text");
console.WriteLineAlignRight("Right aligned text");
console.Debug("Debug message");
console.Info("Info message");
console.Warn("Warning message");
console.Error("Error message");

Scoping

Use WithForeColor(), WithBackColor(), and WithColors() to apply colors within a scope without changing the default colors of the IKonsole instance you're using.

console.WriteLine("Default color text")
    .WithForeColor(ConsoleColor.Green).WriteLine("Green text");

console.WriteLine("Still uses default color text");

Prompts

Use the Ask() method to get input from the user. Use the Ask<T> overload to convert user input into the specified data type.

string name = console.Ask("What is your name?");
DateTime birthDate = console.Ask<DateTime>("What is your birth date?");
int power = console.Ask<int>("What is Goku's power level?");
var favs = console.Ask("What are your favorite programming languages:",
    new[] { "C#", "JavaScript", "Python", "COBOL", "Ruby" });

đź’ˇ Create a custom TypeConverter to convert user input to a non-primitive data type. Internally, this method uses TypeConverter.ConvertFromInvariantString(input) to do the conversion.

Use the Confirm() method to get a yes/no answer from the user.

bool hasPets = console.Confirm("Do you have any pets?");
bool proceed = console.Confirm("Do you want to continue?", defaultAnswer: false);

Progress Bars

A single progress bar

var progressBar = console.ProgressBar("Loading file");
progressBar.Update(30); // Set progress to 30%

Multiple progress bars can working simultaneously when added to a group

var group = console.ProgressBarGroup();
var progressBar1 = group.ProgressBar("File 1");
var progressBar2 = group.ProgressBar("File 2");

progressBar1.Update(50);
progressBar2.Update(35);

Extending the Konsole

You can create your own implementation of the IKonsole interface, or inherit from Konsole and override the members you need:

public class MyConsole : Konsole
{
    public override IKonsole Write(string text)
    {
        return base.Write($"My app says: {text}");
    }
}

Code Samples

Checkout the Konsole.Samples project for a working example.

Output Formatting

IKonsole console = new Konsole();

// Sample 1
console.WriteLine("Sample 1: The Basics").WriteDivider();
console.WriteLine("1. Text with default colors.");
console.WithForeColor(ConsoleColor.Cyan).WriteLine("2. Cyan text on the default background");
console.WithBackColor(ConsoleColor.Blue).WriteLine("3. Default text on a blue background");
console.WithForeColor(ConsoleColor.Black).WithBackColor(ConsoleColor.Red).WriteLine("4. Black text on a red background");

console.ForegroundColor = ConsoleColor.Red;
console.BackgroundColor = ConsoleColor.Yellow;

console.WriteLine("5. Text color is now red and background is now yellow");
console.WithForeColor(ConsoleColor.Green).WriteLine("6. Green text with a yellow background");


// Sample 2
console.WriteLine().ResetColors().WriteLine("Sample 2: Ice Cream Menu");
console
    .WithForeColor(ConsoleColor.Green)
    .WriteDivider()
    .WriteLine("Sunny's Ice Cream Shop")
    .WriteDivider()
    .WithForeColor(ConsoleColor.Cyan).WriteLine("These are your options:")
    .WithForeColor(ConsoleColor.White).WriteLine("   1. Vanilla")
    .WithForeColor(ConsoleColor.DarkMagenta).WriteLine("   2. Chocolate")
    .WithForeColor(ConsoleColor.Red).WriteLine("   3. Strawberry");


// Sample 3
console.WriteLine().WriteLine("Sample 3: Lists").WriteDivider();
console.WriteLine("Ice Cream Flavors").List("Vanilla", "Chocolate", "Strawberry");
console.WriteLine("Toppings").OrderedList("Sprinkles", "Strawberries", "Syrup");


// Sample 4
console.WriteLine().WriteLine("Sample 4: Text Alignment").WriteDivider();
console.WriteLine("This text is left aligned");
console.WriteLineAlignCenter("This text is center aligned");
console.WriteLineAlignRight("This text is right aligned");
console.Write("Left aligned").WriteLineAlignRight("Right aligned");

This results in the following output:

preview-output-formatting

Prompts

string name = console.Ask("What is your name?");
DateTime birthDate = console.Ask<DateTime>("What is your birth date?");
bool hasPets = console.Confirm("Do you have any pets?");
int power = console.Ask<int>("What is Goku's power level?");
var favs = console.Ask("What are your favorite programming languages:", new[] { "C#", "JavaScript", "Python", "COBOL", "Ruby" });

console
    .WithForeColor(ConsoleColor.Cyan).WriteLine("\nProfile").WriteDivider().ResetColors()
    .WriteLine($"{"Name:",-20} {name}")
    .WriteLine($"{"Age:",-20} {Math.Floor((DateTime.Today - birthDate.Date).TotalDays / 365)}")
    .WriteLine($"{"Pets:",-20} {(hasPets ? "Yes" : "No")}")
    .WriteLine($"{"DBZ Fan?:",-20} {(power > 9000 ? "Yep!" : "No :(")}")
    .WriteLine("Favorite Languages:").List(favs);

This results in the following output:

preview-prompts

Progress Bars

Single Progress Bar
var progressBar = console.ProgressBar("Loading file");

for (int i = 1; i <= 10; i++)
{
    progressBar.Update(i * 10);
}

console.Info("Loading complete.");
Progress Bar Group

Multiple progress bars running asynchronously.

private void Process()
{
    console.WriteLine("\nProgress Bars").WriteDivider();
    var tasks = new List<Task>();

    var group = console.WithForeColor(ConsoleColor.DarkCyan).ProgressBarGroup();
            
    foreach (var i in Enumerable.Range(1, 5))
    {
        var progressBar = group.ProgressBar($"Async Operation {i}");
        tasks.Add(new Task(() => Work(progressBar, 50 + (i * 50) + (i % 2 * 70))));
    }

    tasks.ForEach(t => t.Start());
    Task.WaitAll(tasks.ToArray());

    console.WriteLine().Info("Loading is complete!").WriteLine();
}


private void Work(ProgressBar progressBar, int progressDuration)
{
    var text = progressBar.Text;
    for (int i = 0; i < 10; i++)
    {
        progressBar.Update((i + 1) * 10, $"{text} | Item {i + 1} of 10");
        Thread.Sleep(progressDuration);
    };
}

This results in the following output:

preview-progressbars