Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify the previous line of console text?

I'd like to achieve something like this:

Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OK

I displayed 3 line of text, each one related with a thread which can end sooner or later. But if the second one complete later than the third one, I'll get something like this:

Time consuming operation...OK
Another time consuming operation...
And another one, but it completed, so...OKOK

Which is of course unacceptable. I know how to go back in current line, but is there a way to go UP? I'd swear I've seen it somewhere, though it could be a Linux console :)

Forget it. See Far File Manager! It works in Windows console, it works even in PowerShell! How to make something like this? And the coolest part is it restores console state after exiting. So maybe I should ask - how to access console buffer directly? I assume I'll need some native code to do the trick, but maybe there's another way? I thought of clearing console with each update, but this seems like overkill. Or maybe it isn't? Will it blink?

like image 336
Harry Avatar asked May 29 '12 17:05

Harry


People also ask

How do you write on the same line in console?

Write() only wrote all in the (" ") and keep you on the same line.

Which function is used to print line of text on the console?

println(): println() method in Java is also used to display a text on the console. This text is passed as the parameter to this method in the form of String. This method prints the text on the console and the cursor remains at the start of the next line at the console. The next printing takes place from next line.


3 Answers

You can move cursor wherever you want: Console.SetCursorPosition or use Console.CursorTop.

Console.SetCursorPosition(0, Console.CursorTop -1);
Console.WriteLine("Over previous line!!!");
like image 196
Alexei Levenkov Avatar answered Oct 16 '22 14:10

Alexei Levenkov


Use a carriage return. This sample prints a single line, overwriting what was there before.

  Console.WriteLine();
  for (int i = 0; i <= 100; i++)
  {
    System.Threading.Thread.Sleep(10);
    Console.Write("\x000DProgress: " + i);
  }

This works as long as all your strings are less than 80 columns (or whatever your terminal buffer is set to).

like image 42
agent-j Avatar answered Oct 16 '22 14:10

agent-j


Note: the following answer was originally edited into the question by the OP.


Here's complete solution with demo:

using System;
using System.Collections.Generic;
using System.Threading;

namespace PowerConsole {

    internal class Containers {

        internal struct Container {
            public int Id;
            public int X;
            public int Y;
            public string Content;
        }

        public static List<Container> Items = new List<Container>();

        private static int Identity = 0;

        public static int Add(string text) {
            var c = new Container();
            c.Id = Identity++;
            c.X = Console.CursorLeft;
            c.Y = Console.CursorTop;
            c.Content = text;
            Console.Write(text);
            Items.Add(c);
            return c.Id;
        }

        public static void Remove(int id) {
            Items.RemoveAt(id);
        }

        public static void Replace(int id, string text) {
            int x = Console.CursorLeft, y = Console.CursorTop;
            Container c = Items[id];
            Console.MoveBufferArea(
                c.X + c.Content.Length, c.Y,
                Console.BufferWidth - c.X - text.Length, 1,
                c.X + text.Length, c.Y
            );
            Console.CursorLeft = c.X;
            Console.CursorTop = c.Y;
            Console.Write(text);
            c.Content = text;
            Console.CursorLeft = x;
            Console.CursorTop = y;
        }

        public static void Clear() {
            Items.Clear();
            Identity = 0;
        }
    }

    internal class Program {
        private static List<Thread> Threads = new List<Thread>();

        private static void Main(string[] args) {
            Console.WriteLine("So we have some threads:\r\n");
            int i, id;
            Random r = new Random();
            for (i = 0; i < 10; i++) {
                Console.Write("Starting thread " + i + "...[");
                id = Containers.Add("?");
                Console.WriteLine("]");
                Thread t = new Thread((object data) => {
                    Thread.Sleep(r.Next(5000) + 100);
                    Console.ForegroundColor = ConsoleColor.Green;
                    Containers.Replace((int)data, "DONE");
                    Console.ResetColor();
                });
                Threads.Add(t);
            }
            Console.WriteLine("\n\"But will it blend?\"...");
            Console.ReadKey(true);
            i = 0;
            Threads.ForEach(t => t.Start(i++));
            Threads.ForEach(t => t.Join());
            Console.WriteLine("\r\nVoila.");
            Console.ReadKey(true);
        }
    }
}
like image 1
user247702 Avatar answered Oct 16 '22 14:10

user247702