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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
" Heuristically set expandtab and shiftwidth options
"
" Modified version of vim-sleuth:
" - tabstop is not set, it's up to user to set it
" - check maximum of 32 lines, instead of 1024
" - check maximum 6 files, instead of 20
" - check maximum of 2 filer per directory level, instead of 8
" - check maximum of 3 directory levels
" - check only to the nearest .git, .hg, or .svn directory
" - globs are concatenated for performance
if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'autoindent') != -1
finish
endif
if exists("g:loaded_polyglot") || v:version < 700 || &cp
finish
endif
let g:loaded_sleuth = 1
let g:loaded_polyglot = 1
" Makes shiftwidth to be synchronized with tabstop by default
if &shiftwidth == &tabstop
let &shiftwidth = 0
endif
function! s:guess(lines) abort
let options = {}
let ccomment = 0
let podcomment = 0
let triplequote = 0
let backtick = 0
let xmlcomment = 0
let heredoc = ''
let minindent = 10
let spaces_minus_tabs = 0
for line in a:lines
if !len(line) || line =~# '^\W*$'
continue
endif
if line =~# '^\s*/\*'
let ccomment = 1
endif
if ccomment
if line =~# '\*/'
let ccomment = 0
endif
continue
endif
if line =~# '^=\w'
let podcomment = 1
endif
if podcomment
if line =~# '^=\%(end\|cut\)\>'
let podcomment = 0
endif
continue
endif
if triplequote
if line =~# '^[^"]*"""[^"]*$'
let triplequote = 0
endif
continue
elseif line =~# '^[^"]*"""[^"]*$'
let triplequote = 1
endif
if backtick
if line =~# '^[^`]*`[^`]*$'
let backtick = 0
endif
continue
elseif &filetype ==# 'go' && line =~# '^[^`]*`[^`]*$'
let backtick = 1
endif
if line =~# '^\s*<\!--'
let xmlcomment = 1
endif
if xmlcomment
if line =~# '-->'
let xmlcomment = 0
endif
continue
endif
" This is correct order because both "<<EOF" and "EOF" matches end
if heredoc != ''
if line =~# heredoc
let heredoc = ''
endif
continue
endif
let herematch = matchlist(line, '\C<<\W*\([A-Z]\+\)\s*$')
if len(herematch) > 0
let heredoc = herematch[1] . '$'
endif
let spaces_minus_tabs += line[0] == "\t" ? 1 : -1
if line[0] == "\t"
setlocal noexpandtab
return 1
elseif line[0] == " "
let indent = len(matchstr(line, '^ *'))
if indent % 2 == 0 && indent < minindent
let minindent = indent
endif
endif
endfor
if minindent < 10
setlocal expandtab
let &shiftwidth=minindent
return 1
endif
return 0
endfunction
function! s:detect_indent() abort
if &buftype ==# 'help'
return
endif
if s:guess(getline(1, 32))
return
endif
let pattern = sleuth#GlobForFiletype(&filetype)
if len(pattern) == 0
return
endif
let pattern = '{' . pattern . ',.git,.svn,.hg}'
let dir = expand('%:p:h')
let level = 3
while isdirectory(dir) && dir !=# fnamemodify(dir, ':h') && level > 0
" Ignore files from homedir and root
if dir == expand('~') || dir == '/'
return
endif
for neighbor in glob(dir . '/' . pattern, 0, 1)[0:level]
" Do not consider directories above .git, .svn or .hg
if fnamemodify(neighbor, ":h:t")[0] == "."
return
endif
if neighbor !=# expand('%:p') && filereadable(neighbor)
if s:guess(readfile(neighbor, '', 32))
return
endif
endif
endfor
let dir = fnamemodify(dir, ':h')
let level -= 1
endwhile
endfunction
setglobal smarttab
augroup polyglot
autocmd!
autocmd FileType * call s:detect_indent()
augroup END
|