Bash – Fix Copying Tabs Issue at Text-Wrapping Edge

bashgnome-terminalterminal

The following code will print "a"s up to the terminal width and then a tab character and then a "b". I've tested both Ubuntu's default Gnome terminals and Terminator and they display all the "a"s and the "b" on one line as a single word with no tab character. Copying them results in no tab character either. Same happens when we print one more "a" (change the 0 to 1). Is this a bug?

printf '%'$(($(stty size | cut -d ' ' -f 2)+0))'sb\n' $'\t' | tr ' ' 'a'

Best Answer

This is also the behavior of xterm, which is widely considered as the de facto standard for terminal emulation; and I'm pretty certain that it's also backed by corresponding standards that these terminal emulators follow.

TAB is not a printable character (isprint(9) returns 0), [and in my opinion the practice of storing TABs in text files is a big mistake all throughout the computer world, not just for the troubles it causes with terminal emulation; but this is a debate for another day, I don't want to start a tabs vs spaces flamewar here :)]

TAB is a control character that moves the cursor in the same row to the next TAB stop. It's like all those various other cursor moving escape sequences that the terminal supports.

Just for fun, you can also notice that TAB doesn't wipe out the characters underneath. If there's any actual content that it jumps through then it leaves those unchanged, totally breaking the visual result and copy-pasting compared to what you'd probably expect.

Many terminal emulators out there don't copy TABs to the clipboard but copy spaces instead (jumping through cells in the "erased" state converts them to spaces I guess). It's a special quirk in VTE (the terminal emulation widget used both by GNOME Terminal and Terminator) and presumably in a few other terminal emulation engines to preserve the TAB characters under certain circumstances (e.g. if it didn't jump over an already existing character).

As much as I dislike the current behavior just like you and would much rather prefer that a TAB jumped to the next line and would be preserved while copy-pasting or when rewrapping the lines on a resize, I'm afraid such a deviation from the standard is likely to cause various sorts of bugs in various applications.

TAB is not a printable character, it's a control instruction. Just like with any other nonprintable characters, including escape sequences, you shouldn't send them to the terminal unless you know exactly what you're doing. Unfortunately this expectation from the terminal (and its backing standards), and the widespread use of TABs in text files and expecting cat to "just work" really don't play well together.

Related Question