Vim Tips Wiki
Advertisement
Tip 1592 Printable Monobook Previous Next

created February 16, 2008 · complexity basic · author Metacosm · version 7.0


You can set the 'expandtab' (abbreviated to 'et') option so each tab that you type is converted to an equivalent number of spaces. And you can use the :retab command to convert all existing tabs to spaces. You can do both in one command:

:set et|retab

You can also convert spaces to tabs:

:set noet|retab!

Both of the above examples should be used with caution. They convert all sequences, even those that might be in a "quoted string like this".

This tip shows how to convert only the indents at the left margin. Any spaces or tabs after the first non-white character are not affected.

Super retab

Use the following command to define a new SuperRetab command. You could enter this in Vim, or put it in your vimrc:

:command! -nargs=1 -range SuperRetab <line1>,<line2>s/\v%(^ *)@<= {<args>}/\t/g

For example, you may have a code snippet which uses two-space indents, and you want to entab the indents (convert each leading group of two spaces to a tab). To do this, visually select the code (press V then j), then enter:

:'<,'>SuperRetab 2

The above command would change:

  for {
    that;
  }

to the following ("|-------" represents a tab):

|-------for {
|-------|-------that;
|-------}

The command :SuperRetab 5 would give the same result from the following selected text:

     for {
          that;
     }

Alternative

An alternative super retab procedure is to use the following two commands:

:command! -range=% -nargs=0 Tab2Space execute "<line1>,<line2>s/^\\t\\+/\\=substitute(submatch(0), '\\t', repeat(' ', ".&ts."), 'g')"
:command! -range=% -nargs=0 Space2Tab execute "<line1>,<line2>s/^\\( \\{".&ts."\\}\\)\\+/\\=substitute(submatch(0), ' \\{".&ts."\\}', '\\t', 'g')"

The above defines a Tab2Space and a Space2Tab command that convert leading whitespace (spaces and tabs that are not at the beginning of a line are not affected). These commands use the current 'tabstop' (abbreviated as 'ts') option.

Examples:

" Convert all leading spaces to tabs (default range is whole file):
:Space2Tab
" Convert lines 11 to 15 only (inclusive):
:11,15Space2Tab
" Convert last visually-selected lines:
:'<,'>Space2Tab
" Same, converting leading tabs to spaces:
:'<,'>Tab2Space

Comments

I‘m using Python and have to switch from Tabs to spaces while loading and vice-versa while saving, as the project prefers tabs for some reason, but I want to edit the files using spaces.

It‘s easy to convert all tabs to spaces, but vice-versa it‘s a hard job. Searching for sequences of 4 left-margin-spaces and replacing them with tabs does not work, as it might convert too many spaces. Example: (-\t- is a tab)

def foobar():
    mylist = ['el1',
              'el2',
             ]
print "Foo"

Using retab or something similar I would get the following:

def foobar():
-\t-mylist = ['el1',
-\t--\t--\t-  'el2',
-\t--\t--\t- ]
print "Foo"

But I want this one:

def foobar():
-\t-mylist = ['el1',
-\t-          'el2',
-\t-         ]
print "Foo"

So… Python has indent levels, if a line ends with a ':' char (outside of comments of course), the indent level raises by one and the following lines have a new tab. If there is another ':$', the following lines start with two tabs etc. These spaces should be converted to tabs, but no more.

An indent level decreases, if there is not enough space, ie. there are not enough spaces to be converted into tabs. In the example above the indent level was zero at the beginning, than increases to one because of the ':' and decreases in the last line because of a lack of leading spaces.

I hope you guys can help me here, I don’t have much experience with VimL and am not able to do it myself, but I suggest some iterative function could work here.

Thanks, Keba.

Advertisement