I am running urxvt on Arch Linux. I can select the output with mouse for copy / paste. The problem occurs when output contains tabulators. All tabulators are selected and copied as spaces. That makes it really difficult to preserve the structure of some outputs when copying them.

Is there any way to fix this behaviour?

EDIT: I am using zsh if that has any effect on the issue.

  • 2
    I don't think you can avoid it, you might re-enter the tabs by piping the paste through unexpand. – Thor Sep 8 '12 at 20:01

I don't know of any terminal that does, and I'll just say why I don't think any terminal does:

tab is one of the many characters that once displayed outputs more than one character on screen or moves the cursor. CR (move to beginning of line), LF (down), backspace (left) and all the escape sequences that move the cursor or change character attributes and/or don't display anything...

urxvt doesn't even get exactly what the application outputs. When an application sends a LF (\n) to the slave side of the pseudo-terminal, you'll notice that, most of the time, it does not just move the cursor down, as LF normally does, it also moves it back to the start of the line. That's because the pty driver translates the "\n" to "\r\n" before making it available for reading from the master side of the terminal by urxvt (you may use stty to change that behavior).

Also note that the selection will not capture trailing spaces.

The X selection selects the characters that are displayed, not the ones that have been sent by the application(s) to generate that display (consider that any character at any given position on the screen may have been overridden several times by one or more application(s)).

Some terminals though allow to capture all the characters that they receive on the master side of the pseudo-terminal, and if they don't, you can use "script" or "screen" to do it instead. But to get the output of an application into the X selection, you can also simply do:

the-command | xsel

The topic has come up occasionally with various terminal emulators. The discussion in Debian #259828 xterm: whitespace after tabs represented as space characters in selections (for xterm) had this comment by urxvt's developer:

I thought about implementing this in rxvt-unicode: tabs could be represented trivially in rxvt-unicode's data structure. However, there are semantic problems:

Tabs are not characters, but cursor movements. As such, there is no good way to represent them as tab characters, just as "cursor up" or "goto 5,6" will not be represented in the selection text.

and went on to say (in effect) that urxvt supported the feature:

If anybody cares, here is how rxvt-unicode-3.8 implements HT characters now, plus some initial experience on the effects.

When rxvt-unicode-3.8 received a HT, it first calculates the tab movement (which is a relative cursor movement). Iff all characters skipped over are spaces with the same attributes as the first space, it will replace these spaces by a (very) wide tab character (which is easy to do in the way rxvt-unicode handles wide characters, so the code changes were limited to less than 15 lines within the scr_tab method). If any of the characters are not spaces, or if there are attribute changes (e.g. colour), it will only move the cursor.

Of course urxvt 3.8 is a while back. But consider the application problems which get in the way:

  • just the terminal itself has to support the feature (store tabs-as-tabs and allow selecting those),
  • the terminal has to do the right thing when a tab hits the right margin (that bug report notes cases which did not),
  • the terminal has to be configured to use hard tabs (see stty setting for this),
  • applications (and libraries such as ncurses) have to be configured to use hard tabs, and
  • applications such as screen/tmux have to (again) manage tabs-as-tabs so that when painting and re-painting the screen those are sent to the terminal as tabs.

Just because your application sends a tab to the screen doesn't mean that it gets to the terminal. It can be translated to spaces in more than one level, and optimized entirely away if an intermediate level decides that the screen would not change anyway.

A quick check with urxvt 9.15 shows me that the feature still works (in the simplest configuration, of course):

$ /tmp/foo
hello   .   world
00000000  68 65 6c 6c 6f 09 2e 09  77 6f 72 6c 64 0a        |hello...world.|
$ cat /tmp/foo
printf 'hello\t.\tworld\n' |xclip

If it doesn't work for you, then your terminal may be set to soft tabs, or one of the other above-mentioned problems is in your way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.