For a long running task I'd like to have a progress display. I'm currently using \33[2K\r at the start of my printf command, and no newline or anything at the end. What I don't like about this approach is that messages printed to the same terminal (stderr without redirection for example) appear at the end of the line, instead of a new one.
If I put the \r at the end of the progress display, other messages (all terminated with \n) would visually override the progress display and get mixed up with remains if they are shorter than that. Also, I don't want to have to/can't adapt the lines printing those other messages, as some of them come from external libraries.
I don't have a problem if my progress display would continue on a new line afterwards, but I'd like to have other messages appearing on their own line (mostly error messages, but I'm trying to gracefully recover as much as possible, so the process will continue most of the time)
Any Ideas?
I don't need portability, it's fine with me if it only runs on linux bash.
Upd: For better visualization of what I'm asking for:
Currently I can do:
status1ERR
status2
Or
ERRtus1
status2
Or
status1
status2 <--- ERR is overriden by status2 here
But what I want is:
status1
ERR
status2
Or
ERR
status2
In the last example ERR overrides a complete status line - I know I can clear lines with the aforementioned VT100 character sequence, but I can't change some of the error messages, so it needs to work with them always being of the format error message\n
Wow. This is a blast from my past.
You can use ANSI or VT100 character sequences to do some cursor positioning.
That will let you separate the types of output on the screen.
Here's a good starter page: http://wiki.bash-hackers.org/scripting/terminalcodes
Just use a \n at the beginning of the error messages. This - of course - doesn't work if you call some other code that produces stderr-output, too.
Related
Trying to debug a program in Scilab, I inserted a couple
of "print" instructions to track what is going on.
At first, I used the %io(2) output "file" which, according
to the Help, stands for the console. Nothing happened.
Then I used an actual filename:
print("C:\Leszek\Xprmnt\scl\Ovsjanko\K3ScilabLog.txt", "START! \n \n \n \n GOING \n")
which does print to that file, but when the dust has settled
and I want to inspect the file what I find inside is just the last
message (just before the program crashed), even though there should
have been others before it, including the "START" etc in the quote above.
Apparently, every print command reopens the file for writing as a clean slate,
overwriting whatever was in it before. Looking into Help and online docs
I didn't find any options or parameters that I could use to change this.
What I want is, obviously, the output from all my print commands since the
beginning of the program, either on the console or in a text file.
TIA.
Just use disp("some text") or mprintf("format",var1,...,varn), both will display on the console. If you need to write in a file use fd = mopen("file.txt") then mfprint(fd,"format",var1,...,varn).
I am trying to code a little console chat-program in C on linux.
So far I coded it in a way that both chatting partners are only able to alternately send/recv, because these function calls are blocking by default.
Now I would like to modify that program, so that both are able to send and receive simultaneously.
The problem that I find is, that once you typed some input to the terminal, I don't know how to output received messages, without messing up the current input line of the terminal.
If there was a way to delete that current input line, you could temporarily save that line, print the new message and put the input line right back.
However, I was not able to find a solution for this problem on the internet.
Is it possible to delete the current input line, and if not, how else could I achieve what I want?
I think you should look into ncurses as Edd said in his comment.
It would allow you to easily manage contents in your terminal window, which sounds like a good idea for your chat program.
All you'd need to do is store your messages in 2 character arrays:
char incoming[MSG_MAX]
and
char outgoing[MSG_MAX]
Then you can output those messages wherever you want in your terminal window, since ncurses allows you to specify x,y coordinates on where to put your text.
Then a simple wrapper for one of ncurses erase() family functions would allow you to delete characters from specify x,y coordinates in your terminal window.
Edit: MSG_MAX is not an actual ncurses macro.
I have to write a self-refreshing progress bar to the terminal - that denotes how much of a file has been copied so far. I tend to refresh the output every 1000 bytes or so. To refresh the screen, I have used the following outline:
printf("\r"); // clear previous output
// output is the progress bar, percent is an integer (0 to 100)
printf("%s %d file written", output, percent);
It works fine when the terminal is large. However, when the terminal is small, such that the entirety of the progress bar doesn't fit into it, the carriage return doesn't work. It only clears the visual single line, not the entire line. I wrote a sample program to demonstrate:
printf(
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghi"
"j");
printf("\rCHECK");
As you can see in the below image, since the terminal is small, only some part of the entire print output is deleted.
Putting multiple carriage returns has no effect.
Then, what is a good way to build such a continuously refreshing terminal output in C?
I also tried clear screen (printf("\033[2J");) but it didn't work for me. It tends to insert arbitrary number of whitespaces at the beginning of the output, see image for example:
Generally, the only way to tell if your message has wrapped to the next line of the terminal is to compare it to the terminal width (number of columns). You can get that info by using terminfo(3)
#include <term.h>
int main() {
setupterm(0, 1, 0); /* default terminal setup from the TERM envvar */
Now you can access the global var columns to know how many columns there are on the terminal. You can also use putp(tigetstr("cuu1")); to go up one line on the terminal. So you can keep track of how long your status message is and figure out how far up you need to go to get back to the beginning of it.
I'm trying to use the escape sequence \033[999D as a brute-force way of moving the cursor to the top row in the console. When I run my program, rather than doing what I intend, it returns a left-pointing arrow and a [999D, on the same line that I was last on.
How should I properly use this escape code? Are there any (better) substitutions?
My (test) code:
printf("This is a line\n");
printf("This is another line\n");
printf("\033[999D Overwrite");
My output:
This is a line
This is another line
←[999D Overwrite
Check out the Win32 Console API.
Particularly of interest to you:
GetStdHandle (MSDN)
SetConsoleCursorPosition (MSDN)
Here is an example showing how to move the cursor to a specific position.
Here is an example showing how to clear the screen.
Of interest to people looking to set console colors:
SetConsoleTextAttribute
There are two problems (most likely): The first is that the D VT100 cursor control sequence is to go back a number of columns, which means it will go back a number of columns on the current row. It will not change line.
The second and the likely problem the code is printed is because you probably are using the Windows console program (the "DOS prompt") which is very bad at handling VT100 sequences by default.
My embedded system has one background program which generates some output message to console.
When it's not finished, the login program starts and prompt login string to same console as well.
My question is, when the login prompt string comes out, the output message generated by the background program is not aligned like this:
Embedded System login: msg_line1...
msg_line2...
msg_line3...
The expected output should be:
Embedded System login: msg_line1...
msg_line2...
msg_line3...
msg_line4...
Have no idea how to resolve the problem...
Could anyone help?
THX!!
Configure your terminal program to autolinefeed, so that it generates the \r internally whenever it receives a \n.
use a redirection for your background program
YourBackStuff.sh >/tmp/back_out.1 2>/tmp/Back_out.2 &
or refresh the screen.
Notice that only the appearance is modified, the real output ou current application/shell (so not the background one) is correct, only the terminal show your all the info received. So
YourFrontApp.sh | tee /tmp/front_out.1
cat /tmp/front_out.1
will produce a correct display (when background process stop)
Looks to me like your messages are sent with a new-line character (represented by \n in C) at the end of each line. This requests a new line from the terminal, which it duly provides. It does not request a carriage return (i.e. "go back to the left hand edge"). This would be represented in C as a \r.
To fix it, you need to set your terminal application to interpret \n as \n\r - it will have a setting for "treat newlines as newline+CR" or some such.