Erasing terminal output on Linux

I wrote a command line program that will have a status bar, like wget.

The main problem I encountered: how to delete what I have already sent to stdout / stderr?

I had an idea: use backspace char '\ b' and delete the output I sent. Is this the best way? Is this the only way? Is there a better way?

PS: I do not want to use anything like ncurses. Simple old C please.

thanks


EDIT:

Can I go up and / or down? Example: I have 10 lines of output, I want to change the 3rd line from Doing ABC to ABC: Done . How can i do this?

Also, can anyone post more details on what VT102 characters are? What are its features? Please write good links to this, if you have any.

thanks

+7
c linux terminal stdout
source share
7 answers

Use '\ r' to go back to the beginning of the line and possibly rewrite the entire line.

Take a look at VT102 escape sequences - these are ESC ... character sequences to control your terminal.

+3
source share

The main characters for formatting control are backspace (\ b), tab (\ t), newline (\ n) and carriage return (\ r). If you need more than then, you can use ANSI X3.64 / ISO / IEC 6429 / ECMA-48 escape sequences; at least a subset of the VT100 is recognized by most modern terminals and emulators. The advantage of using ncurses is that it will look for the capabilities of your particular terminal and therefore it will work even if your terminal uses a different set of escape sequences.

+6
source share

You must remember that with regard to regular procedures, stdio stdout is just a stream of bytes that do not have the characteristic characteristics of a mapping; which depends on the target device, which can be anything: from a regular terminal such as VT100 to a printing terminal to a printer with a sheet printer on any plotter.

IMO, you are much better off using a library like ncurses than trying to crack your own display control code with VT100 escape codes, even for a relatively simple task like this. I know that you want to stick with "plain old C", but this is a task that goes beyond plain old C.

+5
source share

There is also the option of using Ncurses , which is a text-interface library where this behavior should have some support. However, this may be redundant for something like this.

+2
source share

A slight deviation from your own decision:

You can also print a carriage return ( \r ), which will return you to the beginning of the line.

+1
source share

This is a progress indicator for bash.

 function gauge() { progress="$1" total="$2" width=`tput cols` let gwidth=width-7 if [ "$total" == "0" ]; then percent=100 else set +e let percent=progress*100/total; set -e fi set +e let fillcount=percent*gwidth/100 let nofillcount=gwidth-fillcount set -e fill=""; if [ "$fillcount" -gt "0" ]; then for i in `seq $fillcount`; do fill="$fill""|" done fi; nofill="" if [ "$nofillcount" -gt "0" ]; then for i in `seq $nofillcount`; do nofill="$nofill"" "; done fi echo -e -n "\r[""$fill""$nofill""] ""$percent""%"; } 
0
source share

About the progress bar: something like this?

 #include <stdio.h> #include <unistd.h> typedef enum { false=0, true=!false } bool; typedef struct { /* Start delimiter (eg [ )*/ char StartDelimiter; /* End Delimiter (eg ] )*/ char EndDelimiter; /* Central block (eg = )*/ char Block; /* Last block (eg > ) */ char CurBlock; /* Width of the progress bar (in characters) */ unsigned int Width; /* Maximum value of the progress bar */ double Max; /* True if we have to print also the percentage of the operation */ bool PrintPercentage; /* True if the bar must be redrawn; note that this must be just set to false before the first call, the function then will change it by itself. */ bool Update; } ProgressBarSettings; /* Prints/updates the progress bar */ void PrintProgressBar(double Pos, ProgressBarSettings * Settings); /* Inits the settings of the progress bar to the default values */ void DefaultProgressBar(ProgressBarSettings * Settings); int main() { int i; /* Init the bar settings */ ProgressBarSettings pbs; DefaultProgressBar(&pbs); pbs.Max=200; pbs.Width=60; printf("Progress: "); /* Show the empty bar */ PrintProgressBar(0,&pbs); for(i=0;i<=pbs.Max;i++) { /* Wait 50 msec */ usleep(50000); /* Update the progress bar */ PrintProgressBar(i,&pbs); } puts(" Done"); return 0; } /* Inits the settings of the progress bar to the default values */ void DefaultProgressBar(ProgressBarSettings * Settings) { Settings->StartDelimiter='['; Settings->EndDelimiter=']'; Settings->Block='='; Settings->CurBlock='>'; Settings->PrintPercentage=true; Settings->Update=false; Settings->Max=100; Settings->Width=40; } /* Prints/updates the progress bar */ void PrintProgressBar(double Pos, ProgressBarSettings * Settings) { /* Blocks to print */ unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max); /* Counter */ unsigned int counter; /* If we are updating an existing bar...*/ if(Settings->Update) { /* ... we get back to its first character to rewrite it... */ for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--) putchar('\b'); } else Settings->Update=true; /* next time we'll be updating it */ /* Print the first delimiter */ putchar(Settings->StartDelimiter); /* Reset the counter */ counter=Settings->Width; /* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have the number of spaces to fill the bar */ for(;printBlocks>1;printBlocks--,counter--) putchar(Settings->Block); /* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */ putchar((Settings->Max==Pos)?Settings->Block:Settings->CurBlock); /* Another block was printed, decrement the counter */ counter--; /* Fill the rest of the bar with spaces */ for(;counter;counter--) putchar(' '); /* Print the end delimiter */ putchar(Settings->EndDelimiter); /* If asked, print also the percentage */ if(Settings->PrintPercentage) printf(" %3d%%",(int)(100*Pos/Settings->Max)); /* Flush the output buffer */ fflush(stdout); }; 

Note: unistd.h and usleep are just a fake of the progress of the operation, the execution code itself simply uses the standard library. His only assumptions regarding the output stream are that \ b actually goes to the previous character written. I tried this successfully on Windows and Linux (with gnome-terminal), I don’t know if it works with some terminal emulators. Sorry for the excessive number of comments, I wrote it for another forum, where I needed to explain each line of code for a newbie C.

0
source share

All Articles