File: detectindent.vim

package info (click to toggle)
vim-scripts 20080722-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 4,352 kB
  • ctags: 2,300
  • sloc: perl: 451; sh: 370; xml: 95; makefile: 25
file content (127 lines) | stat: -rw-r--r-- 3,922 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
" Name:          detectindent (global plugin)
" Version:       1.0
" Author:        Ciaran McCreesh <ciaranm at gentoo.org>
" Updates:       http://dev.gentoo.org/~ciaranm/vim/
" Purpose:       Detect file indent settings
"
" License:       You may redistribute this plugin under the same terms as Vim
"                itself.
"
" Usage:         :DetectIndent
"
"                " to prefer expandtab to noexpandtab when detection is
"                " impossible:
"                :let g:detectindent_preferred_expandtab = 1
"
"                " to set a preferred indent level when detection is
"                " impossible:
"                :let g:detectindent_preferred_indent = 4
"
" Requirements:  Untested on Vim versions below 6.2

fun! <SID>IsCommentStart(line)
    " &comments isn't reliable
    if &ft == "c" || &ft == "cpp"
        return -1 != match(a:line, '/\*')
    else
        return 0
    endif
endfun

fun! <SID>IsCommentEnd(line)
    if &ft == "c" || &ft == "cpp"
        return -1 != match(a:line, '\*/')
    else
        return 0
    endif
endfun

fun! <SID>DetectIndent()
    let l:has_leading_tabs            = 0
    let l:has_leading_spaces          = 0
    let l:shortest_leading_spaces_run = 0
    let l:longest_leading_spaces_run  = 0

    let l:idx_end = line("$")
    let l:idx = 1
    while l:idx <= l:idx_end
        let l:line = getline(l:idx)

        " try to skip over comment blocks, they can give really screwy indent
        " settings in c/c++ files especially
        if <SID>IsCommentStart(l:line)
            while l:idx <= l:idx_end && ! <SID>IsCommentEnd(l:line)
                let l:line = getline(l:idx)
                let l:idx = l:idx + 1
            endwhile
            let l:idx = l:idx + 1
            continue
        endif

        let l:leading_char = strpart(l:line, 0, 1)

        if l:leading_char == "\t"
            let l:has_leading_tabs = 1

        elseif l:leading_char == " "
            " only interested if we don't have a run of spaces followed by a
            " tab.
            if -1 == match(l:line, '^ \+\t')
                let l:has_leading_spaces = 1
                let l:spaces = strlen(matchstr(l:line, '^ \+'))
                if l:shortest_leading_spaces_run == 0 ||
                            \ l:spaces < l:shortest_leading_spaces_run
                    let l:shortest_leading_spaces_run = l:spaces
                endif
                if l:spaces > l:longest_leading_spaces_run
                    let l:longest_leading_spaces_run = l:spaces
                endif
            endif

        endif

        let l:idx = l:idx + 1
    endwhile

    if l:has_leading_tabs && ! l:has_leading_spaces
        " tabs only, no spaces
        set noexpandtab
        if exists("g:detectindent_preferred_tabsize")
            let &shiftwidth  = g:detectindent_preferred_indent
            let &tabstop     = g:detectindent_preferred_indent
        endif

    elseif l:has_leading_spaces && ! l:has_leading_tabs
        " spaces only, no tabs
        set expandtab
        let &shiftwidth  = l:shortest_leading_spaces_run

    elseif l:has_leading_spaces && l:has_leading_tabs
        " spaces and tabs
        set noexpandtab
        let &shiftwidth = l:shortest_leading_spaces_run

        " mmmm, time to guess how big tabs are
        if l:longest_leading_spaces_run < 2
            let &tabstop = 2
        elseif l:longest_leading_spaces_run < 4
            let &tabstop = 4
        else
            let &tabstop = 8
        endif

    else
        " no spaces, no tabs
        if exists("g:detectindent_preferred_tabsize")
            let &shiftwidth  = g:detectindent_preferred_indent
            let &tabstop     = g:detectindent_preferred_indent
        endif
        if exists("g:detectindent_preferred_expandtab")
            set expandtab
        endif

    endif
endfun

command! -nargs=0 DetectIndent call <SID>DetectIndent()