codeblog code is freedom — patching my itch

March 9, 2007

detecting space-vs-tab indentation type in vim

Filed under: General,Ubuntu — kees @ 10:36 am

I edit a lot of other people’s code. Dealing with indenting depth has always plagued me, and I’ve tried all sorts of things to try to address it, but the “real” problems I have are when tabs are mixed into code.

I personally use “4 spaces” for code indentation, and if I’m working on code that uses 8, I just hit “tab” twice, and if I’m working on code that uses 2, I can just backspace over the 2-too-many spaces. When the code has actual tabs, things break. When the code has a mix of tabs and spaces, it becomes a serious head-ache.

I wrote some vim insanity to detect which indentation type was being used “the most” in a given source file. If anyone has a simpler way to solve this (without switching to a different editor), I’m all ears. What follows are some bits from my .vimrc.

First, my space-indentation defaults:

set noai ts=4 sw=8 expandtab

Next, Makefiles and debian/rules files always use tabs, so I have a base set of overrides:

" Makefile sanity
autocmd BufEnter ?akefile* set noet ts=8 sw=8
autocmd BufEnter */debian/rules set noet ts=8 sw=8

Finally, define a function that compares the number of lines that start with a tab to those that start with a space. If the tabs outnumber the spaces, disable my defaults, and don’t expand tabs:

function Kees_settabs()
    if len(filter(getbufline(winbufnr(0), 1, "$"), 'v:val =~ "^\\t"')) > len(filter(getbufline(winbufnr(0), 1, "$"), 'v:val =~ "^ "'))
        set noet ts=8 sw=8
    endif
endfunction
autocmd BufReadPost * call Kees_settabs()

© 2007, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

6 Comments

  1. “When the code has actual tabs, things break.” — unless (as your later configuration handles it too) you keep it tabs-only. The only scary (and horribly broken) case is the mixture of tabs and spaces, which appears as the first (and recommended!!!) method in the VIM documentation about ts…

    Trick: set ts, sts, sw all to the same number, and to a number you prefer (I see you use 4 unit wide indentation; so in your case, 4), and of course noet, and the tabs will be just as safe as with the number set to 8, just displayed differently.

    I personally use tabs (one character = one indentation, seems pretty logical to me really) and made sure that at least VIM users don’t mess my files up, so I preemptively set a magic comment with the above trick (and default it to 4).

    Comment by Ralesk — March 9, 2007 @ 11:18 am

  2. Audacity uses three spaces. The story behind this is that Josh wanted four and I wanted two. Or was it the other way around? In any event, we decided to compromise on three, and neither of us seemed to mind. Which is kind of funny looking back on it, because I’ve never found any other code with three indents anywhere else!

    Anyway, we put the following “magic” at the bottom of all of our source files, which then forces all vim and emacs users to automatically go into 3-spaces mode when editing that file. If only there was magic like that for MS Visual Studio…

    // Local Variables:
    // c-basic-offset: 3
    // indent-tabs-mode: nil
    // End:
    //
    // vim: et sts=3 sw=3

    Comment by Dominic Mazzoni — March 9, 2007 @ 10:55 pm

  3. I personally think that it’s better to set softabstop to 4, and keep tabstop at its default value of 8.

    Comment by Marius Gedminas — March 10, 2007 @ 7:07 am

  4. The following vim script is very useful, it auto-detects from the current file the indentation settings.

    http://www.vim.org/scripts/script.php?script_id=1171

    Comment by bboissin — March 10, 2007 @ 7:23 am

  5. You’ll almost certainly find life easier on Unix and Unix-like systems if you have ts=8 sw=4, and either use control-T and control-D for indenting instead of tab and backspace, or do
    :map! ^V^I ^V^T

    Tabs on MS Windows are often set to be equivalent to 4 spaces, unfortunately, and for those :set ts=4 sw=4

    If you have sw set right you can use the = operators, e.g. >% to indent a loop or

    Comment by Liam Quin — March 15, 2007 @ 3:08 pm

  6. @tabs, see all characters, even invisible.

    Comment by cob — January 24, 2013 @ 9:08 pm

Powered by WordPress