A Better Keyboard Input Experience For .NET Console Apps

Toni Solarin-Sodara
4 min readMar 19, 2018

--

For a long time, console/cli apps have always been a great way to get yourself introduced to .NET (or programming languages/frameworks in general). In recent times there’s been a huge focus on GUI apps and Web apps because they offer an array of rich input interfaces and are generally more user friendly.

However, when it comes to operating system utilities, developer tools and more hardcore users, console apps are still the way to go. Bash and other unix shells have always been the poster children for being able to provide rich text input from within a terminal, with features like keyboard shortcuts to navigate around the input text, tab completions and non-rendering password input. What these unix shells have in common is that they all use GNU ReadLine and getpass under the hood to make all that keyboard input magic happen. The default behaviour you get with the standard Console.ReadLine() in C# and .NET in comparison is sadly, still way below par.

ReadLine is a simple .NET library (distributed via NuGet) that aims to bridge this gap and allow you offer a rich keyboard input experience to users of your .NET console app. It’s a pure C# implementation of both GNU ReadLine and getpass and works as a drop in replacement for Console.ReadLine() , with the default behaviour requiring no configuration at all. It comes with support for majority of the shortcuts that bash supports as well as an easy to configure autocompletion interface.

Text Input

using System;
class Program
{
public static void Main(string[] args)
{
string input = ReadLine.Read();
Console.WriteLine(input);
}
}

From the above sample you simply call ReadLine.Read() where you would’ve originally called Console.ReadLine() and that’s it! When the user is prompted for input they’d be able backspace their text, jump to various parts of the text using shortcuts and even navigate through their input history since the start of your console app’s process!

Password Input

ReadLine also provides the ability to request for sensitive input from your users. When in this mode, the text the user provides isn’t rendered to the screen.

using System;
class Program
{
public static void Main(string[] args)
{
string input = ReadLine.ReadPassword();
Console.WriteLine(input);
}
}

Autocomplete

This is perhaps the only part of ReadLine that needs some extra work to get it working. ReadLine provides a simple interface to allow you configure autocompletion rules to your taste.

class AutoCompletionHandler : IAutoCompleteHandler
{
public char[] Separators { get; set; } = new char[] { ' ' };

public string[] GetSuggestions(string text, int index)
{
var suggestions = new string[] { "clone", "stash" };
return suggestions;
}
}

ReadLine.AutoCompletionHandler = new AutoCompletionHandler();

The first thing you have to do is create a concrete implementation of the IAutoCompleteHandler interface. There a only two members you have to concern yourself with, the first is the Separators property which is simply an array of characters you’d like to use as completion markers (more on this soon) and the second is the GetSuggestions method that takes in some information about the current state of the input text and returns a list of possible suggestions that ReadLine cycles through as the user continually hits he tab key.

From the sample code above, we have a single space separator and a GetSuggestions method that just returns a fixed array (your implementation can do whatever fancy thing you need it to do to return appropriate suggestions). In this case, let’s assume the user enters git (note the space) and hits the tab key. ReadLine will call your GetSuggestions method and pass in the full input as the text argument and 3 as the index argument (because that’s the index the space separator appears in text). The first item of the returned string array will be displayed (e.g. git clone) and subsequents hits of the tab key will cyclically loop through the array, displaying suggestions appropriately, until the user is satisfied with the selection and moves on.

Wrapping it all up!

ReadLine is one of those libraries that aims to help you achieve so much with so little effort. It tries to get out of your way as much as possible by conforming to the style you’re already used to but still give room for customization with extra features like optional input prompts, history toggle and even default inputs so your users can just hit enter and be on their merry way!

Let me know what you think in the comments!

--

--

Toni Solarin-Sodara

Microsoft MVP | .NET Contributor | C# Enthusiast | Mildly Uninteresting