Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I found that

setterm -regtabs 4

doesn't work in xterm or urxvt.

But, this

xterm_set_tabs () { 
  TERM=linux;
  export $TERM;
  setterm -regtabs 4
}

will circumvent the problem.

But, I suspect it is suboptimal as (1) I get a gfx bug I can't otherwise explain (at least, if I get the tab stuff right that possibility is ruled out), and (2) when I ssh to my school's Solaris, and run emacs -nw, it says the terminal "linux" is unknown! So then I have to change it back to "xterm". Of course, this is silly as all the while I'm using the same terminal...

Also, perhaps not relying on tabs at all is a good rule of thumb!

share|improve this question

4 Answers 4

You can set the environment variable temporarily without needing to export it to your whole session using env:

env TERM=linux setterm -regtabs 4
share|improve this answer
    
That is better. –  Emanuel Berg Aug 26 '12 at 22:42
    
Tried this, same problem as described in my post, and in the comment to sch's post. –  Emanuel Berg Sep 1 '12 at 17:36

Many terminals support escape sequences that set tab stops. The capability has even an entry in terminfo(5): tbc (clear all tabs) and hts (horizontal tab set).

$ tput tbc; echo aaaaaaaaaaaaaaaaaaaaa$(tput hts); echo 'a\tb'
aaaaaaaaaaaaaaaaaaaaa
a                    b

Above we set a tab stop at the end of those aaaaaaaa, and we see the result on next line.

So, to set the tab stops, every 4 colums, we need:

tbc=$(tput tbc) hts=$(tput hts) cuf4=$(tput cuf 4)
printf '%s\r' "$tbc"
i=4
while [ "$i" -lt "$COLUMNS" ]; do
  printf %s "$cuf4$hts"
  i=$(($i + 4))
done
printf '\r'

Or you can also set tab stops at irregular intervals. Above we used "tput cuf" to move the cursor forward, while in the first example we used "aaaa". You can do:

printf '\r%s' "${tbc}aaaa${hts}aaaaa${hts}aaaaaaaa${hts}"

to set one tab stop at the 4th column, then the next one, 5 columns further...

share|improve this answer
    
Will this set the general tab width so that \t = " " if the tab width is 4? (Imagine four spaces, seems I can't write that.) –  Emanuel Berg Aug 26 '12 at 21:03
    
OK, I see you've made an edit, answering my comment above. You seem to know a lot about this... Check out my answer below, is there a practical difference or are your solution simply much cooler? –  Emanuel Berg Aug 29 '12 at 2:35
    
Hello again, just tried this and it breaks the cursor movement in emacs -nw just like my solution below. –  Emanuel Berg Sep 1 '12 at 17:13

In response to @Jim Paris:

Note that that only works for terminals that support the same escape sequences as linux virtual terminals to set tabs (and move the cursor forward).For instance, using "cat -v", we can see what sequence setterm is sending:

$ TERM=linux setterm -regtabs 4 | cat -vte
^[[3g^M^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^[[4C^[H^M

Luckily, it's the same sequences as supported by xterm:

~$ TERM=xterm tput tbc | cat -vte
^[[3g
~$ TERM=xterm tput hts | cat -vte
^[H
~$ TERM=xterm tput cuf 4 | cat -vte
^[[4C

And as it's the case of vt100, it's likely to be the case of most termnial emulators.

share|improve this answer
    
Better yet would probably be to set it native in xterm, urxvt, etc., not going sideways to the Linux virtual terminal. I suspect there is an .Xresources option for this; I'll keep looking. (Above, isn't it enough with cat -t?) –  Emanuel Berg Aug 27 '12 at 9:19

OK, I've read man xterm and there is no mention of tab width. I'm starting to think it is easiest just to reset TERM. In .bashrc:

function xterm_set_tabs () {
  TERM=linux
  export $TERM
  setterm -regtabs 4
  TERM=xterm
  export $TERM
}

if [ `echo $TERM` == "xterm" ]; then
  xterm_set_tabs
fi

Edit: This works for the problem described, but it has the side effect that when I run emacs -nw the cursor movement is messed up. As that is very serious, this is not an acceptable solution to the problem. (I'm unsure about site policy - should I remove my answer, or should I leave it so others will learn from the mistake as well? Obviously, I think it should remain. Anyhow, back to the drawing board.)

share|improve this answer
    
TERM=linux setterm -regtabs 4 is how you set the TERM variable to linux only for the setterm command. Are you sure you'll run that only in xterm terminals? –  Stéphane Chazelas Aug 29 '12 at 6:00
    
So far the above has worked, the display in xterm is correct and I can ssh and then emacs -nw, but I'm absolutely not sure of any under the hood workings in this case. There are a lot of suggestions already, if you know their pros and cons, do tell, that's why we are here :) –  Emanuel Berg Aug 29 '12 at 14:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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