1

I want to print some dynamic status text message starting from the top left corner of console, leaving the left area blank on linux(something like watch -n 1 pwd). How can I do it using C or C++?

konchy
  • 573
  • 5
  • 16
  • 2
    Look for something like ncurses maybe. – πάντα ῥεῖ Aug 03 '23 at 11:14
  • Use the termcap database to find the terminal's control sequences for cursor positioning, or use a Curses library (such as ncurses) which can abstract all that behind higher-level concepts such as windows and widgets. – Toby Speight Aug 03 '23 at 11:57
  • 1
    Did you read how `watch` works? Since you have an example of what you want to do, it's likely a good idea to read its sources to find how to do it yourself. – Toby Speight Aug 03 '23 at 11:58

2 Answers2

2

There is a good chance that your terminal supports ANSI escape codes. These provide a way of altering terminal output properties, controlling cursors, etc.

In the program below ESC is defined to be an escape code prefix, CLS is defined to be the control sequence that clears a screen, and HOME is defined to be the control sequence that moves the cursor to its home position at the top left of the console window. Printing these codes to a terminal window should have the desired effect in terminal emulators that support ANSI escape codes.

Note that this is not supported by the C language, but is widely supported by terminal emulators.

#include <stdio.h>

/* ANSI Escape Sequences */
#define ESC  "\x1B"
#define CLS  ESC"[2J"
#define HOME  ESC"[H"

void clear_to_top(void) {
    printf(CLS);
    printf(HOME);
    fflush(stdout);
}

int main(void) {
    clear_to_top();
    puts("Starting from the top....");
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
1

You can clear the terminal screen and set the cursor to the top left corner by printing a '\f' byte to the terminal. eg: putchar('\f'), but remember that stdout is line buffered by default so you may need to flush the buffered output with fflush(stdout).

'\f' stands for form feed, a command used to eject the page from the printer, and is interpreted by terminals as a clear screen command.

The byte value in ASCII is 12, also referred to as Ctrl-L.

Some terminals handle it this way, but it seems neither the OP's ConEmu, nor macOS' Terminal or iTerm2, nor most X-Windows terminals... So this is definitely not a solution to the problem.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I'm using ConEmu and when ssh into my linux server, print `'\f'` gives me a [female sign](https://stackoverflow.com/questions/4334370/escape-sequence-f-form-feed-what-exactly-is-it)... – konchy Aug 04 '23 at 02:27
  • Printing `'\f'` to the terminal and calling `fflush` did not seem to have any effect for me in either Konsole or Xfce Terminal on Debian Linux. – ad absurdum Aug 04 '23 at 14:06
  • @adabsurdum: I guess I was out of line! FF is handled like LF, it merely causes a line to be skipped. I even implemented this in the Quick Emacs shell buffer which acts like an ANSI terminal. Shame on me. I shall delete this answer tonight. – chqrlie Aug 04 '23 at 17:39
  • @chqrlie -- I always enjoy reading your answers, and I usually learn some things. When I saw your proposed `'\f'` solution I hadn't heard of it, so I tried it unsuccessfully. That is what inspired me to write my answer since I knew it was possible with ANSI escape codes (which of course isn't portable, either). I only tried your solution with two terminal emulators, but I suspected that there were some terminals in which `'\f'` would work. – ad absurdum Aug 04 '23 at 17:50
  • @adabsurdum: I honestly cannot remember where I got this idea. It is difficult to test remotely from my macbook in a crowded ferry terminal... It seems logical, but I don't know where it works. – chqrlie Aug 04 '23 at 17:58