Search code examples
c#consolenewlineeditconsole.readline

C# Console - How to ReadLine() without a new line? ( or undo a \n or a vertical \b)


I want to know if it is possible to get back to the last line when I'm at the beginning of the next line? (in C# Console, of course)

I mean Console.WriteLine() cause going to the next line and I want to stay in my line even after pressing enter. (And I think there isn't another way to ReadLine without going to the next line , is there?)

I found that Console.SetCursorPosition() can be useful, like below:

        int x, y;
        Console.WriteLine("Please enter the point's coordinates in this form (x,y):");
        Console.Write("(");
        x = Convert.ToInt32(Console.ReadLine());
        Console.SetCursorPosition(x.ToString().Length + 1, Console.CursorTop - 1);
        Console.Write(",");
        y = Convert.ToInt32(Console.ReadLine());
        Console.SetCursorPosition(x.ToString().Length + y.ToString().Length + 2, Console.CursorTop - 1);
        Console.WriteLine(")");

This seems to work fine but when I try to change Console.Write("("); into something like Console.Write("Point A=("), I need to change the the Console.SetCursorPosition() arguments every time.

Also it would be very helpful if I could move the cursor to the last character (except spaces) in the console buffer.(I think it would be easy if I could copy a specific line from console into a string.)

Thanks in advance.


Solution

  • How about using a simple helper class that fits your specific use case and helps make your code logic a bit more readable.

    public class Prompt
    {
        public struct CursorPosition
        {
            public int CursorLeft;
            public int CursorTop;
        }
    
        private CursorPosition _savedPosition;
    
        public Prompt Write(string prompt)
        {
            Console.Write(prompt);
            return this;
        }
    
        public Prompt Write(string promptFormat, params object[] args)
        {
            return Write(string.Format(promptFormat, args));
        }
    
        public Prompt WriteLine(string prompt)
        {
            Write(prompt);
            Console.WriteLine();
            return this;
        }
    
        public Prompt WriteLine(string promptFormat, params object[] args)
        {
            return WriteLine(string.Format(promptFormat, args));
        }
    
        public string ReadLine(bool advanceCursorOnSameLine = false, bool eraseLine = false)
        {
            if (advanceCursorOnSameLine || eraseLine)
            {
                SavePosition();
                if (eraseLine)
                    WriteLine(new string(' ', Console.WindowWidth - _savedPosition.CursorLeft)).RestorePosition();
            }
            var input = Console.ReadLine();
            if (advanceCursorOnSameLine)
                RestorePosition(input.Length);
            return input;
        }
    
        public Prompt SavePosition()
        {
            _savedPosition = GetCursorPosition();
            return this;
        }
    
        public CursorPosition GetCursorPosition()
        {
            return new CursorPosition {
                CursorLeft = Console.CursorLeft,
                CursorTop = Console.CursorTop
            };
        }
    
        public Prompt RestorePosition(CursorPosition position, int deltaLeft = 0, int deltaTop = 0)
        {
            var left = Math.Min(Console.BufferWidth - 1, Math.Max(0, position.CursorLeft + deltaLeft));
            var right = Math.Min(Console.BufferHeight - 1, Math.Max(0, position.CursorTop + deltaTop));
            Console.SetCursorPosition(left, right);
            return this;
        }
    
        public Prompt RestorePosition(int deltaLeft = 0, int deltaTop = 0)
        {
            return RestorePosition(_savedPosition, deltaLeft, deltaTop);
        }
    }
    

    Which can then be used like this:

    class Program
    {
        public static void Main(params string[] args)
        {
            int x, y;
            var prompt = new Prompt();
            prompt.WriteLine("Please enter the point's coordinates in this form (x,y):");
            var savedPos = prompt.GetCursorPosition();
            while (true)
            {
                x = Convert.ToInt32(prompt.Write("(").ReadLine(true, true));
                y = Convert.ToInt32(prompt.Write(",").ReadLine(true));
                prompt.WriteLine(")");
                // do something with x and y
    
                var again = prompt.Write("More (Y):").ReadLine(true, true);
                if (!again.StartsWith("Y", StringComparison.OrdinalIgnoreCase))
                    break;
                prompt.RestorePosition(savedPos);
            }
        }
    }