Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listen on ESC while reading Console line

I want to read an users input into a string while still reacting on ESC press at any time, but without defining a system wide hotkey.

So when the user types e. g. "Test Name" but instead of confirming with ENTER presses ESC he should be led back into main menu.

Console.Write("Enter name: ")
if (Console.ReadLine().Contains(ConsoleKey.Escape.ToString()))
{
    goto MainMenu;
}
return Console.ReadLine();

Thats the simplest way I could think of, but since ESC is not seen by Console.ReadLine() it is not working.

Found a rather complex way to react on ESC when pressed before starting to enter text here, but I want it to work at any time.

like image 961
AstronAUT Avatar asked Aug 13 '15 19:08

AstronAUT


People also ask

What is the use of console readkey ()?

Console.ReadKey () is a blocking function, it stops the execution of the program and waits for a key press, but thanks to checking Console.KeyAvailable first, the while loop is not blocked, but running until the Esc is pressed. Show activity on this post.

How do I get console to read key without blocking it?

Use Console.KeyAvailable so that you only call ReadKey when you know it won't block: Console.WriteLine ("Press ESC to stop"); do { while (! Console.KeyAvailable) { // Do something } } while (Console.ReadKey (true).Key != ConsoleKey.Escape);

Why should I not use ESC command in a list?

Well, one reason not to is that it can be used in some shortcut sequences. I don't know exactly what they are called, which is why I landed here in search of a list of such sequences. One that I use a lot is Esc. which inserts the last parameter of the previous command at the current cursor position.

How to read console input with Node JS?

Read console input with Node.js 1 Interacting with the terminal. We will use process.stdin to read data that was typed in the terminal. We will use... 2 Keeping things organized. Since Node.js is asynchronous, things are going to get a little weird. When you ask the user... 3 Putting it all together. More ...


2 Answers

You will probably have to forego the use of ReadLine and roll your own using ReadKey:

static void Main(string[] args)
{
    Console.Clear();
    Console.Write("Enter your name and press ENTER.  (ESC to cancel): ");
    string name = readLineWithCancel();

    Console.WriteLine("\r\n{0}", name == null ? "Cancelled" : name);

    Console.ReadLine();
}

//Returns null if ESC key pressed during input.
private static string readLineWithCancel()
{
    string result = null;

    StringBuilder buffer = new StringBuilder();

    //The key is read passing true for the intercept argument to prevent
    //any characters from displaying when the Escape key is pressed.
    ConsoleKeyInfo info = Console.ReadKey(true);
    while (info.Key != ConsoleKey.Enter && info.Key != ConsoleKey.Escape)
    {
        Console.Write(info.KeyChar);
        buffer.Append(info.KeyChar);
        info = Console.ReadKey(true);
    } 

    if (info.Key == ConsoleKey.Enter)
    {
        result = buffer.ToString();
    }

    return result;
}

This code is not complete and may require work to make it robust, but it should give you some ideas.

like image 103
Chris Dunaway Avatar answered Oct 06 '22 01:10

Chris Dunaway


A bit improved version of Chris Dunaway's one :

    public static bool CancelableReadLine(out string value)
    {
        value = string.Empty;
        var buffer = new StringBuilder();
        var key = Console.ReadKey(true);
        while (key.Key != ConsoleKey.Enter && key.Key != ConsoleKey.Escape)
        {
            if (key.Key == ConsoleKey.Backspace && Console.CursorLeft > 0)
            {
                var cli = --Console.CursorLeft;
                buffer.Remove(cli, 1);
                Console.CursorLeft = 0;
                Console.Write(new String(Enumerable.Range(0, buffer.Length + 1).Select(o => ' ').ToArray()));
                Console.CursorLeft = 0;
                Console.Write(buffer.ToString());
                Console.CursorLeft = cli;
                key = Console.ReadKey(true);
            }
            else if (Char.IsLetterOrDigit(key.KeyChar) || Char.IsWhiteSpace(key.KeyChar))
            {
                var cli = Console.CursorLeft;
                buffer.Insert(cli, key.KeyChar);
                Console.CursorLeft = 0;
                Console.Write(buffer.ToString());
                Console.CursorLeft = cli + 1;
                key = Console.ReadKey(true);
            }
            else if (key.Key == ConsoleKey.LeftArrow && Console.CursorLeft > 0)
            {
                Console.CursorLeft--;
                key = Console.ReadKey(true);
            }
            else if (key.Key == ConsoleKey.RightArrow && Console.CursorLeft < buffer.Length)
            {
                Console.CursorLeft++;
                key = Console.ReadKey(true);
            }
            else
            {
                key = Console.ReadKey(true);
            }
        }

        if (key.Key == ConsoleKey.Enter)
        {
            Console.WriteLine();
            value = buffer.ToString();
            return true;
        }
        return false;
    }
}

I didn't test it much, but at least works for me.

like image 35
oleg wx Avatar answered Oct 05 '22 23:10

oleg wx