What we still use ASCII CR for today (on Unix)
I recently read Things Every Hacker Once Knew, which
is really mostly about the somewhat less grander topic of ASCII,
RS-232, and serial terminals (via, and
also). Part of
the article is a writeup of all of the ASCII control characters,
covering their original purposes and what they're still used for
today, if anything. It has this to say about CR (aka Ctrl-M, C
decimal byte 13 (hex 0x0d, octal 015)):
- CR (Carriage Return)
- It is now possible that the reader has never seen a typewriter, so this needs explanation: "carriage return" is the operation of moving your print head or cursor to the left margin. Windows, other non-Unix operating systems, and some Internet protocols (such as SMTP) tend to use CR-LF as a line terminator, rather than bare LF. Pre-Unix MacOS used a bare CR.
This description may sound like CR is no longer used on Unix, except as part of being carefully compatible with old protocols like SMTP and newer ones like HTTP. This is misleading, because CR is still in active use on Unix today.
(Sadly, HTTP and other new(ish) protocols continue to specify that 'lines' in the protocol are terminated with CR LF instead of plain LF. This is generally an annoying mistake that simply complicates everyone's life, but that's another rant.)
You see, printing a CR has an extremely useful property: it painlessly resets the cursor to the start of the line but doesn't advance it to the next line. So if you print something without a newline, print a CR, and then carefully print again just so, you will overwrite your original output with new output on the same line. This is the traditional and frequently used low-rent way of creating a constantly updated line for program progress, the current status of something, or basically anything where you want frequent updates but not to scroll things madly the way you would if you printed each update as a new line.
Of course this has limits. The big limit is that what you want to print and over-print can't be longer than one row in your (emulated) terminal. If your terminal is, say, 60 columns wide and you print a 70-character status, the last ten characters or so will overflow onto the next physical line, along with the cursor, and then your CR will only return the cursor to the start of that second line. If you write another 70-character status update, you'll advance yet another line, and so on.
(Dealing with multi-line status updates requires going to full
cursor addressing using
curses(3) or the like. This is a lot
more complicated, which is why people really like to stick to
just printing CRs for as long as possible and thus why some
things will explode if you run them in too-narrow terminals or
resize the terminal on them as they're running.)
As a side note, this isn't the only way to do same-line status
updates; you can also backspace over what you've printed by printing
some number of Ctrl-Hs. The Ctrl-H trick tends to be what gets used
if you just want to update a bit of status at the end of a line,
eg updating the percentage in a message like '
current progress on
frobnicating things: XX%'. The CR trick usually gets used when
counting how many Ctrl-Hs to print (and printing them all) gets
annoying. However, Ctrl-H has a quiet advantage; it often does a
better job of handling overly-long status lines, because in many
(emulated) terminals enough Ctrl-Hs will back up to previous lines.
If you print 90 normal characters and then 90 Ctrl-Hs, you usually
wind up with the cursor where you started no matter what the width
of the terminal is.
(Reading the description of DEL in the article might make you think you could print DELs instead of BSs, with the extra advantage that this would not merely move the cursor back but also erase that pesky existing status for you. In practice (emulated) terminals generally don't respond at all to having DEL printed out to them; it gets ignored and does nothing.)