I am testing some Escape Sequence Character in C using Command Line Tool in xCode on El Capitan. This is the string I tested:
printf("\a111\b222\n");
The expected result was:
bell noise followed by 112221
to my surprise, there was no bell sound at the start, \b did not move cursor one character back, and write from there on. Is this a Mac and xCdoe problem? If so, what do I need to enable all the escape characters.
How those escape sequences are interpreted is up to the terminal/shell where you execute the program. Not all terminals support all sequences.
Related
I'm using the readline library in C to create a bash-like prompt within bash. When I tried to make the prompt colorful, with color sequences like these, the coloring works great, but the cursor spacing is messed up. The input is wrapped around too early and the wrap-around is to the same line so it starts overwriting the prompt. I thought I should escape the color-sequences with \[ and \] like
readline("\[\e[1;31m$\e[0m\] ")
But that prints the square brackets, and if I escape the backslashes it prints those too. How do I escape the color codes so the cursor still works?
The way to tell readline that a character sequence in a prompt string doesn't actually move the cursor when output to the screen is to surround it with the markers RL_PROMPT_START_IGNORE (currently, this is the character literal '\001' in readline's C header file) and RL_PROMPT_END_IGNORE (currently '\002').
And as #Joachim and #Alter said, use '\033' instead of '\e' for portability.
I found this question when looking to refine the GNU readline prompt in a bash script. Like readline in C code, \[ and \] aren't special but \001 and \002 will work when given literally via the special treatment bash affords quoted words of the form $'string'. I've been here before (and left unsatisfied due to not knowing to combine it with $'…'), so I figured I'd leave my explanation here now that I have a solution.
Using the data provided here, I was able to conclude this result:
C1=$'\001\033[1;34m\002' # blue - from \e[1;34m
C0=$'\001\033[0;0m\002' # reset - from \e[0;0m
while read -p "${C1}myshell>$C0 " -e command; do
echo "you said: $command"
done
This gives a blue prompt that says myshell> and has a trailing space, without colors for the actual command. Neither hitting Up nor entering a command that wraps to the next line will be confused by the non-printing characters.
As explained in the accepted answer, \001 (Start of Heading) and \002 (Start of Text) are the RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE markers, which tell bash and readline not to count anything between them for the purpose of painting the terminal. (Also found here: \033 is more reliable than \e and since I'm now using octal codes anyway, I might as well use one more.)
There seems to be quite the dearth of documentation on this; the best I could find was in perl's documentation for Term::ReadLine::Gnu, which says:
PROMPT may include some escape sequences. Use RL_PROMPT_START_IGNORE to begin a sequence of non-printing characters, and RL_PROMPT_END_IGNORE to end the sequence.
I was looking for some alternative to system("cls") that works on MacOS and I found this:
printf("\e[1;1H\e[2J");
However I do not know what this is doing.
Post where I found this
\e is escape and what that printf() line is telling the terminal to move the cursor to line 1 column 1 (\e[1;1H) and to move all the text currently in the terminal to the scrollback buffer (\e[2J).
These are ANSI escape codes and here's some resources: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
https://bluesock.org/~willkg/dev/ansi.html
https://en.wikipedia.org/wiki/ANSI_escape_code (suggested by tadman)
Edit: I also recommend the use of \e[H\e[2J\e[3J as that is what cls/clear prints. This tells the terminal to move the cursor to the top left corner (\e[H), clear the screen (\e[2J), and clear the scrollback buffer (\e[3J).
if your language does't support \e you can instead replace it with \x1b or \033
Hexadecimal
printf("\x1b[1;1H\x1b[2J");
Decimal
printf("\033[1;1H\033[2J");
Some applications running in terminal can erase their outputs. e.g.
when it tells you to wait, it will show a sequence of dots alternating between different lengths.
How is erasing output in terminal implemented in C? Is it done by reverse line feed?
Can a program only erase the previous characters in the current line, not the characters in the previous line in stdout?
Thanks.
It depends on the terminal.
The COMSPEC shell on Windows (often called the DOS prompt or command.com) exposes an API in C to control the cursor. I haven't done any Windows programming so I can't tell you much about it.
Most other terminals (especially on unixen) emulate protocols that resemble the VT100 serial terminal (the VT100 terminal was a physical device, a monitor and keyboard, that you attached to a modem or serial port to communicate with a server).
On VT100 terminals, carriage return and line feed are separate commands, both one byte. The carriage return command sets the cursor to the beginning of the line. The line feed command moves the cursor down a line (but doesn't bring the cursor to the beginning of the line by itself). Most shells on unixen automatically insert a carriage return after a line feed but almost none inserts a line feed after a carriage return.
With this knowledge, the simplest implementation is to simply output a carriage return and reprint the entire line:
printf("\rprogress: %d percent ", x);
Note the extra spaces at the end of the line. Printing "\r" doesn't erase the line so reprinting over the old line may end up leaving some of the old string on screen. The extra spaces is used to try and erase the remainder of the old line.
If you googled "VT100 escape secquence", you'll find commands that will allow you to do things like erase the current line, change color of text, goto a specific row/column on screen etc. The most popular use of VT100 sequences is to output coloured text. But you can also do other things with them.
The next simplest implementation is to cleanly delete the line and reprint it:
printf("\033[2K\rprogress: %d percent", x);
The \033[2K is the escape sequence to delete the current line (ESC[2K).
From here you can get more creative if you want. You can use the cursor save/restore command with the erase until end of line command to only erase the part you want to update (instead of the entire line). You can use the goto commands to put the cursor in a specific location on screen to update text there etc.
It should be noted that the more advanced stuff such as VT102 sequences or some of the full ANSI escape sequences are generally not portable accross terminals (by terminals I don't mean the shell, I mean the terminals: rxvt, xterm, linux terminal, hyperterminal(on windows) etc).
If you want portability (and/or sane API) you should use the curses or ncurses libraries.
If you wanted to know how it's done, then that's how it's done. It's just printing specially formatted strings to screen (except for the COMSPEC shell). Kind of like HTML but old-school.
I have an embedded device communicatiing with a host (with Tera Term) through USART. I realised the ASCII characters could be "extended" through the escape character ^[. For example, ^[A is "up arrow".
Is there an ASCII escape for "clear line"? Where can I find a list of escapes?
This list is a list of ansi escape codes. Your terminal may or may not support them.
Following the more complete list mentioned there, you can see the following information:
Esc[K Clear line from cursor right EL0
Esc[0K Clear line from cursor right EL0
Esc[1K Clear line from cursor left EL1
Esc[2K Clear entire line EL2
#include <stdio.h>
int main()
{
int countch=0;
int countwd=1;
printf("Enter your sentence in lowercase: ");
char ch='a';
while(ch!='\r')
{
ch=getche();
if(ch==' ')
countwd++;
else
countch++;
}
printf("\n Words =%d ",countwd);
printf("Characters = %d",countch-1);
getch();
}
This is the program where I came across \r. What exactly is its role here? I am beginner in C and I appreciate a clear explanation on this.
'\r' is the carriage return character. The main times it would be useful are:
When reading text in binary mode, or which may come from a foreign OS, you'll find (and probably want to discard) it due to CR/LF line-endings from Windows-format text files.
When writing to an interactive terminal on stdout or stderr, '\r' can be used to move the cursor back to the beginning of the line, to overwrite it with new contents. This makes a nice primitive progress indicator.
The example code in your post is definitely a wrong way to use '\r'. It assumes a carriage return will precede the newline character at the end of a line entered, which is non-portable and only true on Windows. Instead the code should look for '\n' (newline), and discard any carriage return it finds before the newline. Or, it could use text mode and have the C library handle the translation (but text mode is ugly and probably should not be used).
It's Carriage Return. Source: http://msdn.microsoft.com/en-us/library/6aw8xdf2(v=vs.80).aspx
The following repeats the loop until the user has pressed the Return key.
while(ch!='\r')
{
ch=getche();
}
Once upon a time, people had terminals like typewriters (with only upper-case letters, but that's another story). Search for 'Teletype', and how do you think tty got used for 'terminal device'?
Those devices had two separate motions. The carriage return moved the print head back to the start of the line without scrolling the paper; the line feed character moved the paper up a line without moving the print head back to the beginning of the line. So, on those devices, you needed two control characters to get the print head back to the start of the next line: a carriage return and a line feed. Because this was mechanical, it took time, so you had to pause for long enough before sending more characters to the terminal after sending the CR and LF characters. One use for CR without LF was to do 'bold' by overstriking the characters on the line. You'd write the line out once, then use CR to start over and print twice over the characters that needed to be bold. You could also, of course, type X's over stuff that you wanted partially hidden, or create very dense ASCII art pictures with judicious overstriking.
On Unix, all the logic for this stuff was hidden in a terminal driver. You could use the stty command and the underlying functions (in those days, ioctl() calls; they were sanitized into the termios interface by POSIX.1 in 1988) to tweak all sorts of ways that the terminal behaved.
Eventually, you got 'glass terminals' where the speeds were greater and and there were new idiosyncrasies to deal with - Hazeltine glitches and so on and so forth. These got enshrined in the termcap and later terminfo libraries, and then further encapsulated behind the curses library.
However, some other (non-Unix) systems did not hide things as well, and you had to deal with CRLF in your text files - and no, this is not just Windows and DOS that were in the 'CRLF' camp.
Anyway, on some systems, the C library has to deal with text files that contain CRLF line endings and presents those to you as if there were only a newline at the end of the line. However, if you choose to treat the text file as a binary file, you will see the CR characters as well as the LF.
Systems like the old Mac OS (version 9 or earlier) used just CR (aka \r) for the line ending. Systems like DOS and Windows (and, I believe, many of the DEC systems such as VMS and RSTS) used CRLF for the line ending. Many of the Internet standards (such as mail) mandate CRLF line endings. And Unix has always used just LF (aka NL or newline, hence \n) for its line endings. And most people, most of the time, manage to ignore CR.
Your code is rather funky in looking for \r. On a system compliant with the C standard, you won't see the CR unless the file is opened in binary mode; the CRLF or CR will be mapped to NL by the C runtime library.
There are a few characters which can indicate a new line. The usual ones are these two:
'\n' or '0x0A' (10 in decimal) -> This character is called "Line Feed" (LF).
'\r' or '0x0D' (13 in decimal) -> This one is called "Carriage return" (CR).
Different Operating Systems handle newlines in a different way. Here is a short list of the most common ones:
DOS and Windows
They expect a newline to be the combination of two characters, namely '\r\n' (or 13 followed by 10).
Unix (and hence Linux as well)
Unix uses a single '\n' to indicate a new line.
Mac
Macs use a single '\r'.
That is not always true; it only works in Windows.
For interacting with terminal in putty, Linux shell,... it will be used for returning the cursor to the beginning of line.
following picture shows the usage of that:
Without '\r':
Data comes without '\r' to the putty terminal, it has just '\n'.
it means that data will be printed just in next line.
With '\r':
Data comes with '\r', i.e. string ends with '\r\n'. So the cursor in putty terminal not only will go to the next line but also at the beginning of line
It depends upon which platform you're on as to how it will be translated and whether it will be there at all: Wikipedia entry on newline
\r is an escape sequence character or void character. It is used to bring the cursor to the beginning of the line (it maybe of same or new line) to overwrite with new content (content written ahead of \r like: \rhello);
int main ()
{
printf("Hello \rworld");
return 0;
}
The output of the program will be world not Hello world
because \r has put the cursor at the beginning of the line and Hello has been overwritten with world.