Hacker News new | ask | show | jobs
by faho 1435 days ago
"\r", "carriage return", is what the return/enter key sends (either that or "\n", it's configurable).

So what's being sent from the terminal to bash here is "ls" (which is echoed back) and then the return/enter key, which bash interprets as "run the command".

So it sends "\r\n" to the terminal (this is "recv" in that notation), which moves the cursor to the beginning of the line and then to a new line to get the cursor off of the prompt line, and then "\x1b[?2004l", which is the sequence to turn off bracketed paste.

Then ls runs and prints "file\r\n", which is the filename "file" on its own line.

Then bash takes over again, reenables bracketed paste and prints the prompt. Notably it does not move the cursor to get the prompt on its own line, so when the command didn't end in a newline the prompt hangs in a weird spot - try `printf '%s' foobar`, it'll show your prompt like "foobarbork@kiwi:/play$". There are tricks to get around this.

2 comments

I think bash actually sends just "\n", the LF-to-CRLF translation is handled in the tty driver (it used to be part of the kernel, but no longer. Funny how Linux still has to translate text to use the so-called "Microsoft line endings" when it comes to terminals).
This is correct, but they're only "Microsoft" line endings (CR+LF) when you're encoding a text file. When output to a terminal, they're literal instructions:

CR - carriage return - escaped as \r - move the carriage to the beginning of the line (the "carriage" is the print head of a line printer, think an old dot-matrix or a typewriter)

LF - line feed - escaped as \n - advance the paper one line.

Since all on-screen terminals are "virtual", these are translated to cursor movements. But their origin is in paper output.

    If you've ever
                  seen text that
                                gets printed like this
...it's because the \n LF line separators in the output aren't being translated to terminal instructions, just dumped raw.

MS decided that both should be kept in text files; Unix-ish dropped the carriage return to use \n; MacOS before OSX used only \r.

There are also (text-based) network protocols; almost all of them use CRLF as line breaks since time immemorial because "text is something that can be sent straight to the teletype and should be shown all right". UNIX decided to break with this tradition, others like DEC, and CP/M, and then Microsoft, decided not to which is why I put "Microsoft line-endings" in quotes: reasonably, they are just "line-endings", have always been, and then there is the "UNIX line-ending convention".
Thank you for your explanation.

After we press the return/enter key to tell bash to "run the command", is bash doing everything from here (ls is not part of this bash part right?) including switching off the bracketed paste and re-enabling it?

Bash also turns off the bracketed paste, because it can't know if the command it is about to launch supports it. So that command would have to re-enable it itself. Something like emacs or vim might do so (or another bash, you can nest shells).

And yes, then bash starts ls, which is an external program. It might be /usr/bin/ls.

And then ls quits, and bash re-enables bracketed paste because the command might have not enabled it or enabled it and disabled it before quitting. So you get this weird bracketed paste sandwich.