10

I've already read several questions and answers:

But none of them offers a solution for me.

I really want to apply the "Indent with tabs, align with spaces" principle, but when it comes to auto-indentation, I failed to teach Vim how to do that right.

Consider the code, assuming tabstops == 3, shiftwidth == 3

(>-- means tab, and . (a dot) means space):

{
>--long a = 1,
>-->--..b = 2,
>-->--..c = 3;
}

So, it indents with tabs as much as possible, and then fills the rest with spaces. But it is actually a very bad approach: when someone will read this code with different tab size, the code will be messed up. Here what it will look like with tab size equal to 8 chars:

{
>-------long a = 1,
>------->-------..b = 2,
>------->-------..c = 3;
}

It is horrible. The problem is that Vim doesn't distinguish between indentation and alignment.

To make it look correctly with whatever the tab size is, the code should be indented this way:

{
>--long a = 1,
>--.....b = 2,
>--.....c = 3;
}

Then, this code will look nice whatever that tab size is. For example, 8 chars:

{
>-------long a = 1,
>-------.....b = 2,
>-------.....c = 3;
}

How to achieve this?

Community
  • 1
  • 1
Dmitry Frank
  • 10,417
  • 10
  • 64
  • 114
  • Maybe the plugin tabular would give you what you are looking for? https://github.com/godlygeek/tabular – Zach Mar 23 '15 at 18:32

2 Answers2

4

The most powerful way to influence indenting in Vim is via 'indentexpr'. From its :help:

The expression must return the number of spaces worth of indent. It can return "-1" to keep the current indent (this means 'autoindent' is used for the indent).

As this returns the number of spaces, not the rendered indent itself, and Vim only so far supports tab-, space-, or maximal-number-of-tab-followed-by-spaces (called softtabstop), this cannot be done.

So, if you really want to use this indent method (I personally like it for its purity and elegance, too! (but I don't employ it)), you have to turn off auto-indenting and auto-formatting and do the entire stuff manually by yourself, unfortunately.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • Ah, it's too bad. Thanks. Probably I will try to write to Vim's mailing list as well as contact NeoVim developers, probably this feature will appear in the future.. – Dmitry Frank Mar 23 '15 at 13:00
  • Unless you develop and submit a complete patch, you'd have to be very patient to get this into Vim; the Todo list is endlessly long, unfortunately. – Ingo Karkat Mar 23 '15 at 13:08
-1

As you already pointed out, vim cannot distinguish if you're pressing tab to indent or because you're trying to align text, so is not possibile to automatize the behaviour you want.

Closest thing you can do is to try to play with softtabstop and different values for tabstop, but this way you get the reverse of what you asked for: pressing a tab is going to insert as much spaces possibile before using a tab.

On a side note, if you want your code to always look like you intended, you could try directly setting expandtab.

Spaces always look the same, so

{
.........long a = 1,
..............b = 2,
..............c = 3;
}

is how your code will always appear.

Mariano Macchi
  • 242
  • 1
  • 7
  • It's not about "pressing tab", it's about **auto**-indentation. There clearly **is** a way to distinguish between alignment and indentation, but Vim doesn't do that. As to softtabstop, thanks for the suggestion, but I don't like this approach. – Dmitry Frank Mar 23 '15 at 12:56
  • As to expandtab, it makes Vim never use tabs (insert only spaces). This is the approach I use these days in my projects, but it's not what I want to achieve in my question. – Dmitry Frank Mar 23 '15 at 13:05
  • I only pointed it out just in case, since what you asked for cannot be achieved and spaces are an easy way to keep code appearance regardless of indentation and alignment, and this was one of your main concerns. – Mariano Macchi Mar 23 '15 at 13:13