1

I have never used Console much beyond outputting text but I know it can do far more.

Is it possible I can print text at the start of the current line, inserting it before whatever might be there?

Console.Write("]Enter command:");
InsertCursorText("(123)");

changes:

]Enter command:

To

(123)]Enter command:

How could I implement InsertCursorText? Subsequent calls to Write or WriteLine should not be affected e.g the cursor should not be left in a weird place.

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • Are you asking about [SetCursorPosition](https://learn.microsoft.com/en-us/dotnet/api/system.console.setcursorposition)? Or what is the goal (what are you trying to achieve)? Without overwriting means you want to shift previously output text or what? – Sinatr Jan 14 '20 at 12:34
  • @Sinatr my question describes a concrete example. I want to insert text at the start of the current line, without knowing what is already there. – Mr. Boy Jan 14 '20 at 12:35
  • `Console.Write("]Enter command"); Console.MoveBufferArea(0, Console.CursorTop, Console.BufferWidth - 5, 1, 5, Console.CursorTop); Console.WriteLine("\r(123)");`. If the console supports [virtual terminal sequences](https://learn.microsoft.com/windows/console/console-virtual-terminal-sequences), that would be are more portable and less screen-oriented approach, but that currently seems to require a P/Invoke to `SetConsoleMode`, which kind of nullifies the portability again a bit... – Jeroen Mostert Jan 14 '20 at 12:37
  • If you want to preserve text, then it somehow have to be [read](https://stackoverflow.com/q/12355378/1997232) or preserved during output. When asking for goal I mean what are you *actially* trying to achieve: e.g. you are trying to prefix all console outputs from some legacy dll. – Sinatr Jan 14 '20 at 12:42
  • The use case here at least is when a worker thread wants to write to console, I want it to insert it rather than mess up whatever input the user is doing. – Mr. Boy Jan 14 '20 at 12:49
  • 1
    The "subsequent calls should not be effected" can be achieved by recording the `Console.CursorLeft` and `Console.CursorTop` positions first and restoring them afterwards with `.SetCursorPosition`. Overall doing inserting by moving the cursor around and shifting buffer contents is rather clumsy, but it's the best you can do with the Win32 console. There is no "insert mode". Worker thread output that shouldn't mess up anything else is hard if not impossible to do -- that's what output files are for. Or else status lines at the bottom, if you have no more than one piece of info to report. – Jeroen Mostert Jan 14 '20 at 13:08
  • @JeroenMostert I hadn't thought about a status line locked to the bottom. Despite coding since DOS I've never really done complex console stuff :) – Mr. Boy Jan 14 '20 at 13:22
  • I would also happily consider inserting an extra line if it were easier but I'm not sure it is from what you said – Mr. Boy Jan 14 '20 at 13:23
  • Not really, no. You still need `MoveBufferArea` to "scroll" the rest of the buffer down a line, then "insert" your line by moving the cursor to the freed up space and writing. It's all quite doable with some well-tested code that you write once and then call, of course, but you're not going to get much help from the primitive operations themselves. – Jeroen Mostert Jan 14 '20 at 13:30
  • I had never realised you couldn't actually read the console contents, I'm sure it's a WinAPI legacy but how weird you can't read the contents of a line, modify this string and write it back! – Mr. Boy Jan 14 '20 at 16:32

1 Answers1

0

You can use this method. It moves the cursor to left and writes the typed value before the staticText. You can also use Console.Write to type text between to static values.

static string ReadAtBegin(string staticText)
{
    string input = "";
    ConsoleKeyInfo key;

    int top = Console.CursorTop;
    int left = Console.CursorLeft;

    Console.Write(staticText);
    do
    {
        key = Console.ReadKey();

        if (key.Key != ConsoleKey.Enter)
        {
            input += key.KeyChar;

            Console.SetCursorPosition(left, top);
            Console.Write(input + staticText); 
        }
        else
        {
            Console.SetCursorPosition(left, top);
            Console.WriteLine(input + staticText);
        }
    } while (key.Key != ConsoleKey.Enter);

    return input;
}

This is how you can use it:

static void Main(string[] args)
{
    //Console.Write("Abc ");
    string command = ReadAtBegin(" Command");
    Console.WriteLine($"Command {command} selected");

    Console.ReadLine();
}
daniel59
  • 906
  • 2
  • 14
  • 31