1

I have the following settings in my vimrc:

set listchars=tab:►-,eol:¬,trail:●

When I display unprintable characters in my makefile, I get something that looks like the following for one of the targets:

target:►prereq1►prereq2►►---prereq3►►---prereq4

I expect to see the following:

target:►---prereq1►---prereq2►---►---prereq3►---►---prereq4

It looks like it is displaying some of the tabs as instead of ►---. I can't understand why. Can someone explain what is going on and how to fix it?

1
  • What have I done to deserve a downvote?
    – flashburn
    Jul 17, 2015 at 18:19

3 Answers 3

7

A tab advances to the next column whose position is a multiple of the tab stop. So, with tabstop=4, if your cursor is in column 7 and you press Tab, the cursor will advance only one column to column 8, as in the first tab in your example. Tabs are not constant width.

You can visualize it thus—each is a tab stop, a column that is a multiple of 4:

    ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓
target:►prereq1►prereq2►►---prereq3►►---prereq4

Note that every tab character advances to the next arrow.

This is what allows tabs to line up columns of text:

    ↓   ↓
a►--b►--c
dd►-ee►-ff
ggg►hhh►iii

is

a   b   c
dd  ee  ff
ggg hhh iii

If every tab was four spaces, it would look like this instead:

a    b    c
dd    ee    ff
ggg    hhh    iii

However, this only works if every column's length is less than the tab stop size; otherwise it will skip to the next tab stop.

a   b   c
dddd    eeee    ffff
3

Unlike A, @ or space, tabulations are not "real" characters with a defined glyph and defined metrics and whatnot. When you insert a "tab" you tell your text editor this:

I want the next character to be displayed at most n spaces from here.

n being the value of tabstop or softtabstop.

In the following example, [ ] represent a 4 spaces wide tabulation:

[  ][  ][  ][  ][  ][  ][  ][  ]...
lorem ipsum dolor sit amet                no tab
    lorem ipsum dolor sit amet            tab before lorem
lorem   ipsum dolor sit amet              tab before ipsum
lorem ipsum     dolor sit amet            tab before dolor
lorem ipsum dolor   sit amet              tab before sit
lorem ipsum dolor sit   amet              tab before amet

Note how each tab appears to have a different width; 4, 2, 4, 2 and 2. That's because tabulations are here to help you align your text: n. No matter the content, you can be certain that inserting a "tab" will push the rest of the line to the next tabstop, which will always be at most 8 (or whatever value you chose) characters to the right.

Now, the value you chose for listchars:

tab:►-

tells vim to materialize tabulations with a followed by zero or more -, up to &tabstop - 1. With your settings, tabulations can take any of the forms below:

►
►-
►--
►---

In the sample above...

[  ][  ][  ][  ][  ][  ][  ][  ]...
lorem ipsum dolor sit amet                no tab
►---lorem ipsum dolor sit amet            tab before lorem
lorem ►-ipsum dolor sit amet              tab before ipsum
lorem ipsum ►---dolor sit amet            tab before dolor
lorem ipsum dolor ►-sit amet              tab before sit
lorem ipsum dolor sit ►-amet              tab before amet

In short, everything is A-OK and the behavior you get is exactly the same you should get in any other text editor or word processor.

3
  • I thought when I set my tabstop to 4 I tell vim to use 4 spaces for a tab. And when I set my listchar character to tab:►-, it will fill the first space with ►, and the other spaces with - . My interpretation seems to be incorrect. Am I correct in understanding that there tab character doesn't occupy the same number of spaces every time? If yes, then how do I know how many spaces it occupies in a given instance?
    – flashburn
    Jul 17, 2015 at 20:42
  • The tab character never occupies even one space. The string used by Vim to materialize tabulations, on the other hand, is of variable width: followed by as many - as necessary (7 with the default ts, 3 if you set it to 4...). My answer is likely to be the most comprehensive you will ever get to this question. If unsure about the value of tabstop for your makefiles do :echo &tabstop. If you are not satisfied with your current settings, look around this site or stack overflow for "filetype specific settings". Or ask another more specific question, with your actual settings.
    – romainl
    Jul 17, 2015 at 20:59
  • 2
    @flashburn: This isn't specific to vim; it's how tab character behave in general. Printing a tab character advances to the next tab stop, however many columns that happens to be. The behavior goes back (at least) to manual typewriters. Jul 20, 2015 at 21:52
0

It is because the tab spans 8 positions. Your prereqX text covers already 7 positions and therefor the ►- is truncated.

Try to insert the line:

a<tab>b<tab>c<tab>d<tab>e<tab>

See also :help tabstop for more details.

Your expectation is using almost :set tabstop=11 by the way.

1
  • My tabstop, shiftwidth and softtabstop are all set to 4. Clearly my understanding of tabstop is wrong even after reading help for tabstop. Would you mind clarifying your answer. Even after reading help for tabstop, I still don't see what I'm doing wrong.
    – flashburn
    Jul 17, 2015 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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